C語言基礎(chǔ)學(xué)習(xí)筆記_第1頁
C語言基礎(chǔ)學(xué)習(xí)筆記_第2頁
免費(fèi)預(yù)覽已結(jié)束,剩余28頁可下載查看

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、C 語言基礎(chǔ)學(xué)習(xí)筆記(第一版修改)丁炳亮1 數(shù)據(jù)類型和表達(dá)式1.1計算機(jī)內(nèi)數(shù)據(jù)存儲方式理解與測試:什么是補(bǔ)碼?我們得先知道模的概念。模“?!笔侵敢粋€計量系統(tǒng)的計數(shù)范圍。如時鐘 等。計算機(jī)也可以看成一個計量機(jī)器,它也有一個計量范圍,即都存在一個“模”。例如: 時鐘的計量范圍是011,模=12。表示n位的計算機(jī)計量范圍是02A(n)-1,模=2A(n)?!澳!睂?shí)質(zhì)上是計量器產(chǎn)生“溢出”的量,它的值在計量器上表示不出來,計量器上只 能表示出模的余數(shù)。任何有模的計量器,均可化減法為加法運(yùn)算。例如:假設(shè)當(dāng)前時針指向10點(diǎn),而準(zhǔn)確時間是6點(diǎn),調(diào)整時間可有以下兩種撥法:一種是倒撥4小時,即:10-4=6;另

2、一種是順撥8小時:10+8=12+6=6在以12模的系統(tǒng)中, 加8和減4效果是一樣的,因此凡 是減4運(yùn)算,都可以用加8來代替。對“?!倍?8和4互為補(bǔ)數(shù)。實(shí)際上以12模的系統(tǒng) 中,11和1,10和2,9和3,7和5,6和6都有這個特性。共同的特點(diǎn)是兩者相加等于模。二進(jìn)制中整數(shù)的補(bǔ)碼求法是:正數(shù)的補(bǔ)碼為原碼,負(fù)數(shù)的補(bǔ)碼是符號位不變其他位全部 取反再整個數(shù)加1。我們可以通過下面的代碼看下負(fù)整數(shù)在計算機(jī)內(nèi)部的表示。void f(int n)unsigned int i;for(i=1,i=1)if(i&n)printf(1);elseprintf(0);printf(n);main()in

3、t a=-0 xff;f(a);getch();輸出的結(jié)果是1111111100000001。1.2變量與常量理解與測試:1)類型聲明 在計算機(jī)內(nèi)部數(shù)據(jù)是以字節(jié)為單位存儲的,但是我們需要的數(shù)據(jù)類型有很多種,每種數(shù)據(jù)類型所占字節(jié)和存儲方式都不一樣。 類型聲明的作用就是告訴計算機(jī)以哪種“格式”去讀 寫該數(shù)據(jù)數(shù)據(jù)。類型說明符 變量名1,變量名2.,變量名n;類型說明符有基本類型(字符型、整數(shù)型、單/雙精度型)、高級類型(結(jié)構(gòu)體型、共用 體型、枚舉類型)、指針型等,其中指針類型包括指向基本類型的指針類型、指向高級類型 的指針型和指向函數(shù)的指針類型(指向函數(shù)指針聲明格式在后面章節(jié))。2)符號常量的定義#

4、define標(biāo)識符 常量; 使用該種方法定義符號常量一個是可以使代碼便于閱讀理解,另一個是方便代碼內(nèi)部多 個相同常量的統(tǒng)一修改。總結(jié)與注意 在寫計算式的時候要考慮變量是否會越界。一般來說計算式子時是先強(qiáng)制轉(zhuǎn)換成式子中 最大存儲空間的數(shù)據(jù)類型(不包括被賦值的變量),還要注意不同的類型數(shù)據(jù)在不同的編譯 器中所占的內(nèi)存有可能是不一樣的,例如有些編譯器整型是占2個字節(jié)有些是占4個字節(jié)。 同時還要考慮到符號的優(yōu)先級和結(jié)合順序, 如果按符號的優(yōu)先級和結(jié)合順序運(yùn)算過程中有越 界的那么整個計算結(jié)果可能和預(yù)想的不一樣了,例如int i=100;i = 500*i/i;最后i=-155。1.3輸出輸入理解與測試:

5、1)格式化輸入輸出函數(shù)可以按設(shè)定的格式和設(shè)定的數(shù)據(jù)類型接收和輸出多個變量??刂聘袷胶蛿?shù)據(jù)類型的是數(shù)據(jù)控制符。2)字符和字符串可以用專門的輸出 輸入函數(shù)。主要有g(shù)etch(); putch();getchar(); putchar(); gets();puts();其中g(shù)etch()和putch()是conio.h中聲明,getch()不需要等待回車鍵就返回字符并 立即執(zhí)行下面一語句符,getch()不在屏幕顯示輸入的字符。getchar();putchar();在stdio.h中聲 明。getchar()讀取鍵盤上的一個字符,立即返回并顯示在屏幕上,需要等待回車鍵才能執(zhí)行下一條語句。例如下面的

6、代碼:int main(void)char ch,i;for(i=0;i10;i+)ch = getchar();putchar(ch);getch();輸入:I LOVE YOU輸出:I LOVE YOU總結(jié)與注意格式輸入函數(shù)中的參數(shù)是變量存放的地址,所以變量前面要”&”符號。如果是數(shù)組則可以直接用數(shù)組名,因?yàn)閿?shù)組名就是指向該數(shù)組首地址的指針常量。1.4 運(yùn)算符號理解與測試:1)表達(dá)式中符號的運(yùn)算順序是有先后的,根據(jù)符號的優(yōu)先級和結(jié)合性(左結(jié)合/右結(jié)合)來判定。如果是幾個符號連在一起C內(nèi)部是怎么去讀的呢?有一個很簡單的規(guī)則:每一個符 號應(yīng)該包含盡可能多的字符。也就是說,編譯器讀取符號

7、的方法是,從左到右一個字符一個 字符地讀入,如果該字符可能組成一個符號,那么在讀入下一個字符,直到與下個字符組合 成的符號沒有意義為止。例如:a-b;這個表達(dá)式等效于(a-)-b;2)復(fù)合賦值符及表達(dá)式在賦值符 “=”之前加上其他雙目運(yùn)算符號可以構(gòu)成復(fù)合賦值符。如:+=、-=、*=、/=、%=。構(gòu)成復(fù)合賦值表達(dá)式的一般格式為變量 雙目運(yùn)算符=表達(dá)式等價于變量=變量 運(yùn)算符 表達(dá)式可以這么去理解,等號左邊的相當(dāng)于變量自增、自減、自除、自取余一個數(shù),這個數(shù)由右邊的表達(dá)式計算得到。如:int a=7,b=3,c=3;a+=b+=c+=5運(yùn)算后是a=18,b=11,c=&3)C中唯一一個三目運(yùn)

8、算符是條件運(yùn)算符,由“?”和“:”構(gòu)成。兩個符號必須按下 面的格式一起使用:表達(dá)式1?表達(dá)式2:表達(dá)式3三個表達(dá)式可以是任意的合法表達(dá)式,條件運(yùn)算符的運(yùn)算規(guī)則如下:如果表達(dá)式1的值 為真,那么整個表達(dá)式的值為表達(dá)式2的值,否則為表達(dá)式3的值。4)sizeof()也是一個運(yùn)算符號,它可以對一個數(shù)據(jù)類型或一個變量取類型長度。但是當(dāng)一個數(shù)組名作為一個實(shí)參傳遞給函數(shù)時,在函數(shù)內(nèi)部是不能用sizeof來獲取該數(shù)組的長度的。 因?yàn)閿?shù)組名是一個指向數(shù)組首地址的指針,使用sizeof只能取得實(shí)參指針類型長度。5)比較少用到的符號是“:”和“,”。冒號運(yùn)算符在C中有三種用途,第一種是我 們上面講到的與“?”構(gòu)成

9、三目運(yùn)算。第二種是在switch中放在常量表達(dá)式后面。第三種用 法是在結(jié)構(gòu)體中定義位域時用到。struct位域結(jié)構(gòu)名位域列表;其中位域列表的形式為: 類型說明符 位域名:位域長度例如:struct bsint a:8;int b:2;int c:6;逗號運(yùn)算符的功能是把兩個表達(dá)式連在一起組成一個新的表達(dá)式,稱為逗號表達(dá)式。其 一般格式為表達(dá)式1,表達(dá)式2,表達(dá)式3,.,表達(dá)式n; 其求值過程是自左向右求兩個表達(dá)式的值,并以最后一個表達(dá)式的值作為整個逗號表達(dá)式的值。例如for(a=0,b=0,c=0;b10,a20;b+,a+)+c運(yùn)算后c=20,如果把中間的兩個語句前 后調(diào)換for(a=0,b

10、=0,c=0;b10,aj?i+:j; printf(%dn,n); getch();輸出結(jié)果:243)在寫式子時要注意運(yùn)算符號對變量的副作用,單目運(yùn)算有“+”和“-”,雙目運(yùn)算有“=”。4)位運(yùn)算符號與邏輯符號容易混淆的有“&”和“&”、“|”和“|”、“”和“!”。 前面兩個可以這么記,位運(yùn)算是單個的所以符號也是單個的。5)在使用位運(yùn)算符號時要主要如果是有符號數(shù)則是對他們的補(bǔ)碼執(zhí)行位運(yùn)算。對于有符號的整數(shù)型使用左移“”左補(bǔ)1。如下代碼:void f(int n)unsigned int i;for(i=1,i=1)if(i&n)printf(1);elseprint

11、f(0);printf(n);main()int a=-0 xff;f(a);a=1;f(a);getch();輸出的結(jié)果是:111111110000000111111111100000006)運(yùn)算符優(yōu)先級可以簡單歸納如下幾點(diǎn):1單目運(yùn)算符比任何一個真正意義上的運(yùn)算符的優(yōu)先級高。2邏輯運(yùn)算符比關(guān)系運(yùn)算符優(yōu)先級高。3移位運(yùn)算符表算術(shù)運(yùn)算符優(yōu)先級低,但高于關(guān)系運(yùn)算符。2 程序控制結(jié)構(gòu)2.1 選擇結(jié)構(gòu)理解與測試:使用if-else多層嵌套時else是與上面同一層的最近if相結(jié)合的,在程序設(shè)計時有過多的 分支最好要選擇使用if-else,當(dāng)然如果可以使用switch語句還是盡量選擇switch語句或者

12、使 用其他能使代碼簡潔易懂的方法。如下面的代碼:main()int a=10,b=6,c=7,d=8,e=9,f=10;if(ab)printf(%dn,a);if(bc)printf(%dn,b);if(cd)printf(%dn,c);if(de)printf(%dn,d);if(ef)printf(%dn,e);elseprintf(%dn,f);getch();這種代碼又長又難看懂,更要命的是經(jīng)常搞不懂下面的大括號對應(yīng)上面的哪個大括號。改進(jìn)后的代碼如下main()int a=10,b=6,c=7,d=8,e=9,f=10;while(1)if(a=b)break;printf(%dn,

13、a);if(b=c)break;printf(%dn,b);if(c=d)break;printf(%dn,c);if(d=e)break;printf(%dn,d);if(e=f)printf(%dn,e);elseprintf(%dn,f);break;getch();第二種方法比第一種方法來看上去更干凈,理解上差不了多少。2)總結(jié)與注意switch語句中每一個分支結(jié)束都要有break語句,如果沒有是繼續(xù)執(zhí)行下面分支,可能會 得到和預(yù)料不同的效果。還要注意,case后面跟的一定是整數(shù)型或符號型常量表達(dá)式,不能 是變量,并且不用有相同值的變量表達(dá)式,不然會矛盾的。2.2 循環(huán)結(jié)構(gòu)理解與測試:

14、1)主要有for、while、do-while這三種結(jié)構(gòu)循環(huán)體,其中最后一種是比較少用到的,因 為一般情況都可以用前面兩種替代。2)循環(huán)體結(jié)構(gòu)中括號的表達(dá)式要知道時候退出,有時候還要知道循環(huán)體運(yùn)行多少次。在 循環(huán)體內(nèi)部也可以使用continue語句跳過本次循環(huán),進(jìn)入下一次循環(huán),或者用break語句退 出當(dāng)前層循環(huán)??偨Y(jié)與注意循環(huán)結(jié)構(gòu)中表達(dá)式的設(shè)計很重要。在for循環(huán)結(jié)構(gòu)我們經(jīng)常用到從0到x,循環(huán)體執(zhí)行x+1次,可以寫成for(i=0;i0;i-=3);這個循環(huán)語句的運(yùn)行結(jié)果一般不是我們想要的。把“=”不注意寫 成“=”也是容易造成死循環(huán)的結(jié)果。3 數(shù)組3.1 一維數(shù)組理解與測試:1)一維數(shù)組的

15、定義如下:類型說明符 數(shù)組名常量表達(dá)式如果定義時就進(jìn)行初始化, 常量表達(dá)式可以省略。 動態(tài)存儲的數(shù)組沒有初始化所有元素 的值都為隨機(jī)。靜態(tài)存儲的數(shù)據(jù)沒有初始化所有的元素自動賦0。2)一維數(shù)組名是一個指針常量,指向數(shù)組的首地址。由于是指針常量所以不能對其賦值, 只能當(dāng)指針引用。同理一個數(shù)組不能對另一個數(shù)組整體賦值。數(shù)組引用時下標(biāo)是從0開始計 算的。3)字符型數(shù)組初始化可以直接賦值字符串。char s= Happy”;或者char s=”Happy”;。 總結(jié)與注意數(shù)組引用時下標(biāo)不要越界,字符串?dāng)?shù)組初始化時,數(shù)組元素個數(shù)要比字符串多一個,因 為字符串結(jié)束有個“n”符,否則越界就會發(fā)生預(yù)料不到的結(jié)果

16、。如下:main ()char a8=abcdefgh;prin tf(%s,a);getch();輸出結(jié)果:abcdefghamain ()int a2,i;for(i=0;i8;i+)scan f(%d, &ai);getch();上面這個代碼當(dāng)輸入字符超過2個時可能出現(xiàn)無法運(yùn)行的結(jié)果??偨Y(jié)與注意數(shù)組名作為函數(shù)參數(shù)時傳遞給形參的是數(shù)組的指針,而且在子函數(shù)中無法用sizeof取得 數(shù)組的大小,所以有需要時可以用另一個參數(shù)傳遞數(shù)組的大小。數(shù)組作為形參時可以寫成int f(int a)或者int f(int * a)或者int f(int a10),他們?nèi)叨家粯拥模驗(yàn)閷τ谥羔榿碚f“”

17、等 效于“”,數(shù)組做形參不會傳遞數(shù)組大小,int a10等效于int a。數(shù)組作為實(shí)參時可以寫成f(a)或者f(&a0)或者,因?yàn)閍0的地址就是數(shù)組的首地址。但是要注意f(a10)將是把a(bǔ)10作為實(shí)參傳遞過去,a10的值賦值給指針使用是危險的。3.2 多維數(shù)組理解與測試:多維數(shù)組和一維數(shù)組相似, 只是使用了多個下標(biāo)。 多維數(shù)組其實(shí)可以理解為數(shù)組的元素 又是一個數(shù)組。例如,二維數(shù)組可以保存一個矩陣,三維數(shù)組可以保存多個矩陣。1)函數(shù)6.1 函數(shù)的定義和調(diào)用理解與測試:1)函數(shù)定義一般格式如下函數(shù)類型 函數(shù)名(形參表)聲明部分;語句部分;return表達(dá)式;聲明部分必須是放在函數(shù)的最前面,

18、如果放在語句中則編譯不能通過。2)值參數(shù)是指,將實(shí)際參數(shù)的值傳遞到函數(shù)的形式參數(shù)中,這也是參數(shù)默認(rèn)傳遞方式。 函數(shù)調(diào)用中發(fā)生的數(shù)據(jù)傳遞是單向的,即只能把實(shí)際參數(shù)的只傳遞給形式參數(shù),在函數(shù)調(diào)用 過程中,形式參數(shù)發(fā)生改變,而實(shí)際參數(shù)中的值不會發(fā)生變化(形式參數(shù)可與實(shí)際參數(shù)同名)。 引用參數(shù)是將實(shí)際參數(shù)的地址傳遞給函數(shù)的形式參數(shù)??偨Y(jié)與注意形參必須是變量,用于接收實(shí)參傳遞過來的值。實(shí)參可以常量、變量、表達(dá)式、函數(shù) 調(diào)用等,無論實(shí)參是何種類型的量,在函數(shù)調(diào)用時都必須有確定的值。實(shí)參與形參,數(shù)量和 類型要能一一對應(yīng)。函數(shù)如果在定義前使用,或者在其他文件中。那么必須先聲明,再使用。 函數(shù)運(yùn)行的時候是根據(jù)形

19、參類型去讀寫形參變量的,而傳遞過來的實(shí)參會根據(jù)函數(shù)聲明里的形參類型進(jìn)行類型轉(zhuǎn)換。如果聲明的函數(shù)沒有形參列表則傳遞的實(shí)參無法進(jìn)行類型轉(zhuǎn)換 就直接把代表實(shí)參的二進(jìn)制碼直接復(fù)制給形參。如果實(shí)參和形參的數(shù)據(jù)類型不對,而函數(shù)運(yùn) 行時又是根據(jù)自己的形參類型去讀取形參變量的,所以就會發(fā)生讀取出錯,嚴(yán)重的會使程序 停止。聲明返回值類型是把數(shù)據(jù)自動轉(zhuǎn)換成相應(yīng)的類型才返回給調(diào)用者。聲明函數(shù)的返回值和 定義函數(shù)時的返回值不一樣編譯時會提示類型出錯。在使用前沒有聲明或者聲明的函數(shù)沒有 聲明返回值則編譯時默認(rèn)的返回值都是int型,若該函數(shù)定義時聲明的返回值不是int型,編 譯器就也會提示類型錯誤。大多數(shù)C語言實(shí)現(xiàn)都是通

20、過函數(shù)main的返回值來告訴操作系統(tǒng)該函數(shù)是否執(zhí)行成功。 一般是返回0表示成功,返回其他值則表示失敗。如果main中沒有return 0;返回的是一個int型數(shù)值,但是不能保證值為0。6.1 局部變量和全局變量理解與測試:1)全局變量也叫外部變量,它是定義在函數(shù)外部。它不屬于那個函數(shù),而屬于一個源程 序文件。局部變量是定義在函數(shù)內(nèi)部,可以在函數(shù)的聲明中定義,也可以在一個語句塊中定 義。變量的作用范圍都是相對于同一層次來講的。例如函數(shù)有聲明變量,在函數(shù)的語句塊內(nèi) 又有定義相同名稱的變量, 則起作用的是語句塊內(nèi)的變量, 雖然它們名稱相同但是互不影響 如下面的代碼:int k = 10;void f

21、(int i)int k = i;k+;printf(%dn,k);main()int k;printf(%dn,k);f(10);for(k=0;k1)分析:像這種有遞推公式的就有很明確的遞推關(guān)系。我們的目的是要求n!,我們只需要兩步,第一步是把n!看成n*(n-1)!。第二步求(n-1) !。由于n!和(n-1) !都是求某 一個數(shù)的階乘,所以調(diào)用函數(shù)本身來處理(n-1)!。我們的思路知道此為止,不要在一直想下面 怎么處理,程序會按我們這思路自己往下遞推的。程序設(shè)計:f(i nt n)一、if(n=1|n=0) n!=1; /設(shè)計邊界二、n!= n*f(n-1);利用跟被包含的下一個同概念

22、函數(shù)計算這里千萬不要感覺f()沒有寫完就不能用,其實(shí)遞歸函數(shù)方便的 就可以隨便大膽的調(diào)用“自己”。代碼如下:double fact(i nt n);double fact1(i nt n);main ()int n;void hanio(int n,char a,char b,char c)if(n=1)printf(%c-%cn,a,b);elsehanio(n-1,a,c,b);printf(%c-%cn,a,b);hanio(n-1,c,b,a);/* 遞歸函數(shù)出口 */*利用 C 把 n-1 個片從 A 移到 B */* 利用 B 把 n-1 個片從 C 移到 A */printf(I

23、nput n:);scanf(%d,&n);printf(%d! = %.0fn,n,fact(n); printf(%d! = %.0fn,n,fact1(n); getch();double fact(int n)double f;if(n=1|n=0)/遞歸函數(shù)出口f = 1;elsef = n*fact(n-1);return f;漢諾塔問題:分析:要把A上的n個盤借助C搬到B上,我們的只需要兩步。第一步是把n-1個盤搬 到C上,再把A上的最后一個盤搬到B。第二步是把C上的n-1個盤借助A搬到B上。由 于把n個盤和把n-1個盤的規(guī)律相同,所以可以直接調(diào)用函數(shù)本身。代碼如下:vo

24、id hanio(int n,char a,char b,char c);main()int n;printf(Input the number of disks:); scanf(%d,&n);printf(The steps for %d disks are:n,n); hanio(n,A,B,C);getch();九連環(huán)解法:分析:我們這邊設(shè)計是可以解n連環(huán)的程序。九連環(huán)有個規(guī)律是要解或上第n個環(huán)必須解去n-1個環(huán)。我們解n個環(huán)只需要分成兩步來處理,第一步就是把解下1個環(huán)。第二步就是把剩下n-1個環(huán)用解n個環(huán)的函數(shù)來處理。解一個環(huán)的過程是些解下n-2個環(huán),再把第n個環(huán)解下,再安上

25、n-2個環(huán)(剩下部分要都是未解開的環(huán))。安n個環(huán)的步驟過程和解n個 環(huán)的步驟過程相似。代碼如下:#include Stdio.h#include Conio.hstatic int upstep = 0;static int downstep = 0;void UpRing(int n); /* 加上函數(shù)說明,否則編譯將會出一點(diǎn)小錯誤 */void DownRing(int n) /* 下環(huán)的邏輯就體現(xiàn)在這里 */if(n2) DownRing(n-2);printf(DW:%dt,n);+downstep;if(n2) UpRing(n-2);if(n1) DownRing(n-1);voi

26、d UpRing(int n) /* 上環(huán)的邏輯則體現(xiàn)在這里 */if(n1) UpRing(n-1);if(n2) DownRing(n-2);printf(UP:%dt,n);+upstep;if(n2) UpRing(n-2);main()int n;scanf(“%d”,&n);puts(Starting.);DownRing(n);puts(nEnding.);printf(nup = %dtdown = %dn,upstep,downstep);getch();迭代法也稱輾轉(zhuǎn)法,是一種不斷用變量的舊值遞推新值的過程,跟迭代法相對應(yīng)的是 直接法,即一次性解決問題。迭代法又分為

27、精確迭代和近似迭代。二分法”和牛頓迭代法”屬于近似迭代法。迭代法的思路和遞推法相反,迭代是從開始往后面推導(dǎo)。例如計算n!用迭代法如下:double fact1(i nt n)double f=1;int i;if(n=0)return 1;elsefor(i=1;i=n ;i+)f = f*i;return f;總結(jié)與注意用遞歸法的步驟是:一、把一個事物截去一部分剩下的的部分還是不是該事物如果是 就可用遞推函數(shù)來求解。二、找到截去一部分(剩下的概念上還是該事物)的方法。三、需 要把事物截取成多部分函數(shù)實(shí)現(xiàn)就可以分成兩步,首先是用上面的方法把事物截去一部分, 最后就是把剩下的部分用這個截去多段事

28、物的函數(shù)本身處理。遞歸函數(shù) F遞歸函數(shù)的運(yùn)行是一個不斷遞推的過程,每一次遞推都要把數(shù)據(jù)壓入棧,如果遞推的 步驟過多可能就會使棧溢出。所以能用迭代盡量用迭代,一般來說能寫出遞推式的都可以用 迭代。double fact1(i nt n)double f=1;int i;if(n=0)return 1;elsefor(i=1;i=n;i+)f = f*i;return f;2)指針6.2 指針與簡單變量理解與測試:簡單的講指針就是地址。指針變量的定義如下:基本類型*指針變量名;指針定義完最好都進(jìn)行初始化,初始化值可以為NULL。因?yàn)闆]有初始化的指針指向的 地址時隨機(jī)的,如果程序有引用是很容易出錯的

29、。總結(jié)與注意指針變量指向變量的首地址,指針引用指向的變量時是根據(jù)自己的類型來取變量值的,所以不能將不同類型的變量賦值個同一個指針,例如把一個整形指針賦值個符號指針,引用 符號型指針指向的變量時只是整形的低字節(jié)。6.2 指針與數(shù)組理解與測試:數(shù)組名就是一個指向數(shù)組首地址的指針常量。對于指針數(shù)組符號相當(dāng)于指針符號*,所以數(shù)組元素的地址有下面幾種表示:&a0.&aia.a+ipa.pa+i從技術(shù)上可以說數(shù)組就相當(dāng)于指針,但是在聲明一個數(shù)組,C語言編譯時會分配一段固 定的連續(xù)空間,而聲明一個指針卻不會。實(shí)際上C語言只有一維數(shù)組。多維數(shù)組其實(shí)可以理解為指針數(shù)組和普通數(shù)組的結(jié)合例如,cha

30、r a25;可以理解為一個char *a2數(shù)組,里面的每個元素分別指向一個char b5數(shù)組。在二維數(shù)組x中,數(shù)組名x表示數(shù)組的首地址,xi表示一個一維數(shù)組的名稱, (也就是 說xi不保存元素值),它只是一個地址。x和xi的值相等,但是*a!=*a0,因?yàn)閍是一個 二維數(shù)組首地址指針,a0一個一維數(shù)組首地址指針,引用它們指向的變量時會根據(jù)自己類型 性質(zhì)定義變量的類型性質(zhì)。如下代碼:void main()char a26=Hello,World;char * p;p = a;if(a=a0)printf(a=a0n);if(*a=*a0)printf(*a=*a0n);if(*p=*a0)pri

31、ntf(*p=*a0n);printf(%dn,sizeof(a);printf(%dn,sizeof(a0);getch();運(yùn)算結(jié)果:a=a0*p=*a0126xi表示數(shù)組的首地址,xij表示數(shù)組xi的第j+1個元素的值,&xij返回數(shù)組xi的 第j+1個元素的地址。也可以使用*(xi+j)的方式表示第j+1個元素的值,而*(xi+j)又可表示 為*(*(x+i)+j)。指針的運(yùn)算:賦值、間接運(yùn)算、求地址、遞增、遞減、求差、比較。指針加上后減去 一個整數(shù)偏移的長度等于這個整數(shù)乘以指針?biāo)笖?shù)據(jù)類型的長度。如下面的代碼:int main()unsigned int i;unsigned

32、 int *p = &i;printf(%d %d,p,p+1);getch();運(yùn)行輸出:-58-566.2 指針與字符串理解與測試:在C系統(tǒng)內(nèi)部字符串當(dāng)作一個一維數(shù)組, 在內(nèi)存中連續(xù)存放。 結(jié)尾存放字符串結(jié)束 符, 就是ASCII碼為0的空字符 0, 所以字符串常量實(shí)質(zhì)上是指向該字符串首字符的指針常 量。 如char * p =“point”。數(shù)組名就是存放數(shù)組的首地址,如char sa=”array”;。因?yàn)樽址褪侵羔槼A浚?使用指針數(shù)組來存放字符串指針常量可以方便操作多個 字符串。由于數(shù)組名也是一個指針常量, 所以指針數(shù)組名是一個指向指針的指針, 可以用“*” 來讀取他被

33、指向的變量。例如下面的代碼:void main()char * a2=Hello,World;printf(%sn,a0);printf(%cn,*a);getch();輸出的結(jié)果是:HelloH字符串出來函數(shù)主要有輸入輸出函數(shù):scanf(),printf(),gets(),puts。專門字符串出 來函數(shù):strcpy(目的字符串,原字符串),目的字符串是字符串指針,原字符串可以是字符串 指針也可以是一個字符串常量。strcat(目的字符串,原字符串),把原字符串中的字符串連 接到目的字符串中字符的后面,并刪去原字符串后面的字符串結(jié)束符。本函數(shù)返回的是目的字符串的首地址。strcmp(字符串

34、1,字符串2),按ASCII碼順序比較兩個字符串,字符串1等于字符串2返回0,大于返回1,小于返回-1。strlen(字符串),計算字符串長度,不包括 結(jié)束符。輸入命令時,在可執(zhí)行文件(命令)名的后面可以跟一些參數(shù),這些參數(shù)被稱為命令行參數(shù)。主函數(shù)mian(int argc,char * argv);有兩個參數(shù),第一參數(shù)argc接受命令行參數(shù)(包 括命令名)個數(shù)。第二個參數(shù)argv是個指針數(shù)組,接受以字符串常量形式存放的命令行參數(shù)(命令名本身也作為一個參數(shù))。例如下面的代碼(文件名:test.exe):int main(int a,char *v)int k,s=0;for(k=1;k”運(yùn)算符

35、來訪問其成員,這邊其實(shí)是訪問結(jié)構(gòu) 體指針?biāo)赶虻慕Y(jié)構(gòu)體的成員,因?yàn)榻Y(jié)構(gòu)體指針也和其他變量的指針相似,指向的是結(jié)構(gòu)體 存儲單元的首地址。結(jié)構(gòu)體指針引用成員的一般格式如下:結(jié)構(gòu)體指針-成員名 或(*結(jié)構(gòu)體指針).成員名總結(jié)與注意結(jié)構(gòu)體類型與結(jié)構(gòu)體變量是不同的概念,不要混同。只能對變量賦值、存取或運(yùn)算,而 不能對一個類型賦值、存取或運(yùn)算。在編譯時,對類型時不分配空間的,只對變量分配空間。結(jié)構(gòu)體數(shù)組理解與測試:結(jié)構(gòu)體作為一種數(shù)據(jù)類型也可定義數(shù)組,用結(jié)構(gòu)體定義的數(shù)組每個元素都是一個結(jié)構(gòu)體 變量。結(jié)構(gòu)體數(shù)組的定義、引用和普通結(jié)構(gòu)體變量相同。總結(jié)與注意在測試的過程中發(fā)現(xiàn)使用結(jié)構(gòu)體數(shù)組存在下面問題:int m

36、ain()int i = 0;struct studentfloat grade2;st2=1,2,1,2;scanf(%f,&sti.grade0);printf(%f,sti.grade0);getch();運(yùn)行后窗口只是一閃下。如果在scan f();不要用變量作為數(shù)組下標(biāo)程序可以正常運(yùn)行。這 應(yīng)該是scanf();語句的一個bug。鏈表理解與測試:動態(tài)內(nèi)存分配函數(shù):void * mallo(unsigned size)在內(nèi)存的動態(tài)存儲區(qū)中分配一連續(xù)空間,其長度為size。成功,返回指向內(nèi)存空間首地址的指針。失敗則返回NULL。返回類型(void*)是通用指針的一個重要用途。vo

37、id * calloc(unsigned n,unsigned size)在內(nèi)存的動態(tài)存儲區(qū)中分配n個連續(xù)空間,每一存儲空間長度為size,分配后把存儲塊 里初始化為0。成功,返回指向內(nèi)存空間首地址的指針。失敗則返回NULL。void free(void *ptr)釋放有動態(tài)存儲分配函數(shù)申請到的整塊內(nèi)存空間。void * realloc(void * ptr,unsigned size)更改以前的存儲分配。失敗返回NULL。成功返回指向分配到的存儲塊首地址指針。更 改后如果size小于原塊大小,則內(nèi)容為原塊前size范圍的數(shù)據(jù),如果新塊更大,則原有數(shù)據(jù) 存在新塊的前一部分。更改成功后不要再用原

38、來的指針去操作存儲塊。鏈表是一種動態(tài)分配存儲單元的結(jié)構(gòu)。鏈表由若干個節(jié)點(diǎn)構(gòu)成,每個節(jié)點(diǎn)具有相同的 數(shù)據(jù)類型,并且每個節(jié)點(diǎn)都有一個可以指向下一個節(jié)點(diǎn)的指針(指針域)。因此線性鏈表不 需要連續(xù)存放。鏈表的基本操作有:建立、查找、插入、刪除、輸出等。下面具體介紹各操作。建立:定義變量head、tail、pnew。head定義一個頭指針作為頭結(jié)點(diǎn);tail:定義一個尾指針作為尾結(jié)點(diǎn);pnew:定義一個指針,代表新插入的結(jié)點(diǎn)。鏈表的建立是一個從無到有的過程。因此head = NULL; tail = NULL;新申請結(jié)點(diǎn)pnew=(struct linknode *)malloc(sizeof(stru

39、ct linknode) /分配內(nèi)存/執(zhí)行后都要判斷pnew是否為空。pnew-no=1;或者seanf(“d”,&pnew-no); /設(shè)置數(shù)據(jù)域pnew-next=NULL;/沒有指向下個結(jié)點(diǎn) 建立鏈表的示范代碼如下:struet linkonde * Create()struet linkonde *head=NULL,*tail=NULL,*pnew;int no;float seore;while(1)printf(input the new no and seore:n);seanf(%d%f,&no,&seore);if(no=0)/學(xué)號為零時退出brea

40、k;pnew = (struet linkonde *)malloe(sizeof(struet linkonde);if(pnew=NULL)printf(no enough memory!n);return(NULL);pnew-no = no;pnew-seore = seore;pnew-next = NULL;if(head=NULL)head = pnew;elsetail-next = pnew;tail = pnew;return head;查找:示范代碼如下:struct linkonde *Search(struct linkonde *head,int n)int i=1

41、;struct linkonde *p = head;for(p=head;p!=NULL;p=p-next,i+)/空指針指用間接運(yùn)算符號運(yùn)算得到的是0if(i=n)break;if(inext = p-next;p-next = r;刪除:鏈表刪除的時候遵循先接后刪的原則。下面為示范代碼:void Delete(struct linkonde * p)struct linkonde * q;q = p-next;p-next = q-next;free(q);輸出:下面為示范代碼:void Display(struct linkonde * head)struct linkonde *p;

42、for(p=head;p!=NULL;p=p-next)printf(Num:%d,Score:%.2fn,p-no,p-score);總結(jié)與注意動態(tài)內(nèi)存分配為了保證是成功的,執(zhí)行完要判斷返回值是否不為NULL共用體理解與測試:共用體和結(jié)構(gòu)體的區(qū)別就是共用體的成員使用的是同一段內(nèi)存空間。 共用體定義用的關(guān) 鍵字是union。共用體的定義、引用都和結(jié)構(gòu)體相似。需要注意的是共用體一次只能對一個成 員變量進(jìn)行賦值,多次賦值只有最后一次賦值的共用體成員的值有效,之前賦值的成員值將 被覆蓋。需要不同時用多個不用類型變量,使用公共用體可以節(jié)省存儲空間。枚舉類型理解與測試:定義一個枚舉類型相當(dāng)于定義了一個數(shù)

43、組常量, 每個元素都可以由我們自定義一個名稱。 枚舉類型的定義和結(jié)構(gòu)體類型定義相似,使用的關(guān)鍵字是enum。同樣也可以定義枚舉數(shù)組、 枚舉指針等。例如:enum weekdays un,m ou,tue,wed,thu,fri,sat;enum weekday a,b,c2=sun,mou;enum weekdays un ,mou,tue,wed,thu,fri,sata,b,*c=&a;enu ms un,m ou,tue,wed,thu,fri,sata,b,c;總結(jié)與注意1)枚舉值(枚舉元素)是常量,在程序中可以作為普通常量使用。枚舉元素本身有系統(tǒng)定義了一個表示序號的數(shù)值, 從

44、0開始順序定義0,1,2.如果在定義枚舉類型時指定元素的值也可以改變枚舉元素的值。例如:enum weekdeysun=7,mon=1,tue,wed,thu,fri,sat;其實(shí)枚舉變量就是整數(shù)型變量,可以當(dāng)成整數(shù)型變量使用。邏輯上講要把一個整數(shù)賦值 給枚舉變量應(yīng)該使用強(qiáng)制類型轉(zhuǎn)換。如:day = (eu nm weekday)2;但實(shí)際很多編譯器直接就把枚舉變量視為整型變量。2) 在需要使用多個常量時可以使用宏定義也可以定義一個枚舉類型,根據(jù)自己的需要修 改枚舉元素的值(只能是正整數(shù))。自定義類型理解與測試:1)C語言允許給已有的數(shù)據(jù)類型起一個別名。一般格式如下;typedef已有類型名

45、別名為了區(qū)分起見,別名一般采用大寫字母。2)使用#define宏定義給數(shù)據(jù)類型取別名一般是基本的數(shù)據(jù)類型,對于像結(jié)構(gòu)體這種高 級變量類型就不方便了,所以結(jié)構(gòu)體等高級變量類型一般使用typedef定義別名。預(yù)處理命令理解與測試:1)C語言的預(yù)處理命令包括:宏定義、文件包含、條件編譯、以及其他預(yù)處理命令。2)宏定義是用自定義字符串替代程序中的字符。分為不帶參數(shù)和帶參數(shù)兩種。不帶參數(shù) 宏定義一般格式如下:#define標(biāo)識符 字符串 標(biāo)識符也稱為宏名,字符串也稱為宏體,宏體可以省略,例如,編譯頭文件省略宏體。 在預(yù)編譯的時候把程序出現(xiàn)宏名的地方都用后面的宏體替代。對于宏體中有參數(shù)的我們就可以使用帶參

46、數(shù)的宏定義,一般格式如下:#define標(biāo)識符(參數(shù)表) 字符串宏定義可以放在程序中的任何一行,需要終止宏的作用域可以用#undef。格式為:#undef字符串”#”可以將一個宏參數(shù)轉(zhuǎn)換成字符串字面量。 ”#”運(yùn)算符可以將兩個記號(例如標(biāo)識符)“粘”在一起成為一個記號。例如下面的代碼:#define PRINT(a,b) (printf(%#an,(b)#define GENERIC_MAX(type) type type#_max(type x,type y)return xy?x:y;GENERIC_MAX(int); /* 定義一個兩數(shù)值比較大小函數(shù),返回值為整型 */GENERIC_M

47、AX(float); /* 定義一個兩數(shù)值比較大小函數(shù),返回值為單精度型 */main()int i=5,j=4;float a=5.3,b=6.5;PRINT(d,int_max(i,j);PRINT(f,float_max(a,b);getch();運(yùn)行輸出:56.5文件包含有兩種格式。使用“”是直接到系統(tǒng)指定的”文件包含目錄“查找被包含的文件。使用“ ”是先到當(dāng)期目錄下查找被包含文件,如果沒有再到系統(tǒng)指定的”文件包 含目錄“查找。一般使用雙引號比較保險。雙引號之間還可以指定包含文件的路徑。例如:#in clude”c:prgp1.h”。條件編譯有三種。格式和注意事項(xiàng)如下表:類型#if#e

48、n dif#ifdef#e ndif#ifndef#e ndfr#if 條件 1#ifdef 宏名#ifndef 宏名程序段 1程序段 1程序段 1#elif 條件 2#else#else程序段 2程序段 2程序段 2格式#else程序段 n#en dif#en dif#en dif1、#elif 不能寫成在#ifdef 和#else 之間和 #ifdef#endif 用法注意事項(xiàng)#else if。2、#if 后面是一個常 里表達(dá)式可以不加 括號。可以加多個#elif 命 令。相似。1、 可以沒有#else (#elif),但必須有#endif 作為結(jié)尾。2、 每個命令單獨(dú)占一行。示范代碼:i

49、nt mai n()#define PRINT(a,b) printf(%#an,(b)#defi ne OUTPUT 2#if OUTPUT = 1PRINT(s,o ne);#elif OUTPUT = 2PRINT(s,two);#elsePRINT(s,three);#en dif#defi ne END#ifdef END PRINT(s,END!);#elsePRINT(s,Go ahead!);#en difgetch();運(yùn)行輸出:twoEND!總結(jié)與注意:1)C語言中一般用大寫字母定義宏名,宏名內(nèi)千萬不能出現(xiàn)空格,字符串太長行尾可以 用“ ”續(xù)行符,結(jié)尾不能用分號“;”。一般

50、把需要用到的宏定義統(tǒng)一放在一個頭文件內(nèi)。宏定義可以嵌套但不能遞歸定義。如下:#defineR2#defineK2*R#defineMM*2/遞歸定義錯誤2)帶參數(shù)的宏在使用時,參數(shù)大多是表達(dá)式,宏內(nèi)容本身也是表達(dá)式,為了避錯誤,因 此不但需要將整個宏內(nèi)容括號起來,還要把宏參數(shù)也用()括號起來。例如:#define PRINT(a,b) (printf(%#an,(b)PRINT(d,54);要注意, 宏體中雙引號內(nèi)的字符是不當(dāng)成參數(shù)處理的, 空的雙引號在預(yù)處理中會被刪去, 如上面的PRINT(d,54);替換后是printf(%”d”h”,(54);空雙引號處理中會被刪去,貝U變成printf

51、(“%dn”,(54);要注意宏定義中的”號。在C語言中”符號可作為行結(jié)尾符,在雙引號內(nèi)可以作為 轉(zhuǎn)義符號使用。大部分編譯處理時把 ”放在行尾貝當(dāng)成行結(jié)尾符,在雙引號內(nèi)貝認(rèn)為是轉(zhuǎn)義 符號。宏在預(yù)編譯時的處理步驟如下:在文件中查找非C語言的關(guān)鍵字或運(yùn)算符號字符串;找到宏名貝去宏定義列表中查找該宏名對應(yīng)的宏體;如果是帶參數(shù)的則先實(shí)際參數(shù)帶到宏體中,再用宏體替換。注意,宏體中雙引號內(nèi)的字符不認(rèn)為是參數(shù),所以參數(shù)是不能在雙引號內(nèi)的,若參數(shù)需要加雙引號貝可以用”#”加在參數(shù)前面,編譯時會把實(shí)參加上雙引號代入形參。若參數(shù)也是一個宏名則繼續(xù)到宏定義列表中查找相應(yīng)的宏體,從外往內(nèi)查找再從內(nèi)往外替換(有點(diǎn)類似處

52、理遞推函數(shù))。替換時如果參數(shù)前面有”#”符號,貝實(shí)參加上雙引號代入宏體中,如果宏體中有 ”#”符號則把左右兩個記號(例如標(biāo)識符)“粘”在一起成為一個記 號,再刪除空雙引號,從內(nèi)往外直到把整個語句的宏名全部替換調(diào)。條件編譯一般可以用于移植時選擇編譯需要的程序。在編寫程序中經(jīng)常用的輸出語句, 而正式發(fā)布使用的時候又不需要這些輸出語句,我們就可以利用條件編譯,代碼如下:#ifdef RELEASE#define PRINT(a,b) printf(%#an,(b)#else#define PRINT(a,b) while(O)#en difint mai n()PRINT(s,Hello World

53、!);getch();7 文件7.1 文件的基本操作理解與測試:攙挀 戀 愀攙 挀攙 攙攙挀攀戀愀 一甀洀戀攀爀攀攙開挀挀攀 攀戀昀 昀攙 愀攀攙 攀攀 一甀洀戀攀爀攀攙開昀挀挀戀攀挀昀 愀 戀挀攀挀 一甀洀戀攀爀攀攙開攀攀攀愀挀攀攀文件”是指一組相關(guān)的有序集合。從用戶的角度看,文件可以分為普通文件和設(shè)備文件。從文件的編碼方式看,文件可分為ASCII碼文件和二進(jìn)制碼文件。攙挀 戀 愀攙 挀攙 攙攙挀攀戀愀 一甀洀戀攀爀攀攙開挀挀攀 攀戀昀 昀攙 愀攀攙 攀攀 一甀洀戀攀爀攀攙開昀挀挀戀攀挀昀 愀 戀挀攀挀 一甀洀戀攀爀攀攙開攀攀攀愀挀攀攀在C語言的編譯系統(tǒng)定義了一個FILE結(jié)構(gòu)體變量,用于保存

54、操作文件的有關(guān)信息typedef structshortlevel;/緩沖區(qū)使用量un sig nedflags;/文件狀態(tài)標(biāo)志charfd;文件描述符shortbsize;/緩沖區(qū)大小un sig ned char*buffer;文件緩沖區(qū)的首地址un sig ned char*curp;/指向文件緩沖區(qū)的工作指針un sig ned char hold:/其他信息un sig nedistemp;shorttoke n;FILE攙挀 戀 愀攙 挀攙 攙攙挀攀戀愀 一甀洀戀攀爀攀攙開挀挀攀 攀戀昀 昀攙 愀攀攙 攀攀 一甀洀戀攀爀攀攙開昀挀挀戀攀挀昀 愀 戀挀攀挀 一甀洀戀攀爀攀攙開攀攀攀愀

55、挀攀攀件的基本操作函數(shù)如下:打開關(guān)閉:文件指針=fopen(文件名,文件打開方式);出錯返回NULL文件的打開方式文件使用方式 1意義“t ”只讀打開一個文本文件,只允許讀數(shù)據(jù)at?wt只寫打開或建立一個文本文件,只允許寫數(shù)據(jù)at ”追加打開一個文本文件,并在文件末尾寫數(shù)據(jù)“b ”只讀打開一個一進(jìn)制文件,只允許讀數(shù)據(jù)Wb只寫打開或建立一個二進(jìn)制文件,只允許寫數(shù)據(jù)ab追加打開一個二進(jìn)制文件,并在文件末尾寫數(shù)據(jù)a?rt+讀寫打開一個文本文件,允許讀和寫a ,?wt+讀寫打開或建立一個文本文件,允許讀寫a .at+讀寫打開一個文本文件,允許讀,或在文件末追加數(shù)據(jù)a. ?rb+讀寫打開一個二進(jìn)制文件,允許讀和寫a . ”wb+讀寫打開或建立一個二進(jìn)制文件,允許讀和寫ab+讀寫打開一個二進(jìn)制文件,

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論