雖然考研初試27號就結(jié)束了,現(xiàn)在已經(jīng)過去了三十多天,但是看了看我只看了七八十頁的計算機網(wǎng)絡(luò),感覺再浪下去要把自己腿皮斷了,開始復(fù)試的積極準(zhǔn)備階段吧。
1.31:
下載安裝codeblocks并實現(xiàn)調(diào)試使用(有一說一這個下載速度是真的sloooooooooooooooooow)
基本等于沒干什么事情吧,順手把巨人第一季下載了,這個倒是費了蠻大功夫的。
2.1:
今日重學(xué)了C語言(黃迪明 1`59 直到三目運算符)
下面是廢話筆記時間:
編程四大階段:需求分析,設(shè)計開發(fā),編寫文檔,以及最后的維護(hù)。
算法:有輸入,有輸出,有窮性,確定性,高效性。
程序結(jié)構(gòu):順序,循環(huán),選擇,調(diào)用。
標(biāo)識符:只能由字母,下劃線和數(shù)字構(gòu)成,并且第一個字符只能是字母或者下劃線。
關(guān)鍵字統(tǒng)稱為保留字。
編輯(.c 類型文件)
編譯,編譯完成后生成.obj 類型文件
連接,連接完成后生成 exe 可執(zhí)行文件
沒有標(biāo)注的統(tǒng)一認(rèn)為是有符號數(shù) signed
float 四字節(jié) double 8字節(jié) long double 16字節(jié)(真稀奇啊)
char 一個字節(jié)
如果一個常量后面加上一個字母u或者U 表示無符號數(shù)常量,同樣如果加上的是一個l或者L,就表示是一個long型,都加同理。
.56以及96. 都是合理的浮點數(shù)表示方式
浮點數(shù)通常還可以使用指數(shù)的方式來表示,例如1E8,2.5E-6 但是要求E前后必須有數(shù)字的同時,指數(shù)部分只能為整數(shù)。
浮點常量默認(rèn)為double,如果加上f或者l 則具體變換即可。
至于浮點數(shù)在計算機內(nèi)的具體表示,由于涉及到二進(jìn)制整數(shù)位1的舍棄,所以比較復(fù)雜,教材這里并沒有詳細(xì)說明。
C語言編譯程序通常會在字符串的末尾自動加上 ‘\0’ 作為字符串的結(jié)束標(biāo)志。
連等賦值不被允許,形如int i=j=k=50;
自增運算符只能用于變量,不可運用于常量和表達(dá)式
int main()
{
int a=3;
printf("%d\n",-a++);
printf("%d\n", a);
}
自增運算符號存在著陷阱,如上代碼。首先由于++不可對表達(dá)式使用,那么只能是a++再取反,這時候由于++后綴的特性,輸出的值最終是-3 第二個輸出的a則是4
PS:此特性對C++同理
然后又是垃圾運算符優(yōu)先級時間,此處直接把隔壁C++的貼過來吧
后置++ --要比前置++ --優(yōu)先級要高一點,不過應(yīng)該不會考這種shit東西吧 (好在++i++是違法的)
- :: 和()
- [] . -> 后置++ 后置-- 類型轉(zhuǎn)換
- 前置++ ,前置--,大量一元邏輯運算符號(~)
- .* ->*
- 乘除取余
- 加減
- 左移右移
- 大于 小于 大于等于 小于等于
- 等于和不等于
- & ^ |(三者優(yōu)先級不等嗷 從高到底)
- && ||(同上不等
- 三元運算符號?: 它后面是一大堆賦值等號懶得寫了
值得一提的是 int a=b=c=50: 的確不合法,但是int a,b,c; a=b=c=50是合法的,前者的主要錯誤只是在于變量的定義和使用現(xiàn)后順序存在問題。
邏輯運算只在乎最后的結(jié)果是不是0 如果是0就是假 否則統(tǒng)一認(rèn)為是真并將結(jié)果作為1
運算順序總是十分復(fù)雜且難以記憶的,總結(jié)就是 優(yōu)先后++ -- 然后是前++ 前--
再然后是 乘除取余 然后加減 然后大小比較 然后等于不等于比較 再然后邏輯運算(其中位邏輯運算大于普通的邏輯運算 且最高的是~ 依次是& ^ | ),最后是賦值運算和其他的高級賦值運算。
補碼等于反碼+1
按位與 &
按位或 |
按位取反 ~
按位異或 ^
如果i與j進(jìn)行按位與,但是兩個數(shù)字的位數(shù)不同,i為long j為int,那么會在右端對齊的同時依據(jù)j的符號在左側(cè)補上合適的0或者1
異或 指的是 如果兩個位相同則為0 如果不同則為1
按位與將特定位置置為0 或則是置為1 異或則可以將特定位取反
因為與1異或 則一定會與原來的只相反 而與0異或則保持原數(shù)值不變
位邏輯運算符號針對二進(jìn)制位,其只可以運用在整型上,
此處指出位邏輯運算符號和邏輯運算符號的區(qū)別:
- 前者針對二進(jìn)制位,后者針對表達(dá)式,前者只可以運用在整形上,且需要計算具體數(shù)值,后者只需要判斷真假。
- 前者的兩個運算對象可以交換,后者由于運算的不完全性,一旦運算出確定結(jié)果就不會再向下運算,因此后者運算對象交換會可能會導(dǎo)致程序后續(xù)結(jié)果輸出不同。
2.2&&2.3:
兩天早上摸魚,統(tǒng)一睡到大天亮。
重修C語言之從60~86頁第二章測試題
這兩天摸魚比較嚴(yán)重 昨天抽空上了個黃金 今天看了半天大江大河 希望后面幾天能加把勁吧 我也是加把勁騎士了。
三目運算符號的運算順序為從右到左
P60的 例題2-2 是一個很好的例子 首先三目運算符號先算表達(dá)式1 然后才會考慮計算表達(dá)式2或表達(dá)式3 這將導(dǎo)致最后i的值不同,同時注意 i>=j>=k的運算結(jié)果。
神奇的逗號表達(dá)式 i=35,i2; 該語句i=15 但是整個表達(dá)式的值為30 即
j=(i=3 * 5,i * 2)的結(jié)果j=30,i=15;
float類型數(shù)據(jù),即使是兩個float類型數(shù)據(jù)相加,仍然都將其轉(zhuǎn)化為double類型進(jìn)行運算。
數(shù)據(jù)的自動類型轉(zhuǎn)換,其中是針對兩個操作數(shù)逐步逐步轉(zhuǎn)換的,而不是一次性統(tǒng)一轉(zhuǎn)換,也就是6.0/4+5.5 不等于 6/4+5.5 的原因。
三目運算符號 單目運算符以及賦值運算符都是從右到左,其中務(wù)必需要注意的就是三目運算符的運算方向。
可以確定運算方向是從左到右的三個運算符分別是|| && 和,
其可以舉一個非常的例子如下:
int main()
{
int a,b,c;
a=0;
b=1;
c=0;
if(a++||b++&&c++)
{
printf("這個式子成立");
}
printf("%d,%d,%d",a,b,c);
}
以及
int main()
{
int a,b,c;
a=0;
b=0;
c=0;
if(a++||b++&&c++)
{
printf("這個式子成立");
}
printf("%d,%d,%d",a,b,c);
}
我們可以明確的看到,如果三者全為0時,只會判斷a++和b++,但是b不為0時則會計算c++,我們可以知道c++是最后運算的,如果設(shè)置a=1,那么只有a的數(shù)值發(fā)生了變化,這是由于盡管||運算的優(yōu)先級沒有&&高,但是由于強制從左往右算,其式子等同于i++||(b++&&c++) ,這就是關(guān)鍵,程序依然會先判斷i++再考慮運算右側(cè)的內(nèi)容。
轉(zhuǎn)義字符中 \101 中這個101指的是八進(jìn)制
putchar() 函數(shù)輸出int 變量時會自動轉(zhuǎn)化為ascil碼
printf函數(shù)輸出樣式 %d %o(八進(jìn)制) %x(16進(jìn)制) %u(無符號十進(jìn)制)
%f (浮點數(shù) 自帶六位小數(shù)) %e (指數(shù)形式) %g (數(shù)值最小寬度)
修飾符號
l指的是長整型
m指定數(shù)據(jù)輸出的寬度(指的是域?qū)挘?br>
.n 對實數(shù)型數(shù)據(jù)指定輸出n位小數(shù)或者輸出字符串的前n個字符
+表示輸出帶符號數(shù)
- 左對齊
意思也就是如果使用m 指定數(shù)據(jù)輸出的寬度,如果輸出寬度不足m 左邊補上空格,可以做到右側(cè)對齊的效果,左對齊用- 實現(xiàn)即可,其和C++ left right差不多,都需要注意如果一旦輸出實際數(shù)字大于指定長度,則無視指定長度。
%g的優(yōu)勢就在于合理的選擇%f還是%e,將輸出數(shù)值的長度做到最小,其中比較愚蠢的東西就是C++的float的精度并做不到完全的精確,正如234.896存儲的結(jié)果輸出是234.895996一樣,只是一個近似值而不是完全相等的確切值。
輸出格式之 %m.ns 如果n>m那么以n為準(zhǔn)確保n位正確輸出,同時m>n時同樣保證右對齊,并且左側(cè)用空格補齊。
%后面只有XSG可以不區(qū)分大小寫,我想這么細(xì)節(jié)的內(nèi)容應(yīng)該不會考吧。
如果時prinf內(nèi)有算式計算,通常是從右往左開始計算。
如果想要輸出% 需要連續(xù)使用兩個%
但是單雙引號則是 \' 和 \" 的方式來輸出
getchar() 我又想起來當(dāng)初被這個東西支配的恐懼 這個東西會將空格和回車作為標(biāo)準(zhǔn)輸入接受,反正非常讓人發(fā)指這個東西。
下面這個又是神經(jīng)病的東西,這本書講的實在是太細(xì)了,給大佬磕頭了。這個東西對空格的要求非常奇怪,就是scanf你填充空格的地方?jīng)]有空格不會出現(xiàn)異常,但是如果沒有填充空格的地方你輸入空格,就會炸。

其次如果是浮點型數(shù)據(jù)輸入,是不可以使用m.nf的方式來控制輸入的,也就是你不可以指定小數(shù)點后位數(shù),但是可以通過僅使用m的方式確定小數(shù)的輸入整個長度,而不能控制其輸入的小數(shù)點長度。
%*4d 這個 * 用來忽視接下來的輸入,也就是這個輸入請求被屏蔽。
2.4:
今日完成C語言第二章課后習(xí)題
以及第三章部分內(nèi)容 總的來說看到了103頁
規(guī)范的指數(shù)形式要求 小數(shù)部分小數(shù)點前有且只有一位非零數(shù)字。
且指數(shù)形式中,指數(shù)部分只能是整數(shù),否則認(rèn)為不合法。
負(fù)數(shù)取余運算,這里涉及到一個沒講到的知識點,負(fù)數(shù)取余C語言的余數(shù)和被除數(shù)同號,這樣同樣也可以判斷負(fù)數(shù)除法的機制,其都是向0方向收縮。
三目運算符的優(yōu)先級大于賦值運算
無論是正負(fù)數(shù) 移位操作都等于直接乘除對應(yīng)的值。
scanf 讀入%md時 如果讀入的數(shù)據(jù)不足m 則直接忽視m的要求即可
2.5:
今日計劃C語言到150~160頁 順便回去看看一直沒看的計算機網(wǎng)絡(luò) 唉
以下代碼可以實現(xiàn)循環(huán)讀入,直到a為234為止跳出循環(huán)
void main ()
{
int a=0;
for(a=0;a!=234;)
{
scanf("%d",&a);
}
}
九九乘法表很簡單 這里就不再贅述
下面是 十進(jìn)制轉(zhuǎn)化為2進(jìn)制
void main ()
{
int a;
scanf("%d",&a);
printf("%x\n",a);
for(int i=0;i<32;i++)
{
unsigned int temp=0; //務(wù)必記住 這里一定要設(shè)置為unsigned 數(shù)
//否則無法得到正確結(jié)果 因為負(fù)數(shù)移位編譯環(huán)境不同結(jié)果可能不同
temp=a&0x80000000;
printf("%1x",temp>>31);
if(i%4==3) //此處是為了每四位輸出一個空格方便校驗
{
printf(" ");
}
a<<=1;
//printf(" %x\n",a);
}
}
當(dāng)然了 采用標(biāo)準(zhǔn)的公式法也是可以的,但是需要遞歸。
void function(int a)
{
int temp=a%2;
a=a/2;
if(a!=0)
{
function(a);
}
printf("%d",temp);
}
void main ()
{
int a;
scanf("%d",&a);
printf("%x\n",a);
if(a>=0)
{
function(a);
}
else{
// 如果是負(fù)數(shù)有點麻煩 、
// 需要數(shù)組 如果是c++我直接就寫上了 以后有空再寫吧
}
}
%04x 表示不足4位用0填充
判斷是否在某一位包含特定數(shù)字的標(biāo)準(zhǔn)寫法
void main ()
{
int a;
scanf("%d",&a);
printf("a=%d\n",a);
for(int i=0;i<=100;i++)
{
int j=i;
int flag1=1,flag2=1;
while(flag1&&j>0) //關(guān)鍵就在這里,%10判斷是否相等,不相等再/10 即可
{
if(j%10==a)
{
flag1=0;
break;
}
j/=10;
}
if(flag1==0)
{
j=i;
j*=j;
while(flag2&&j>0)
{
if(j%10==a)
{
flag2=0;
break;
}
j/=10;
}
}
if(flag2==0)
{
printf("%d, %d\n",i,i*i);
}
}
}
下運算為輸出十六進(jìn)制從右到左的第k位
void main ()
{
int a;
unsigned b;
scanf("%d",&a);
b=(unsigned)a;
printf("%x\n",b);
int k;
scanf("%d",&k);
b>>=4*(k-1);
b=b&0xf;
printf("%x",b);
}
continue語句 將推轉(zhuǎn)出循環(huán)結(jié)構(gòu),忽略continue后面的語句,直接下一次循環(huán),在while語句則之間進(jìn)去檢測控制表達(dá)式,而for語句則是直接跳轉(zhuǎn)語句3,然后進(jìn)行判斷
2.6:
顯然 2.5號的任務(wù)和自己的執(zhí)行力相比是不切實際的,不知道今天能不能補上2.5號的坑。
goto語句無法實現(xiàn)由循環(huán)外跳轉(zhuǎn)到循環(huán)內(nèi)的效果,此不合法。
輸出日歷例題
#include<stdio.h>
void main ()
{
int year,one_month,one_day,xingqi;
scanf("%d %d %d %d",&year,&one_month,&one_day,&xingqi);
int flag=(year%4==0&&year%100!=0)||(year%400==0);
int inputmonth;
printf("---------------------\n");
scanf("%d",&inputmonth);
int start=1,end=0;
int month[12]={31,28+flag,31,30,31,30,31,31,30,31,30,31};
for(int i=0;i<inputmonth-1;i++)
{
start+=month[i];
}
for(int i=0;i<inputmonth;i++)
{
end+=month[i];
}
printf("%d,%d\n",start,end);
for(int i=0;i<7;i++)
{
printf(" 星期%d",i+1);
}
printf("\n");
int start_day=(start+xingqi-1)%7;
if(start_day==0)
{
start_day=7;
}
printf("%*d",(start_day)*9,1); //這個我想這本書沒有教過這個東西的用法,
//實際上是(start_day)*9是 *的內(nèi)容 也就是后面兩個數(shù)據(jù)一個用來指定輸出寬度
for(int i=2;i<=end-start+1;i++)
{
//
printf("%9d",i);
start_day++;
if(start_day%7==0)
{
printf("\n");
}
}
}
實際效果:

不使用原代碼的主要原因是原代碼實在是寫的太復(fù)雜。。。。。
圖書管理系統(tǒng)就不寫了,實在沒什么實現(xiàn)的難度,就不浪費自己時間了。
課后題3.7: 看成加減乘除了 那還是比較麻煩的,通常是用棧來做,但是畢竟不像C++可以直接stack懟臉,還要自己弄,只有加減法就很簡單了,如下(好像要求是浮點數(shù),算了就這樣吧)
void main ()
{
int sum1;
char yunsuan;
scanf("%d",&sum1);
char oldyunsuan='#';
while((yunsuan=getchar())!=';')
{
//只要運算符號不是;就繼續(xù)正常運算
int sum2;
scanf("%d",&sum2);
//此處獲得兩個運算符號
//printf("%d,%d",sum1,sum2);
switch(yunsuan)
{
case '+':
sum1+=sum2;
break;
case '-':
sum1-=sum2;
break;
}
}
printf("%d",sum1);
}
3.8 (下次這種題目還是不寫了吧。。)
void main ()
{
double a;
scanf("%lf",&a);
double sum=0;
for(int i=0;i<=15;i++)
{
double sumtempfenmu=1;
for(int j=1;j<=i;j++)
{
sumtempfenmu*=j;
}
sum+=pow(a,i)/sumtempfenmu;
}
printf("%f",sum);
}
質(zhì)數(shù) 畢竟早就忘了怎么分配動態(tài)數(shù)組了 大學(xué)到底學(xué)了個啥玩意
你是不是nt
#include<stdio.h>
void main ()
{
//經(jīng)典判斷質(zhì)數(shù)
//去年復(fù)試就腦癱了 1不是質(zhì)數(shù)哥哥
int a[50];
int count=0;
for(int i=2;i<=100;i++)
{
if(count==0) //如果count=0顯然這個數(shù)一定是質(zhì)數(shù)
{
a[count++]=i;
}
else
{
int flag=1;
for(int j=0;j<count;j++)
{
if(i%a[j]==0) //如果沒有余數(shù)一定不是質(zhì)數(shù)
{
flag=0;
break;
}
}
if(flag)
{
a[count++]=i;
}
}
}
for(int i=0;i<count;i++)
{
printf("%d\n",a[i]);
}
}
3.17 移位操作 這題其實有點意思
我是用for循環(huán)做到每步移位的 看了一眼答案 其實可以一步到位
#include<stdio.h>
void main ()
{
int i,j;
scanf("%d %d",&i,&j);
printf("%x,%d\n",i,j);
//為了簡單起見我們統(tǒng)一認(rèn)為i是無符號數(shù) 否則何來循環(huán)移位這一說
unsigned int temp=i;
if(j>0) //將i徐娜換左移
{
for(int z=0;z<j;z++) //左移n位
{
unsigned int single=temp&0x80000000;
single>>=31;
temp<<=1;
temp=temp|single;
}
}
else //循環(huán)右移
{
for(int z=0;z<j;z++)
{
unsigned int single=temp&0x00000001;
single<<=31;
temp>>=1;
temp=temp|single;
}
}
printf("%x",temp);
}
如果不采用循環(huán)則使用下列格式即可
#include<stdio.h>
void main ()
{
int i,j;
scanf("%d %d",&i,&j);
printf("%x,%d\n",i,j);
//為了簡單起見我們統(tǒng)一認(rèn)為i是無符號數(shù) 否則何來循環(huán)移位這一說
unsigned int temp=i;
if(j>0) //將i徐娜換左移
{
//如果循環(huán)左移 那么就需要截取最右側(cè)的j位
//最簡單的辦法就是將這個東西右移32-j位
unsigned temp2=temp>>(32-j);
temp<<=j;
temp=temp|temp2;
}
else //循環(huán)右移
{
j=-j; //先調(diào)整為個正數(shù)
unsigned temp2=temp<<(32-j);
temp>>=j;
temp=temp|temp2;
}
printf("%x",temp);
}
第三章完結(jié)。
2.6日總結(jié):
今日完成了第三章的復(fù)習(xí)132頁 課后題答案在51頁到66頁 進(jìn)度還是差很多 明天要出去,帶本計網(wǎng)看看吧,電腦就不帶了。
2.9:
C語言 黃(153頁)
靜態(tài)數(shù)組定義,在定義大小時,大小必須是一個常量表達(dá)式,也就是一個整形常量(實際上codeblocks 可以支持非常量實現(xiàn) vs則不可以)
也就是下面這個東西,本質(zhì)上時不符合C++/C規(guī)范的,但是部分編譯器也可以正確運行。
int p;
scanf("%d",&p);
int a[p];
如果初始化數(shù)組變量時省略數(shù)組大小,則自動默認(rèn)設(shè)置為初始化變量的個數(shù)。
二維數(shù)組,在全部賦值的情況下,可以省略第一維的定義長度,但是不可以省略第二維的定義長度。
要注意的是,看似這兩種賦值方法是等價的,但實際上組成的數(shù)組長度是不同的,并且后者如果沒有留出給 '\n' 的空間,還會導(dǎo)致編譯錯誤。

這里要指出的是codeblocks 所用的mingv編譯器非常的包容,大概娘化了也肯定是個大姐姐,即使你第二種方法越界了,也不會報編譯錯誤,但是vs則不行,大概是個銼刀吧。
C語言的scanf讀入字符串時不能包入類似分隔符和回車符的空白符號。
但是gets則可以成功的讀入空格字符,在遇到換行符時則會停止讀入。
除此之外,使用gets 或者 scanf中的%s讀入字符串時,不需要使用取地址符號,因為數(shù)組名本身就代表了數(shù)組首地址。
對于printf采用%s格式輸出時,則一旦遇到\0符號即立刻停止輸出,不論\0之后是否還有有意義內(nèi)容,而puts則會將字符串結(jié)束標(biāo)記的\0轉(zhuǎn)換為\n,實現(xiàn)自動換行。
接下來是大家并不喜聞樂見的字符串處理函數(shù):
- 字符串長度測量函數(shù) strlen
使用方法為 strlen(字符數(shù)組名) - 字符串復(fù)制函數(shù) strcpy
即將字符串2的所有字符一個一個復(fù)制到字符數(shù)組1中,直到遇到結(jié)束標(biāo)志“\0”為止,并且同時也寫入結(jié)束標(biāo)志。
strcpy(A,B) 其會將B的內(nèi)容復(fù)制到A中,
然后是常見錯誤:
word1=word2 編譯錯誤。
strncpy 可將字符串2的前n個字符復(fù)制到字符串1中。
strncpy(字符串1,字符串2,復(fù)制的字符個數(shù));
字符串連接函數(shù) strcat
strcat(數(shù)組一,數(shù)組二) 即取消第一個字符數(shù)組中的字符串的結(jié)束標(biāo)志 “\0”,把第二個字符串拼接到第一個字符串后面,并且把拼接的結(jié)果存放到第一個字符數(shù)組中。也就是整個過程中,第二個數(shù)組不會發(fā)生變化,而第一個則會成為拼接結(jié)果。
字符串比較函數(shù) strcmp
這個東西會將第一個字符串和第二個字符串進(jìn)行大小的比較:
如果兩個字符串相等,則返回0
如果1大于2,則返回一個正整數(shù)
如果1小于2,則返回一個負(fù)整數(shù)
strstr 用來查找一中是否有2的子串
strchr 用來查找一中是否有2這個字符
二者一旦查找到結(jié)果,返回第一個匹配對象以及其之后的所有字符。
atof atoi 將字符串轉(zhuǎn)化為浮點數(shù)和整數(shù)
itoa 將值轉(zhuǎn)化為字符串 特指整型
其有三個參數(shù) 第一個為轉(zhuǎn)化的整形數(shù)字,第二個為字符數(shù)組名,第三個參數(shù)為進(jìn)制。
2.12:
字符串電報轉(zhuǎn)換
#include<stdio.h>
#include<string.h>
void main ()
{
char worinige[100];
gets(worinige);
puts(worinige);
for(int i=0;i<strlen(worinige);i++)
{
if(worinige[i]>='A'&&worinige[i]<='Z')
{
//?′?a′óD′×???
worinige[i]=(worinige[i]-'A'+27)*3%52;
}
else if(worinige[i]<='z'&&worinige[i]>='a')
{
worinige[i]=(worinige[i]-'a'+1)*3%52;
}
}
for(int i=0;i<strlen(worinige);i++)
{
if(worinige[i]<=26)
{
worinige[i]=worinige[i]-1+'a';
}
else
{
worinige[i]=worinige[i]-27+'A';
}
}
puts(worinige);
}
定義數(shù)組時直接定義變量,并為變量分配了相應(yīng)的內(nèi)存空間,定義結(jié)構(gòu)體則類似于定義一個模板。
無法直接用scanf和printf輸出結(jié)構(gòu)體變量,但是可以相互之間用等號賦值。
務(wù)必要知道的是,如果結(jié)構(gòu)體內(nèi)有字符數(shù)組變量,那么scanf時不需要加上&,這點務(wù)須注意。
結(jié)構(gòu)體的初始化:
void main ()
{
struct wori{
int x;
int y;
}ppp={10,20};
printf("%d",ppp.x);
}
結(jié)構(gòu)體是可以在函數(shù)體內(nèi)定義的,并不是一定要定義成全局的。
使用哨兵標(biāo)記法,可以免去查找過程中每一步都要檢測數(shù)組是否越界的問題。
也就是設(shè)置A[0]為x,從后往前依次判斷即可。
void main ()
{
int a[10];
for(int i=1;i<10;i++)
{
scanf("%d",&a[i]);
}
int x;
scanf("%d",&x);
a[0]=x;
int i;
for(i=9;a[i]!=x;i--);
printf("%d",i);
}
折半查找 折半查找的注意之點在于while循環(huán)中判斷l(xiāng)eft和right大小時,二者應(yīng)當(dāng)是小于等于的關(guān)系。
#include<stdio.h>
#include<string.h>
void main ()
{
int a[10];
for(int i=0;i<10;i++)
{
scanf("%d",&a[i]);
}
int x;
scanf("%d",&x);
printf("-----------------------------------------\n");
int left=0,right=9;
int mid=(left+right)/2;
while(left<=right)
{
mid=(left+right)/2;
// printf("%d",a[mid]);
if(a[mid]<x)
{
left=mid+1;
}
else if(a[mid]>x)
{
right=mid-1;
}
else
{
printf("%d is the %d number",x,mid);
break;
}
}
}
直接插入排序
說實話我都忘記了這個東西怎么弄了
#include<stdio.h>
#include<string.h>
void main ()
{
int a[10];
for(int i=0;i<10;i++)
{
scanf("%d",&a[i]);
}
printf("-----------------------------------------\n");
for(int i=1;i<10;i++)
{
int temp=a[i];
int j;
//這個東西用來記錄當(dāng)前的值,因為一旦移位就會改變a[i]的值
for(j=i-1;j>=0;j--)
{
if(temp<a[j]) //如果當(dāng)前值較小
{
a[j+1]=a[j];
}
else
{
break;
}
}
//for循環(huán)停止后, 即表明temp大于當(dāng)前的a[j],那么temp適合的位置就是j+1
a[j+1]=temp;
}
printf("\n");
for(int i=0;i<10;i++)
{
printf("%d ",a[i]);
}
printf("\n");
}
這里有一個問題,其實就是哨兵問題,如果設(shè)置哨兵,那么a[0]就代替了temp的位置并且同時控制了for循環(huán)的結(jié)束,因為我比較反感數(shù)組不從0開始這個事情,就不寫了。
printf() 中%* 用來動態(tài)指定輸出寬度
scanf() 中%* 用來省略接下來的輸入
strstr函數(shù)
void main ()
{
char sp[50];
char pp[21];
gets(sp);
gets(pp);
puts(sp);;
puts(pp);
printf("%s",strstr(sp,pp)); //如果不匹配,則會返回null
}
strstr 字符串匹配
strctr 字符匹配
strcmp 字符比較
strcpy 字符復(fù)制
strncpy 字符前n位復(fù)制
strcat 字符拼接
字符串比較和賦值
當(dāng)然了 這個賦值是不必要的,完全可以用結(jié)構(gòu)體的等號直接賦值。
#include<stdio.h>
#include<string.h>
typedef struct student
{
char name[21];
}student;
void main()
{
student sts[10];
for(int i=0;i<10;i++)
{
char temp[21];
scanf("%s",temp);
int j;
for(j=i-1;j>=0;j--)
{
if(strcmp(temp,sts[j].name)<0)
{
strcpy(sts[j+1].name,sts[j].name);
}
else
{
break; //直接插入排序 務(wù)必不要忘記這個break;
}
}
strcpy(sts[j+1].name,temp);
for(int p=0;p<=i;p++)
{
puts(sts[p].name);
}
puts("-----------------------");
}
}
2.13:
第四章習(xí)題:
4.2: 開燈
#include<stdio.h>
#include<string.h>
void main()
{
int a;
scanf("%d",&a); //輸入a=10;
//因為數(shù)組大小必須設(shè)置為常量,C++還是寫成 int* p=new int[num];
//這樣比較好,但是C語言這樣寫是不行的,所以這里暫時就不寫動態(tài)構(gòu)造數(shù)組了。
int shuzu[10+1]={0};
for(int i=1;i<=a;i++)
{
for(int j=1;j<=a;j++)
{
if(i>=j&&i%j==0)
{
shuzu[i]++;
}
}
if(shuzu[i]%2==1)
{
printf("the %d light is open\n",i);
}
}
}
4.3:簡單選擇排序
#include<stdio.h>
#include<string.h>
void main()
{
//簡單選擇排序
int a[10];
for(int i=0;i<10;i++)
{
scanf("%d",&a[i]);
}
for(int i=0;i<10;i++)
{
int max=a[0];
int x=0;
for(int j=0;j<10-i;j++)
{
if(max<a[j])
{
max=a[j];
x=j;
}
}
int temp;
temp=a[10-i-1];
a[10-i-1]=max;
a[x]=temp;
}
for(int i=0;i<10;i++)
{
printf("%d ",a[i]);
}
}
4.4: n階幻方
#include<stdio.h>
#include<string.h>
typedef struct point
{
int x;
int y;
}point;
void main()
{
//4.4 幻方
//這里在這里我們設(shè)置為5 還是那個沒有教動態(tài)設(shè)置數(shù)組的問題
int a[7][7]={0};
//我們設(shè)置為7 答案設(shè)置為5 我們設(shè)置的大一點
int n=7;
point start;
start.x=0;
start.y=(0+n-1)/2;
int now=1;
while(now<=n*n)
{
a[start.x][start.y]=now;
now++;
//正常情況下x 應(yīng)該-- y應(yīng)當(dāng)++ 這樣才會往右上角移動
if(start.x==0&&start.y!=n-1)
{
//這表示這個點向上越界
start.x=n-1;
start.y++;
}
else if(start.y==n-1&&start.x!=0) //右側(cè)越界
{
start.x--;
start.y=0;
}
else if(start.x==0&&start.y==n-1)
{
start.x++;
}
else
{
printf("%d %d %d\n",start.x,start.y,now);
if(a[start.x-1][start.y+1]==0) //如果這個點沒有數(shù)
{
start.x--;
start.y++;
}
else
{
start.x++;
}
}
for(int i=0;i<=n-1;i++)
{
for(int j=0;j<=n-1;j++)
{
printf("%4d",a[i][j]);
}
printf("\n");
}
printf("\n");
}
for(int i=0;i<=n-1;i++)
{
for(int j=0;j<=n-1;j++)
{
printf("%4d",a[i][j]);
}
printf("\n");
}
}
4.5:
這題比較簡單,就不寫了 要注意的是strlen是不會把\n計算到字符串長度中的,這點還是要注意一下
4.6:
識別空格問題,判斷單詞個數(shù)的問題
這個東西判斷的要領(lǐng)就是只要是由空格變?yōu)榉强崭?就算作一個單詞
答案的寫法我看了半天,大概是統(tǒng)計新空格的個數(shù),他認(rèn)為每個單詞后面都有一個空格,所以要判斷最后的字符是不是空格。
#include<stdio.h>
#include<string.h>
void main()
{
char strings[1000];
gets(strings);
int lengths=strlen(strings);
int flag=1;
int count=0;
int i=0;
//我覺得一開始想的太復(fù)雜了
//我覺得設(shè)置flag 只需要統(tǒng)計flag從1變成0的次數(shù)就可以了
while(i<lengths)
{
if(strings[i]==' ') //flag=1變化為0 時計算一個字符 且初值設(shè)為1 可以防止開頭有空格或者沒空格的情況
{
flag=1;
}
else
{
if(flag==1)
{
count++;
flag=0;
}
}
i++;
//如果結(jié)尾有空格 由于flag只會從1變化為0 但是變化不回1 所以不會計數(shù)
}
printf("%d",count);
}

三點共線:
#include<stdio.h>
#include<string.h>
#include<math.h>
typedef struct point{
double x;
double y;
}point;
int equal(double x,double y)
{
if(fabs(x-y)<1e-7)
{
return 1;
}
else
{
return 0;
}
}
void main()
{
//學(xué)生管理系統(tǒng)我們就不寫了
point point1,point2,point3;
scanf("%lf%lf%lf%lf%lf%lf",&point1.x,&point1.y,&point2.x,&point2.y,&point3.x,&point3.y);
double length;
length=sqrt(pow((point1.x-point2.x),2)+pow((point1.y-point2.y),2));
printf("the length is %f\n",length);
if(equal(point1.x,point2.x))
{
//如果前兩個點豎向共線
//那么就不存在k值,所以就需要判斷是否三點共線
if(equal(point2.x,point3.x))
{
printf("a line and shuline\n");
}
else
{
printf("no a line\n");
}
}
else{
double k=(point1.y-point2.y)/(point1.x-point2.x);
double b=point1.y-k*point1.x;
double temp=point3.x*k+b;
printf("%f %f\n",k,b);
if(equal(temp,point3.y))
{
printf("a line\n");
}
else
{
printf("no a line\n");
}
}
}
4.10 分子彈問題
要注意分發(fā)子彈問題要同步發(fā)放。
這個我是用數(shù)組來額外存儲空間的,但是同樣可以只用一個int來代替這個數(shù)組。
void main()
{
int a[10]={10,2,8,22,16,4,10,6,14,20};
int flag=0;
int count=0;
while(flag==0)
{
int temp[10];
for(int i=0;i<10;i++)
{
temp[i]=a[i];
}
for(int i=0;i<10;i++)
{
if(temp[i]%2==1)
{
temp[i]++;
}
}
for(int i=0;i<10;i++)
{
a[i]=temp[i]/2+temp[(i+1)%10]/2;
}
count++;
flag=1;
for(int i=0;i<10;i++)
{
if(a[i]!=a[(i+1)%10])
{
flag=0;
}
}
for(int i=0;i<10;i++)
{
printf("%4d",a[i]);
}
printf("\n");
}
printf("分發(fā)次數(shù)為%4d\n",count);
}
如果使用int來代替數(shù)組,則需要反向思維,從后往前考慮(從前往后則無法實現(xiàn)),從后往前則不需要記錄這個數(shù)組的內(nèi)容,代碼如下:
void main()
{
int a[10]={10,2,8,22,16,4,10,6,14,20};
int flag=0;
int count=0;
while(flag==0)
{
int temp;
for(int i=0;i<10;i++)
{
if(a[i]%2==1)
{
a[i]++;
}
}
//首先重置為偶數(shù)才行
temp=a[9];
for(int i=9;i>0;i--)
{
a[i]=a[i]/2+a[i-1]/2;
}
a[0]=a[0]/2+temp/2;
flag=1;
count++;
for(int i=0;i<10;i++)
{
if(a[i]!=a[(i+1)%10])
{
flag=0;
}
}
for(int i=0;i<10;i++)
{
printf("%4d",a[i]);
}
printf("\n");
}
printf("the count is %4d\n",count);
}
4.11 保齡球問題:
實在不是很能理解這個題目和答案的關(guān)系,我個人傾向于原題是這么個邏輯:
(1) 若某一輪的第一次滾球就擊倒全部十個柱,則本輪不再滾球。(若是第十輪則還需另加兩次滾球)。該輪得分為本次倒柱數(shù) 10 與以后兩次滾球所擊倒柱數(shù)之和。
(2) 若某一輪的第一次滾球未擊倒十個柱,則可對剩下未倒的柱再滾球一次。如果這兩次滾球擊倒全部十個柱,則本輪不再滾球(若是第十輪則還需另加一次滾球),該輪得分為本次倒柱數(shù)10與以后一次滾球所擊倒柱數(shù)之和。
(3) 若某一輪的兩次滾球未擊倒全部十個柱,則本輪不再繼續(xù)滾球,該輪得分為這兩次滾球擊倒的柱數(shù)這和。
總之,若一輪中一次滾球或兩次滾球擊倒十個柱,則本輪得分是本輪首次滾球開始的連續(xù)三次滾球擊倒柱數(shù)之和(其中有一次或兩次不是本輪滾球)。若一輪內(nèi)二次滾球擊倒柱數(shù)不足十個,則本輪得分即為這兩次擊倒柱數(shù)之和。
#include<stdio.h>
#include<string.h>
#include<math.h>
int fequal(double x,double y)
{
if(fabs(x-y)<1e-7)
{
return 1;
}
else
{
return 0;
}
}
void main()
{
int score[10]={0};
int state1=0,state2=0,state=0;
int nowscore=0;
for(int i=0;i<10;i++)
{
printf("------------this is the %d round-----------\n",i);
scanf("%d",&nowscore);
score[i]=nowscore;
if(state1==2&&state2==2) //如果兩個好球 那么就需要加上第三輪的第一個球
{
score[i-2]+=nowscore;
}
if(state2==2||state2==1) //第二輪球無論是什么 都要加上這個球
{
score[i-1]+=nowscore;
}
if(nowscore==10)
{
state=2;
}
else
{
scanf("%d",&nowscore);
score[i]+=nowscore;
if(score[i]==10)
{
state=1;
}
else{
state=0;
}
if(state2==2) //上一輪是一個好球,那么就要加上這一輪的兩個球
{
score[i-1]+=nowscore;
}
}
state1=state2;
state2=state;
}
//前面九輪都得以處理 但是因為第十輪有點問題
if(state2==1) //這個表示第十輪為成功
{
scanf("%d",&nowscore);
score[9]=score[9]+nowscore;
}
else if(state2==2) //這個表示第十輪為好球 獎勵兩個球
{
scanf("%d",&nowscore);
score[9]+=nowscore;
if(state1==2) //這個表示第九輪也是好球
{
score[8]+=nowscore;
}
scanf("%d",&nowscore);
score[9]+=nowscore;
}
int total=0;
printf("---------------------------\n");
for(int j=0;j<10;j++)
{
printf("%d\n",score[j]);
total+=score[j];
}
printf("%d",total);
}
搞明白了也不是很復(fù)雜,就這么大點事情。
4.12: 素數(shù)差問題,問題不大過程搞得很復(fù)雜,實在沒必要
這本書的課后題目多多少少有點問題,大概都是外國教材翻譯過來的,這個翻譯水平多多少少有點拉。
void main()
{
int a[2000];
int count=0;
a[0]=2;
count=1;
for(int i=3;i<2000;i++)
{
int flag=1;
for(int j=0;j<count;j++)
{
if(i%a[j]==0) //如果沒有余數(shù) 就表明不是素數(shù)
{
flag=0;
}
}
if(flag==1)
{
a[count]=i;
count++;
}
}
int bushu[2000];
for(int i=0;i<count-1;i++)
{
bushu[i]=a[i+1]-a[i];
}
for(int i=0;i<count-1;i++)
{
printf("%6d",bushu[i]);
if(i%10==0)
{
printf("\n");
}
}
printf("\n");
for(int i=0;i<count-1;i++)
{
int sum=0;
for(int j=i;j<count-1;j++)
{
sum+=bushu[j];
if(sum==1898)
{
printf("start is %d and the end is %d\n",a[i],a[j+1]);
}
}
}
}
第五章:
指針變量的類型指的是指針變量指向的變量的類型,而不是自身的類型。
既然教材里提到 常量指針 我就提一下
const int* p
int* const p
兩個區(qū)別,第一個是表明*p是常量 也就是p指向的內(nèi)容是一個常量不可改變,但是p可以指向另外一個常量
第二個是表明p是常量,也就是p自身的內(nèi)容不可改變,比如p指向了整形a,那么p就不可以再指向別人,但是a的值可以被修改。
p++ 結(jié)合順序由于++ 和 同優(yōu)先級,并且從右往左,所以原式等于(p++)
如果是v=p++ 那么由于p先執(zhí)行++運算 但是并不立刻改變p的值,所以實際上v得到的是p指針指向的變量的值。
而v=++p 則先進(jìn)行++p 再進(jìn)行運算,所以將p下一個地址的變量值賦值給v
指針相減運算,兩個指向相同數(shù)據(jù)類型的指針相減,差表示兩個指針?biāo)赶虻臄?shù)據(jù)元素之間所相差的元素個數(shù)。
這點可能難以理解,以下實例可以證明:

即兩指針的差會自動除以當(dāng)前變量類型的長度。
設(shè)置int* p=a; //a為數(shù)組名
p[1]和a[1]是合法且等價的。
2.15:
指針這里有很多問題,當(dāng)年學(xué)的時候就沒太搞明白
假設(shè)二維數(shù)組a[3][4] 那么p=a 等價于p=a[0] 等價于p=&a[0][0]
但是有些東西就很奇葩了,比如說p=&a p=&a[0]的 雖然p的值都完全相同,但是其意義則完全不同。
同時要注意的是,定義多維數(shù)組,如果定義數(shù)組的同時初始化,最高位可以省略讓編譯器自動填充,但是后面的位數(shù)則不能省略。
int a[][3]={1,2,3,4,5,6,8,9,10,11,12}; //這樣是合法的
這里似乎不同編譯器執(zhí)行的結(jié)果完全不同,實際上
int a[][3]={1,2,3,4,5,6,8,9,10,11,12};
int *p1,*p2,*p3,*p4,*p5;
p1=a;
p2=a[0];
p3=&a[0][0];
p4=&a;
p5=&a[0];
printf("%d,%d,%d,%d,%d\n",p1,p2,p3,p4,p5);
printf("%d,%d,%d,%d,%d\n",p1+1,p2+1,p3+1,p4+1,p5+1);
在mingw里面運行是沒什么問題的,但是VS是不能運行的,因為指針賦值類型不同,
按照當(dāng)前的C標(biāo)準(zhǔn),這個程序最標(biāo)準(zhǔn)的寫法應(yīng)該是這樣的
int a[][3] = { 1,2,3,4,5,6,8,9,10,11,12 };
int (*p1)[3];
int* p2;
int* p3;
int (*p4)[4][3] ;
int (*p5)[3];
p1 = a; //實際上 a等于&a[0] a等于數(shù)組第一個元素的地址
p5 = &a[0];
p2 = a[0]; //a[0]等價于 &a[0][0]
p3 = &a[0][0];
p4 = &a;
printf("%d,%d,%d,%d,%d\n", p1, p2, p3, p4, p5);
printf("%d,%d,%d,%d,%d\n", p1 + 1, p2 + 1, p3 + 1, p4 + 1, p5 + 1);
也就是實際上 a等價于&a[0] a[0]等價于&a[0][0]
如果p是一個結(jié)構(gòu)體指針,那么調(diào)用結(jié)構(gòu)體內(nèi)變量應(yīng)該使用 (p).data
因為 . 的運算優(yōu)先級要高于 因此必須要用括號括起來。
如果使用 -> 運算符,就完全可以不用考慮這個括號問題
然后是檢測字符串指針內(nèi)容
while(*p) 只有指向內(nèi)容是\0時才會判斷為假,否則都為真。
2.16:
例題5-10 合并字符串
void main()
{
//合并字符串
char a[30],b[30];
scanf("%s %s",a,b);
printf("%s\n%s\n",a,b);
char *pa,*pb;
pa=a;
pb=b;
while(*pa)
{
pa++;
}
while(*pb)
{
*pa++=*pb++;
}
*pa='\0';
printf("%s\n%s\n",a,b);
}
字符串排序 先用冒泡塞了一遍,又用直插塞了回去,大概就是這么個過程吧。
#include<stdio.h>
#include<string.h>
#include<math.h>
void main()
{
char p[10][15];
for(int i=0;i<10;i++)
{
scanf("%s",p[i]);
}
printf("----------------------------- ---------------------------------\n");
for(int i=0;i<10;i++)
{
printf("%15s",p[i]);
}
printf("\n----------------------------- ---------------------------------\n");
for(int i=0;i<9;i++)
{
int flag=0;
//首先是冒泡排序
for(int j=0;j<10-1-i;j++)
{
if(strcmp(p[j],p[j+1])>0)
{
char temp[15];
strcpy(temp,p[j]);
strcpy(p[j],p[j+1]);
strcpy(p[j+1],temp);
flag=1;
}
}
if(flag==0)
{
break;
}
}
for(int i=0;i<10;i++)
{
printf("%15s",p[i]);
}
printf("\n----------------------------- ---------------------------------\n");
for(int i=1;i<10;i++)
{
char temp[15];
strcpy(temp,p[i]);
int j;
for(j=i-1;j>=0;j--)
{
if(strcmp(p[j],temp)<0)
{
strcpy(p[j+1],p[j]);
}
else
{
break;
}
}
strcpy(p[j+1],temp);
}
for(int i=0;i<10;i++)
{
printf("%15s",p[i]);
}
printf("\n----------------------------- ---------------------------------\n");
}
簡單選擇排序本身最大的優(yōu)勢就是較少的交換次數(shù),但是本書為了減少額外的一個存儲空間,大大加大了交換次數(shù),實在是.....一言難盡。
刪除字符串1中包含的字符串2的字符
#include<stdio.h>
#include<string.h>
#include<math.h>
void main()
{
char a[30],b[30];
char *p,*q;
p=a;
q=b;
gets(a);
gets(b);
int deletenum=0;
for(p=a;*p!='\0';p++)
{
for(q=b;*q!='\0';q++)
{
if(*p!=*q)
{
printf("-%c %c-\n",*p,*q);
//如果兩者不相等
*(p-deletenum)=*p;
}
else
{
deletenum++;
break;
}
}
}
*(p-deletenum)='\0';
printf("\n%s",a);
}
下面是簡化版本
#include<stdio.h>
#include<string.h>
#include<math.h>
void main()
{
char a[30],b[30];
char *p,*q;
p=a;
q=b;
gets(a);
gets(b);
int deletenum=0;
for(p=a;*p!='\0';p++)
{
int flag=0;
for(q=b;*q!='\0';q++)
{
if(*p==*q)
{
deletenum++;
flag=1;
break;
}
}
if(flag==0)
{
*(p-deletenum)=*p;
}
}
*(p-deletenum)='\0';
printf("\n%s",a);
}
第五章習(xí)題
5.2
void main()
{
char *point[5]={
"first",
"second",
"third",
"forth"
};
while(*point[2])
{
printf("%c",*point[2]++); //這里先執(zhí)行[] 再執(zhí)行++ 再執(zhí)行*
//因此這個式子等于取數(shù)組內(nèi)的地址,輸出值,然后將數(shù)組內(nèi)地址執(zhí)行”+1“操作
}
}
5.4
void main()
{
int data[12]={12,34,56,12,34,56,3,54,6,7,89,12};
int sum=0;
int* p=data;
for(int i=0;i<12;i++)
{
sum+=*p++;
}
printf("%d",sum);
}
檢測字符串2在字符串1中出現(xiàn)的位置和次數(shù)
其實沒答案里面寫的那么復(fù)雜,這樣就好。
#include<stdio.h>
#include<string.h>
#include<math.h>
void main()
{
char string1[100];
char string2[100];
gets(string1);
gets(string2);
char* p1=string1, *p2=string2;
char* pfind=NULL;
char* temp=p1;
int length=strlen(p2);
int place[100];
int count=0;
while(pfind=strstr(temp,p2))
{
place[count]=strlen(p1)-strlen(pfind);
count++;
temp=pfind+strlen(p2);
}
printf("string1 has %d string2\n",count);
for(int i=0;i<count;i++)
{
printf("the %d place is %d\n",i+1,place[i]);
}
}
比較兩個字符串是否相等
額 你直接strcmp不就好了嗎
我不寫了,有C庫函數(shù),真沒必要一個一個字符比較。
第六章:
函數(shù)不允許嵌套定義
但是可以嵌套調(diào)用,這是很淺顯的道理。
main函數(shù)雖然說不可以被其他函數(shù)調(diào)用,但是main函數(shù)本身實際上是可以調(diào)用main函數(shù)自身的。
如何省略函數(shù)原型:
- 如果被調(diào)函數(shù)的返回值是整形或者是字符型,不必考慮被調(diào)函數(shù)的位置,
- 如果被調(diào)函數(shù)的定義出現(xiàn)在主調(diào)函數(shù)之前
- 提前說明
C99標(biāo)準(zhǔn)的確可以實現(xiàn)第一條,但是C++ 11之后的標(biāo)準(zhǔn)則不可
同時第一條 如果是char類型作為函數(shù)的返回值,依然編譯錯誤
C語言 如果實參數(shù)量和形參不匹配,編譯不會報錯
不過這上面的東西都是一些陳芝麻爛谷子地事情,所以我覺得弄不弄清楚都差不多,反正現(xiàn)在也沒人會這樣寫。
然后參數(shù)調(diào)用時參數(shù)運行的順序也是沒有規(guī)定的,大部分編譯器統(tǒng)一從右往左算,而最離譜的a++ 以及 ++a 這種東西
++a 這種東西 是算完后,等到最后會從內(nèi)存里面取數(shù),而a++則是直接將a的運算結(jié)果導(dǎo)入,啊,實際上討論這個東西實在是沒什么意義。
int a=10;
printf("%d %d %d %d",a++,++a,a,a++);
在mingw 和 vs 中輸出的值都為 12 13 13 10
而書上的例子并沒有實際意義
2.17:
將數(shù)組名稱作為參數(shù)傳遞時,其傳遞的是數(shù)組的頭地址,而不是整個數(shù)組的值傳遞。
數(shù)組名作為函數(shù)參數(shù)時:
- 形參數(shù)組和實參數(shù)組的類型必須一致,
- 形參數(shù)組和實參數(shù)組的長度可以不相同,因為在調(diào)用時,只傳送首地址而不檢查形參數(shù)組的長度。
- 因此在函數(shù)形參表中,可以不給出形參數(shù)組的長度。
傳遞二維/高維數(shù)組時,可以省略第一維的長度。
函數(shù)指針
int (*p)(int a,int b)
唯一需要注意的就是函數(shù)指針這個括號
漢諾塔遞歸問題
#include<stdio.h>
#include<stdlib.h>
void HNT(int m,char start,char mid,char end)
{
if(m==1)
{
printf("%c -> %c\n",start,end);
}
else
{
HNT(m-1,start,end,mid);
HNT(1,start,mid,end);
HNT(m-1,mid,start,end);
}
}
int main()
{
printf("漢諾塔問題\n");
int number=4;
HNT(number,'a','b','c');
}
命令行 argc表示命令行參數(shù)的個數(shù),包括可執(zhí)行程序名本身,argv[] 定義為指向字符串常量的指針數(shù)組,數(shù)組元素是分別指向命令行中可執(zhí)行文件名和各個命令行參數(shù)字符串的指針。
正如 本章實例所說:

那么argc標(biāo)注的參數(shù)個數(shù)為3 而argv字符串指針數(shù)組,這個數(shù)組內(nèi)元素的個數(shù)為argc+1 第一個表示可執(zhí)行文件名,后面為輸入?yún)?shù),最后一個為空表示結(jié)束。
命令行參數(shù) 本書教學(xué)部分就講的不清不白的,不看了(本身也是自選內(nèi)容)
按序輸出五個國家的名稱
#include<stdio.h>
#include<stdlib.h>
void sortCountryname(char name[][100],int low,int line)
{
for(int i=1;i<low;i++)
{
char temp[100];
strcpy(temp,name[i]);
int j=0;
for(j=i-1;j>=0;j--)
{
if(strcmp(temp,name[j])<0)
{
strcpy(name[j+1],name[j]);
}
else
{
break;
}
}
strcpy(name[j+1],temp);
}
}
int main()
{
char countryname[5][100];
for(int i=0;i<5;i++)
{
gets(countryname[i]);
}
puts("----------------------------");
sortCountryname(countryname,5,100);
for(int i=0;i<5;i++)
{
puts(countryname[i]);
}
}
唉 到底什么時候才會講動態(tài)分配內(nèi)存,我傻了。
遞歸函數(shù)并不能節(jié)省內(nèi)存空間和提高運行速度。
第六章習(xí)題處理
6.3 處理字符串
#include<stdio.h>
#include<stdlib.h>
void produce(char* strings)
{
int length=strlen(strings);
int count=0;
char old=NULL;
int i;
for(i=0;i<length;i++)
{
if((strings[i]>'0'&&strings[i]<'9')||(strings[i]>'a'&&strings[i]<'z')||(strings[i]>'A'&&strings[i]<'Z'))
{
old=strings[i];
strings[i-count]=strings[i];
}
else
{
if(strings[i]==old)
{
count++;
}
else
{
strings[i-count]=strings[i];
old=strings[i];
}
}
}
strings[i-count]='\0';
}
int main()
{
char strings[100];
gets(strings);
puts(strings);
produce(strings);
puts(strings);
}
6.4 百十個位數(shù) 乘積
void produce(int num)
{
int gewei=0;
int shiwei=0;
int baiwei=0;
gewei=num%10;
shiwei=(num/10)%10;
baiwei=(num/100)%10;
int sum=pow(gewei,3)+pow(shiwei,3)+pow(baiwei,3);
if(sum==num)
{
printf("%4d\n",sum);
}
}
int main()
{
for(int i=0;i<=999;i++)
{
produce(i);
}
}
6.5 二元一次方程解
#include<stdio.h>
#include<stdlib.h>
void produce(float a,float b,int c)
{
float det=pow(b,2)-4.0*a*c;
float x1;
float x2;
if(det<0)
{
printf("對不起,在實數(shù)域內(nèi)沒有合適的解\n");
}
else
{
det=sqrt(det);
x1=(-b+det)/(2*a);
x2=(-b-det)/(2*a);
printf("x1=%10.4f x2=%10.4f",x1,x2);
}
}
int main()
{
float a,b,c;
scanf("%f %f %f",&a,&b,&c);
produce(a,b,c);
}
6.6 最小公倍數(shù)
#include<stdio.h>
#include<stdlib.h>
int zuixiaogongyueshu(int a,int b)
{
int p=0;
while(a%b!=0)
{
//如果a%b==0 就代表結(jié)束運算
int temp=a%b;
a=b;
b=temp;
}
return b;
}
int find(int a,int b)
{
return a*b/zuixiaogongyueshu(a,b);
}
int main()
{
int a[5];
for(int i=0;i<5;i++)
{
scanf("%d",&a[i]);
}
int temp=a[0];
for(int i=1;i<5;i++)
{
temp=find(temp,a[i]);
printf("--%d--\n",temp);
}
printf("%d",temp);
}
求一到三萬的所有質(zhì)數(shù)
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a[10000];
int count=0;
for(int i=2;i<=30000;i++)
{
if(count==0)
{
a[count]=i;
count++;
}
else
{
int flag=0;
for(int j=0;j<count;j++)
{
if(i%a[j]==0)
{
flag=1;
break;
}
}
if(flag==0)
{
a[count]=i;
count++;
}
}
}
int temp=0;
for(int i=0;i<count;i++)
{
if(temp==1&&i%10==9)
{
printf("\n");
}
else
{
temp=1;
printf("%6d",a[i]);
}
}
}
求完備數(shù)
#include<stdio.h>
#include<stdlib.h>
void find(int num)
{
int sum=0;
int a[100];
int count=0;
for(int i=1;i<num;i++)
{
if(num%i==0)
{
sum+=i;
a[count]=i;
count++;
}
}
if(sum==num)
{
printf("%6d",num);
for(int i=0;i<count;i++)
{
printf("%6d",a[i]);
}
printf("\n");
}
}
int main()
{
for(int i=1;i<30000;i++)
{
find(i);
}
}
6.8 互滿數(shù)
#include<stdio.h>
#include<stdlib.h>
int find(int num)
{
int sum=0;
int a[300];
int count=0;
for(int i=1;i<num;i++)
{
if(num%i==0)
{
sum+=i;
a[count]=i;
count++;
}
}
return sum;
}
int main()
{
int p=0;
for(int i=1;i<30000;i++)
{
p=find(i);
if(i<p&&i==find(p))
{
printf("%7d %7d\n",i,p);
}
}
}
2.20:
6.11 字符串比較函數(shù)
#include<stdio.h>
#include<stdlib.h>
void bijiao(char*a,char *b)
{
while(*a!='\0'&&*b!='\0')
{
if(*a>*b)
{
printf("a>b");
return;
}
else if(*a<*b)
{
printf("a<b");
return;
}
a++;
b++;
}
if(*a)
{
printf("a b 前端完全相等 但是a更長 所以a大");
}
else if(*b)
{
printf("b更大");
}
else
{
printf("a==b");
}
}
int main()
{
char a[100],b[100];
gets(a);
gets(b);
if(strcmp(a,b)==0)
{
printf("a和b相等\n");
}
else if(strcmp(a,b)>0)
{
printf("a>b\n");
}
else
{
printf("a<b\n");
}
bijiao(a,b);
}
輸出組合數(shù) 并且輸出所有可能的組合
這道題 有點意思 這題需要拿數(shù)組做 之前沒想起來
#include<stdio.h>
#include<stdlib.h>
int jiecheng(int k)
{
int sum=1;
for(int i=1;i<=k;i++)
{
sum*=i;
}
printf("%4d",sum);
return sum;
}
void function2(int n,int k,int* a)
{
if(k>=1)
{
for(int i=n;i-k>=0;i--)
{
a[k]=i;
function2(i-1,k-1,a);
}
}
else
{
for(int i=a[0];i>=1;i--)
{
printf("%4d",a[i]);
}
printf("\n");
}
}
void function(int k,int n)
{
int p=jiecheng(n)/(jiecheng(k)*jiecheng(n-k));
printf("共有%d種組合\n",p);
int a[10];
a[0]=k;
function2(n,k,a);
}
int main()
{
int n;
int k;
scanf("%d %d",&n,&k);
function(k,n);
}
排序輸出
#include<stdio.h>
#include<stdlib.h>
void function2(int n,int k,int* a,int *flag)
{
if(k>=1)
{
for(int i=1;i<=n;i++)
{
if(flag[i]==0)
{
flag[i]=1;
a[k]=i;
function2(n,k-1,a,flag);
flag[i]=0;
}
else
{
continue;
}
}
}
else
{
for(int i=a[0];i>=1;i--)
{
printf("%4d",a[i]);
}
printf("\n");
}
}
void function(int k,int n)
{
int a[10];
a[0]=k;
int flag[10]={0};
function2(n,k,a,flag);
}
int main()
{
int n;
int k;
scanf("%d %d",&n,&k);
function(k,n);
}
這里涉及到字符的組合排序問題 下面將拓展這個算法的實際內(nèi)容
參考內(nèi)容為:
https://blog.csdn.net/qq_42552533/article/details/88606550?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control&dist_request_id=d5755e2c-0ba8-445b-9ca8-d4eeb77b9868&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control
#include<stdio.h>
#include<stdlib.h>
void swap(char* p,char *q)
{
char temp=*p;
*p=*q;
*q=temp;
}
void core_function(char* a,int left,int right)
{
if(left<right)
{
for(int i=left; i<=right; i++)
{
swap(&a[left],&a[i]);
core_function(a,left+1,right);
swap(&a[left],&a[i]);
}
}
else
{
puts(a);
}
}
void function(char* a,int length)
{
core_function(a,0,length-1);
}
int main()
{
char a[40];
gets(a);
int length=strlen(a);
function(a,length);
}
如果要實現(xiàn)含有重復(fù)字符的篩查,交換前需要判斷,left和right(包括left左邊界是否有和right邊界相同的元素,如果有,則不發(fā)生交換)
#include<stdio.h>
#include<stdlib.h>
void swap(char* p,char *q)
{
char temp=*p;
*p=*q;
*q=temp;
}
int judge_ISorNot_swap(char* a,int left,int right)
{
int flag=1;
for(int i=left; i<right; i++)
{
if(a[i]==a[right])
{
flag=0;
}
}
return flag;
}
void core_function(char* a,int left,int right)
{
if(left<right)
{
for(int i=left; i<=right; i++)
{
if(judge_ISorNot_swap(a,left,i))
{
swap(&a[left],&a[i]);
core_function(a,left+1,right);
swap(&a[left],&a[i]);
}
}
}
else
{
puts(a);
}
}
void function(char* a,int length)
{
core_function(a,0,length-1);
}
int main()
{
char a[40];
gets(a);
int length=strlen(a);
function(a,length);
}
隨機數(shù)之圓周率
#include<stdio.h>
#include<stdlib.h>
int function()
{
float x1f=rand()*1.0/RAND_MAX;
float x2f=rand()*1.0/RAND_MAX;
// printf("%10f %10f\n",x1f,x2f);
if(pow(x1f,2)+pow(x2f,2)<1)
{
return 1;
}
else
{
return 0;
}
}
int main()
{
srand(time(NULL));
int i=0;
int sum=0;
while(i<100000)
{
sum+=function();
i++;
}
printf("%f",sum*4.0f/100000);
}
身份證比較 這題不算很難 細(xì)節(jié)我就不寫了
但是要注意的是如果不使用for循環(huán)挨個挨個賦值,使用strncpy 務(wù)必注意最后加上 \0 否則會粘貼后的字符串沒有截斷標(biāo)志,會出現(xiàn)很多問題。
extern 可以用來擴展 全局變量的作用范圍
例如m是在程序中部定義的全局變量 使用extern即可將其作用擴展到指定的函數(shù)內(nèi)(該函數(shù)比m定義要早)
同時 extern進(jìn)行引用時,可以不標(biāo)注變量類型。
同時如果局部變量和外部變量重名,那么外部變量會被屏蔽在函數(shù)內(nèi)無法被訪問。
要指出的是 外部變量一定是全局變量。
只有自動變量和形參可以作為寄存器變量,調(diào)用時分配寄存器,調(diào)用結(jié)束后釋放寄存器。
這里要指出的是:只要不是在函數(shù)內(nèi)部定義的變量就是外部變量,所以外部變量的定義還是蠻大的,extern關(guān)鍵字只是為了擴大作用域罷了,不是加上extern才叫外部變量,同時static也可以用來修飾外部變量,就是全局靜態(tài)變量,一旦設(shè)置為全局靜態(tài)變量,那么就只能在當(dāng)前.c文件內(nèi)使用,
外部變量定義時如果缺失初試值,缺省值自動設(shè)置為0.
靜態(tài)變量,不論是局部靜態(tài)變量還是全局靜態(tài)變量,初始化只會初始化一次,即是定義的那一次會初始化一次初值。
例如下面代碼:
void printfx()
{
static int p=10;
printf("%d\n",p++);
}
int main()
{
int i=0;
while(i<10)
{
i++;
printfx();
}
}
輸出結(jié)果從10到19,而不是每次都會執(zhí)行p=10。
malloc函數(shù)的返回值是void* 類型,如果分配成功,函數(shù)返回一個指向該區(qū)域起始地址的指針,如果內(nèi)存不夠,那么返回NULL。
所以分配動態(tài)空間時,需要對指針的類型進(jìn)行轉(zhuǎn)換,例如:
int* p=(int*)malloc(sizeof(int)*4);
calloc函數(shù)和malloc作用相同,但是調(diào)用參數(shù)有兩個,第一個是n表示分配n個空間,第二個是size,表示單個空間的大小。
即 int* p=(int*)calloc(4,sizeof(int))
分配完內(nèi)存后,使用free函數(shù)即可釋放掉動態(tài)申請的存儲空間,
realloc函數(shù) 原型如下
p= realloc(p, size) // void* realloc(void* p, unsigned int size)
作用是重新分配內(nèi)存,如果后開辟的內(nèi)存比原內(nèi)存要大,則完全復(fù)制原內(nèi)存種內(nèi)容,如果要小,則只復(fù)制指定size的內(nèi)容。
重分配內(nèi)存之后,后分配的內(nèi)存起始地址和源地址不一定相同。
2.21:
預(yù)處理程序僅僅在當(dāng)前文件有效
預(yù)處理程序中,例如:
#define CESHI "hello my brother! "
CESHI將代表后方的字符串,如果字符串過長,既可以使用\符號來將其擴展到下一行
例如:
#define CESHI "8843e\
886\
221\
dianzikeji"
通過這種在某位增加反斜杠的方式可以拓展長度
宏定義允許嵌套
例如:
#define ONE 1
#define TWO ONE+ONE
TWO代表的就是2
define的進(jìn)階用法,參數(shù)調(diào)用:
#define MAX(a,b) a>b?a:b
// 不需要指明 a和b的類型
// 不需要強調(diào)返回值
// MAX與左括號之間不允許有空格
宏定義時,最好將整個表達(dá)式和各個參數(shù)用圓括號括起來,否則宏定義可能會產(chǎn)生不可預(yù)見的錯誤,
例如:
#include<stdio.h>
#include<stdlib.h>
#define EVEN(a) a%2==0?1:0
int m=10;
int main()
{
//顯然 按照正常的理解
//9+1=10那么顯然%2==0 所以應(yīng)當(dāng)輸出1
printf("%d",EVEN(9+1));
//但是實際結(jié)果是0,因為其最后調(diào)用結(jié)果是 9+1%2==0?1:0 先計算%再計算+最后計算==的情況下,顯然結(jié)果不是0
//所以輸出的結(jié)果應(yīng)該是0
}
帶參數(shù)的宏定義只是程序預(yù)處理時進(jìn)行簡單的替換,沒有變量類型的要求,可適用于任何類型的參數(shù),
使用宏的優(yōu)點就是運行速度快,因為在預(yù)處理階段就被展開,省去了函數(shù)調(diào)用時的開銷,但同時也使得程序代碼的長度增大,而函數(shù)調(diào)用則由于函數(shù)只會被定義一次,在目標(biāo)程序中只占用同樣的存儲空間,節(jié)省了存儲空間,但是因為調(diào)用的時候涉及到參數(shù)的傳遞和返回,現(xiàn)場的保存和恢復(fù),其都需要額外的時間開銷。
如果要撤銷宏定義,則需要使用#undef 宏標(biāo)識符
條件編譯:
#if
#else
#endif
要注意的是 if 的條件判斷式中只能使用常量或者宏替換名組成判斷表達(dá)式,而不能使用變量,因為其根本就是在編譯階段前進(jìn)行的條件編譯。
同時 條件編譯還可以使用
#ifdef
#ifndef
來根據(jù)是否已經(jīng)定義過/未定義過某些宏定義來進(jìn)行相應(yīng)的編譯處理
任意進(jìn)制轉(zhuǎn)換 這道例題還是滿有價值的,
#include<stdio.h>
#include<stdlib.h>
void function(int convertnum,int mod)
{
extern char a[];
if(convertnum/mod==0)
{
printf("%c",a[convertnum]);
}
else
{
function(convertnum/mod,mod);
printf("%c",a[convertnum%mod]);
}
}
char a[]="0123456789ABCDEF";
void main()
{
int convert;
scanf("%d",&convert);
puts("-------------------------------------------");
int mod;
scanf("%d",&mod);
function(convert,mod);
puts("-------------------------------------------");
printf("%d",0314);
}
額 7.3 7.4 我結(jié)合起來隨便寫了一下
出現(xiàn)了一個編譯錯誤就是 全局變量或者靜態(tài)變量(帶static)的初始化都不可以使用變量
主要原因就是標(biāo)準(zhǔn)C定義靜態(tài)變量/全局變量的時候,事先在全局內(nèi)存區(qū)分配內(nèi)存,然后就會立刻進(jìn)行初始化操作(在編譯階段,即代碼執(zhí)行之前) 這個時候變量還沒有確定的值,自然無法完成初始化操作。
// main.c
#include<stdio.h>
#include<stdlib.h>
extern int* data;
extern int num;
void swap(int* p,int* q)
{
int temp=*q;
*q=*p;
*p=temp;
}
void main()
{
USE();
int flag=0;
for(int i=0;i<num-1;i++)
{
for(int j=0;j<num-1-i;j++)
{
if(data[j]>data[j+1])
{
swap(data+j,data+j+1);
flag=1;
}
}
if(flag==0)
{
break;
}
}
for(int i=0;i<20;i++)
{
printf("%4d",*(data+i));
}
}
//------------------------------------------------
//twice.c
//------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
int* data=0;
int num=20;
void USE()
{
data=calloc(20,sizeof(int));//就是這行代碼并不能寫在data定義的后面
for(int i=0;i<20;i++)
{
scanf("%d",data+i);
}
}
看群消息學(xué)了一個冷知識
int a,b;
b=(a=9);
此時 b和a的值都是9
2.22:
位域 位域變量C99規(guī)定只能是int 或者是 unsigned int
‘這里要提到一個問題,就是*p.a 是先執(zhí)行.運算然后才執(zhí)行*運算
位域運算過程中,不允許取一個位域變量的地址
不允許超過整形邊界
位域的詳細(xì)說明鏈接:
https://blog.csdn.net/yixixi/article/details/2961293 //這個詳細(xì)描述了位域的規(guī)則
https://blog.csdn.net/u010575913/article/details/22886667 //這個舉例了一些位域大小的判斷例題
下面為復(fù)制過來的規(guī)則說明:
如果相鄰位域字段的類型相同,且其位寬之和小于類型的sizeof大小,則后面的字 段將緊鄰前一個字段存儲,直到不能容納為止;
如果相鄰位域字段的類型相同,但其位寬之和大于類型的sizeof大小,則后面的字 段將從新的存儲單元開始,其偏移量為其類型大小的整數(shù)倍;
如果相鄰的位域字段的類型不同,則各編譯器的具體實現(xiàn)有差異,VC6采取不壓縮方 式,Dev-C++采取壓縮方式;
如果位域字段之間穿插著非位域字段,則不進(jìn)行壓縮;
整個結(jié)構(gòu)體的總大小為最寬基本類型成員大小的整數(shù)倍。
位域?qū)崿F(xiàn)奇偶校驗位輸出:
#include<stdio.h>
#include<stdlib.h>
typedef struct test
{
unsigned C0:1;
unsigned C1:1;
unsigned C2:1;
unsigned C3:1;
unsigned C4:1;
unsigned C5:1;
unsigned C6:1;
unsigned C7:1;
}test;
int main()
{
char num[10]="123456789";
for(int i=0;i<10;i++)
{
test* p=num+i;
int sum=p->C0+p->C1+p->C2+p->C3+p->C4+p->C5+p->C6+p->C7;
sum=sum%2;
printf("%c%d%d%d%d%d%d%d%d%d\n",num[i],sum,p->C0,p->C1,p->C2,p->C3,p->C4,p->C5,p->C6,p->C7);
}
}
從這里我們可以看出來現(xiàn)在的windows系統(tǒng)中,都是小端存儲,即低字節(jié)處存放低位信息,例如:
1 ascii碼為 49 為00110001
但是本例將字符地址賦值給test型指針后,依次輸出(按照地址由低到高)C0 C1 C2 ........結(jié)果為10001100
所以可見高位被存儲到高位地址,低位被存儲到低位地址。
所謂大端和小端,指的就是低地址內(nèi)存放的是高位字節(jié)還是低位字節(jié)。
結(jié)構(gòu)體嵌套
#include<stdio.h>
#include<stdlib.h>
typedef struct test
{
unsigned C0:1;
unsigned C1:1;
unsigned C2:1;
unsigned C3:1;
unsigned C4:1;
unsigned C5:1;
unsigned C6:1;
unsigned C7:1;
}test;
typedef struct test2
{
int year;
int month;
int day;
}data;
typedef struct test3
{
data data1;
int ppp;
}databig;
int main()
{
databig big={1,2,3,890}; //注意結(jié)構(gòu)體變量的初始化方式。
printf("%d %d %d %d",big.data1.year,big.data1.month,big.data1.day,big.ppp);
}
聯(lián)合和結(jié)構(gòu)的主要區(qū)別在于:聯(lián)合類型變量所用的空間不是各個成員所需的存儲空間總和,而是聯(lián)合成員中存儲空間最大的成員所要求的字節(jié)數(shù)。
2.23:
聯(lián)合
本身這個東西沒什么好說的
#include<stdio.h>
#include<stdlib.h>
union test{
int a;
double b;
char c;
};
int main()
{
union test p={10};;//要注意的是 這種賦值方式是可以的
//同樣這樣也是可以的 union test p.a=10
//但是這樣是不可以的 union test p=10;
printf("%d",p.a);
}
這個厲害了 真的開眼了
利用聯(lián)合交換指定數(shù)據(jù)的前后字節(jié)
#include<stdio.h>
#include<stdlib.h>
union test{
int p;
struct tests{
char word1;
char word2;
char word3;
char word4;
}testp;
};
int main()
{
union test test1,test2;
int x;
scanf("%x",&test1.p);
printf("%x\n",test1.p);
test2.testp.word1=test1.testp.word4;
test2.testp.word2=test1.testp.word3;
test2.testp.word3=test1.testp.word2;
test2.testp.word4=test1.testp.word1;
printf("%x\n",test2.p);
}
輸出結(jié)果:
枚舉類型:
enum test{black,white,yellow};
#include<stdio.h>
#include<stdlib.h>
enum color{yellow,green,blue,red,black};
int main()
{
enum color c=yellow;
enum color p=green;
enum color s=white; //這一行將不能執(zhí)行
}
要注意的是 enum 本質(zhì)上是將 枚舉的各個變量依次賦值為 01234......
但如果不實用默認(rèn)賦值,例如:
enum test{one,two,three,four=9,five,six}
這樣會使得枚舉變量依次代表0 1 2 9 10 11 12
依次輸出枚舉變量
enum color{yellow,green,blue=8,red,black};
int main()
{
enum color p;
for(p=yellow;p<=black;p++)
{
printf("%d",p);
}
}
輸出結(jié)果將從0到10,和我原來的預(yù)計還是挺不一樣的。
C語言的文件系統(tǒng)分為緩沖型文件系統(tǒng)和非緩沖型文件系統(tǒng)
前者的輸入輸出函數(shù)稱為流式I/O函數(shù) 后者的輸出函數(shù)成為低級I/O函數(shù)