計(jì)算機(jī)軟件基礎(chǔ):10第三章C語(yǔ)言及編程規(guī)范_第1頁(yè)
計(jì)算機(jī)軟件基礎(chǔ):10第三章C語(yǔ)言及編程規(guī)范_第2頁(yè)
計(jì)算機(jī)軟件基礎(chǔ):10第三章C語(yǔ)言及編程規(guī)范_第3頁(yè)
計(jì)算機(jī)軟件基礎(chǔ):10第三章C語(yǔ)言及編程規(guī)范_第4頁(yè)
計(jì)算機(jī)軟件基礎(chǔ):10第三章C語(yǔ)言及編程規(guī)范_第5頁(yè)
已閱讀5頁(yè),還剩23頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

PAGE1《計(jì)算機(jī)軟件基礎(chǔ)》多媒體教程第十講第三章 C語(yǔ)言及編程規(guī)范3.1基本問(wèn)題3.1.1基本數(shù)據(jù)類型與存儲(chǔ)空間變量定義與存儲(chǔ)空間定義一個(gè)變量,表示確定了該變量將占有內(nèi)存單元的空間大小(以字節(jié)byte為單位)。 例如: inta; longb; 表示定義int變量a和long變量b,將各自占有規(guī)定的內(nèi)存單元。同一種數(shù)據(jù)類型,在不同的計(jì)算機(jī)中所占字節(jié)數(shù)可能不同?;緮?shù)據(jù)類型不同計(jì)算機(jī)所占字節(jié)數(shù)本課程約定字節(jié)數(shù)字符型char1or21整數(shù)型int1,2or42short1or22long2,4or84浮點(diǎn)型float2or44double4or88int稱為缺省整型,依不同的計(jì)算機(jī)而定,它可能等同于short也可能等同于long,因此重要的變量要避免定義為int類型。變量引用及其數(shù)值 引用變量是指存取內(nèi)存單元中的值(數(shù)據(jù))。在內(nèi)存存儲(chǔ)的總是二進(jìn)制數(shù)據(jù),也是引用變量進(jìn)行計(jì)算時(shí)用的格式。但是給定不同的輸出格式輸出變量時(shí),需要將內(nèi)部二進(jìn)制格式按照不同的數(shù)據(jù)類型轉(zhuǎn)換為輸出格式。(可參閱課本第314頁(yè)的附錄A:ASCII字符集)【例3-1.1】定義 charc; 內(nèi)存數(shù)據(jù)為(01000001)二=(101)八=(65)十 則執(zhí)行打印語(yǔ)句為 printf(“c(dec)=%d,c(char)=%c\n”,c,c); 運(yùn)行結(jié)果為 c(dec)=65,c(char)=A帶符號(hào)的數(shù)據(jù)類型 整型和字符型存在有符號(hào)和無(wú)符號(hào)的差別,應(yīng)注意正確選用?!纠?-1.2】測(cè)試有符號(hào)和無(wú)符號(hào)的差別。 chara; 有符號(hào)字符型變量,省略signed unsignedcharb; 無(wú)符號(hào)字符型變量 a=b=0xFF; 存儲(chǔ)單元內(nèi)數(shù)值均為(11111111) printf(“a=%d,\tb=%d\n”,a,b); 得 a=-1, b=255 由于標(biāo)準(zhǔn)ASCII碼只用7位二進(jìn)制數(shù),0xFF用到第8位,成為擴(kuò)展的ASCII碼(非標(biāo)準(zhǔn)碼),在不同的計(jì)算機(jī)中用“%c”打印的字符不一定相同。內(nèi)存單元與存儲(chǔ)空間 由于在不同的計(jì)算機(jī)中一種數(shù)據(jù)類型的存儲(chǔ)空間所占字節(jié)數(shù)可能不同,所以通常在開始使用一臺(tái)計(jì)算機(jī)時(shí),可以使用運(yùn)算符sizeof來(lái)測(cè)試內(nèi)存單元所占的字節(jié)數(shù)。 例如,定義int變量a: inta=-1; 但是其存儲(chǔ)空間可能占1個(gè)、2個(gè)或者4個(gè)字節(jié)。測(cè)試方法是使用打印語(yǔ)句如下: printf(“sizeof(int)=%d\n”,sizeof(int)); 或者 printf(“sizeof(int)=%d\n”,sizeof(a)); sizeof既可測(cè)試數(shù)據(jù)類型的字節(jié)數(shù),也可測(cè)試變量的字節(jié)數(shù)。3.1.2類型轉(zhuǎn)換規(guī)則隱式(自動(dòng))轉(zhuǎn)換規(guī)則(從低向高自動(dòng)轉(zhuǎn)換) char(低)->int,short->long->float->double(高)【例3-1.3】隱式轉(zhuǎn)換示例 inti1,i2; floatf; f=i1+i2; (1) i2=f*i1; (2) (1)計(jì)算“i1+i2”時(shí),不轉(zhuǎn)換,它們的和轉(zhuǎn)換為float后賦給f。 (2)先將i1轉(zhuǎn)換為float,計(jì)算“f*i1”,獲得float型,然后再轉(zhuǎn)換為int后賦給i2。顯式(強(qiáng)制)轉(zhuǎn)換 采用顯式轉(zhuǎn)換,可以不需要去記住隱式轉(zhuǎn)換規(guī)則,以免出錯(cuò)。 例如,定義 inti=1; 則 i/3*3為0,而(float)i/3*3為0.99...9 又如,定義 inti1=3,i2; floata=3.5; 則 i2=a*(float)i1; 遵循顯式轉(zhuǎn)換:i2為10 i2=(int)a*i1; 遵循顯式轉(zhuǎn)換:i2為9 i2=a*i1; 遵循隱式轉(zhuǎn)換:i2為10 應(yīng)該盡量采用顯式轉(zhuǎn)換,而不要采用隱式轉(zhuǎn)換規(guī)則。3.2指針3.2.1指針的定義指針定義的格式 類型*變量; 例如: int*pa,*pb; float*pc; 表示定義pa和pb為整數(shù)型指針,pc為浮點(diǎn)型指針。 如果將以上定義改為: int*pa,pb; 則是錯(cuò)誤的定義方式。由于定義指針時(shí)的星號(hào)不能共享,因此結(jié)果只是將pa定義為指針,而pb定義為變量,并沒(méi)有定義為指針。指針的存儲(chǔ)單元 指針的類型實(shí)際是指它目標(biāo)的數(shù)據(jù)類型,而不是指針的數(shù)據(jù)類型。無(wú)論用什么數(shù)據(jù)類型定義指針,指針的存儲(chǔ)單元長(zhǎng)度在同一臺(tái)計(jì)算機(jī)中是相同的,指針?biāo)么鎯?chǔ)單元的類型都是unsignedlong(4個(gè)字節(jié))。因此所謂的指針類型實(shí)際上是指其目標(biāo)的數(shù)據(jù)類型,根據(jù)其類型可以是不同的字長(zhǎng)。 例如: char*pa; 定義字符型(char)指針pa short*pb; 定義浮點(diǎn)型(float)指針pb long**pc; 定義長(zhǎng)整型指針(long*)的指針pc 其中,pa,pb和pc的存儲(chǔ)單元長(zhǎng)度與目標(biāo)無(wú)關(guān),所占的存儲(chǔ)單元類型總是unsignedlong,占4個(gè)字節(jié)。3.2.2指針的含義 指針是一個(gè)變量,所以指針又稱指針變量。指針的用途 指針的存儲(chǔ)單元是用來(lái)存放地址的,該地址所指向的存儲(chǔ)單元稱為指針的目標(biāo)。例如: int*pa,a; 定義整數(shù)型指針pa和整數(shù)型變量a pa=&a; 令指針pa指向變量a(a成為pa的目標(biāo))指針的等價(jià)含義 指針與目標(biāo)的關(guān)系,可用以下任何一種表述,它們是互相等價(jià)的(包括同義命題): 指針指向目標(biāo)。 指針的目標(biāo)是它指向的變量。 指針存放其目標(biāo)的地址。(同義:指針的值為其目標(biāo)的地址) 通過(guò)指針可訪問(wèn)其目標(biāo)。(同義:通過(guò)指針可存取其目標(biāo)的值) 例如: int*pa; 定義pa為整數(shù)型指針(4字節(jié)) inta; 定義a為整數(shù)型變量(2字節(jié)) 則指針與目標(biāo)的等價(jià)表述為: pa指向a。 pa的目標(biāo)是a。 pa存放a的地址。 通過(guò)pa可存取a的值。3.2.3指向目標(biāo)指針指向目標(biāo)的含義 定義指針時(shí),只是定義了指針的存儲(chǔ)空間,但沒(méi)有給指針賦值。 定義指針不等于該指針已指向某個(gè)目標(biāo)。 只有指針的值為有效地址時(shí),才能說(shuō)指針指向目標(biāo)??罩羔?指針的值如果等于零,稱為空指針,也即該指針無(wú)目標(biāo)。 使指針的值等于零,稱為清零指針或指針清零。 C語(yǔ)言中的零地址用宏NULL表示。 例如: short*pa; 定義pa為整數(shù)型指針 pa=NULL; 令指針pa指向空,或稱pa為空指針指針的賦值 給指針賦以有效的地址(例如某個(gè)已知變量的地址),才能說(shuō)指針指向目標(biāo)?!纠?-2.1】指針賦值示例。 shorta,b[3],*pa,*pb; 定義變量和指針(定義空間) pa=&a; 令a成為pa的目標(biāo)(假定a地址為FF50) a=1111; 令a(pa的目標(biāo))為1111 pb=&b[1]; 令pb指向b[1](假定b[1]的地址為E0A1) *pb=4567; 使b[1]的值為4567(等價(jià)為b[1]=4567)內(nèi)存分配內(nèi)存分配與動(dòng)態(tài)存儲(chǔ)空間 程序中定義的變量,無(wú)論是動(dòng)態(tài)變量還是靜態(tài)變量,其存儲(chǔ)單元都有相應(yīng)的地址(位于用戶數(shù)據(jù)區(qū))。除此之外,在計(jì)算機(jī)系統(tǒng)中還提供了可以在程序運(yùn)行過(guò)程中動(dòng)態(tài)申請(qǐng)的存儲(chǔ)空間。通??梢杂脙?nèi)存分配類函數(shù)來(lái)申請(qǐng)動(dòng)態(tài)空間。內(nèi)存分配函數(shù)malloc 調(diào)用形式:malloc(size) malloc的功能是向系統(tǒng)申請(qǐng)size個(gè)字節(jié)數(shù)的存儲(chǔ)單元。如果系統(tǒng)中存在著這樣大小的單元,將返回一個(gè)非零值,表示該單元已為用戶進(jìn)程所有。malloc()的返回類型為char*,而實(shí)際申請(qǐng)所需的目標(biāo)類型可由用戶任意選定,所以應(yīng)該將其類型強(qiáng)制轉(zhuǎn)換。通常用指針指向這樣的動(dòng)態(tài)內(nèi)存空間(使指針指向目標(biāo))。 例如,定義short*pa;int*pb; 執(zhí)行動(dòng)態(tài)內(nèi)存分配: pa=(short*)malloc(sizeof(short)); 假設(shè)返回地址為0D40 pb=(int*)malloc(3*sizeof(int)); 假設(shè)返回地址為0D50 每次調(diào)用malloc函數(shù)后應(yīng)該測(cè)試其返回值。例如: if((pa=(int*)malloc(sizeof(int)))==NULL) exit(-1); 如果返回值為NULL,表示分配失敗(系統(tǒng)內(nèi)存已耗盡),這時(shí)若再要訪問(wèn)其目標(biāo),比如要求執(zhí)行語(yǔ)句:*pa=4; 則操作系統(tǒng)的內(nèi)存保護(hù)功能將發(fā)揮作用,令進(jìn)程異常中止,并給出以下常見的出錯(cuò)信息: “buserror”,“coredump”,“fragmentationviolation”,等等。內(nèi)存釋放函數(shù)free 調(diào)用形式:free(ptr) free的功能是用于釋放由ptr指向的(先前分配的)單元,歸還給操作系統(tǒng)。 雖然用free釋放動(dòng)態(tài)單元后,指針ptr的目標(biāo)已消失,但ptr的值不變,這時(shí)若還要訪問(wèn)其目標(biāo),則也將導(dǎo)致進(jìn)程出錯(cuò)(訪問(wèn)非法地址)。 動(dòng)態(tài)申請(qǐng)的單元必須一次釋放。比如用pb申請(qǐng)了3個(gè)int型的動(dòng)態(tài)空間,首地址為0D50,則釋放時(shí)應(yīng)該為“free(pb);”,指針pb指向的單元地址也必須為0D50,形如“free(pb[1]);”是錯(cuò)誤的(因?yàn)閜b[1]的值為0D52)。3.2.4訪問(wèn)目標(biāo)指針運(yùn)算符 指針運(yùn)算符包括取址符&和取值符*。 取址符&的作用是獲得變量的地址,如&x表示變量x的地址。 取值符*的作用是獲得目標(biāo)的數(shù)值,如*x表示指針x的目標(biāo)的值。【例3-2.2】指針運(yùn)算符示例一 inta,b,*pa; a=5; pa=&a; pa通過(guò)取址符&獲得a的地址 printf(”%d,%d\n”,a,*pa); *pa等價(jià)于a b=*pa; 等價(jià)于b=a; printf(”%d,%d,%d\n”,a,b,*pa); 運(yùn)行結(jié)果為: 5,5 5,5,5由指針指向連續(xù)的存儲(chǔ)單元【例3-2.3】指針運(yùn)算符示例二 int*pc,i,n=4; pc=(int*)malloc(sizeof(int)*n); for(i=0;i<n;i++) *(pc+i)=i+1; printf(“%d,%d\n”,pc[0],pc[3]); 其中,*(pc+i)等價(jià)于pc[i],通常我們?cè)敢馐褂胮c[i]的形式,即數(shù)組元素的形式。由指針指向的這種地址連續(xù)的存儲(chǔ)單元并不是C語(yǔ)言定義的數(shù)組,但是具有數(shù)組的特性。由于它們是通過(guò)動(dòng)態(tài)分配獲得的,因此可將其稱為動(dòng)態(tài)數(shù)組。 運(yùn)行結(jié)果為: 1,43.2.5字符串(數(shù)組和指針的應(yīng)用)字符串的數(shù)據(jù)類型 C語(yǔ)言沒(méi)有為字符串提供專用的數(shù)據(jù)類型,而是利用數(shù)組或動(dòng)態(tài)數(shù)組中連續(xù)的存儲(chǔ)單元存儲(chǔ)字符串。用字符串常量存儲(chǔ)字符串 例如,“Doit!”是一個(gè)字符串常量。 字符串的結(jié)束符‘\0’也占一個(gè)存儲(chǔ)單元。用字符數(shù)組存儲(chǔ)字符串 例如: chars0[7]={‘D’,‘o’,‘□’,‘i’,‘t’,‘!’,‘\0’};用指針的目標(biāo)存儲(chǔ)字符串,可簡(jiǎn)稱為用指針存儲(chǔ)字符串。 char*s,*t,*u; s=(char*)malloc(sizeof(char)*7); u=(char*)malloc(sizeof(char)*7); strcpy(s,”Doit!”); t=s; strcpy(u,s); 其中,s將目標(biāo)的地址復(fù)制給t,將目標(biāo)的值復(fù)制給u,兩者是不同的。字符串的賦值字符串復(fù)制 利用strcpy和strcat等函數(shù)將字符串復(fù)制給數(shù)組或者動(dòng)態(tài)數(shù)組。 函數(shù)strcpy(dst,src)的功能是將src復(fù)制到dst。 函數(shù)strcat(dst,src)的功能是將src附加到dst的后面。 例如,定義chars1[7];可有 strcpy(s1,”Doi”); strcat(s1,”t!”);按數(shù)組元素逐個(gè)賦值 例如,定義chars2[7];可有 s2[0]=’D’; s2[1]=’o’; s2[6]=‘\0’;初始化賦值 例如, chars3[7]=“Doit!”;字符串使用的常見問(wèn)題示例【例3-2.4】字符串使用示例一 #include<stdio.h> #include<stdlib.h> #include<string.h> main() { char*t,*u,*v; t=(char*)malloc(sizeof(char)*strlen("hello")); u=(char*)malloc(sizeof(char)*(strlen("hello")+1)); v=(char*)malloc(sizeof(char)*strlen("he")); strcpy(t,"helloyou"); strcpy(u,"helloyou"); strcpy(v,"helloyou"); printf("t=[%X]\tu=[%X]\tv=[%X]\n",t,u,v); printf("t=[%s]\tu=[%s]\tv=[%s]\n",t,u,v); } 在VC++的環(huán)境下,運(yùn)行結(jié)果為: t=[431C50] u=[431C10] v=[431BE0] t=[helloyou] u=[helloyou] v=[helloyou] 請(qǐng)分析輸出結(jié)果,并且提出應(yīng)該如何編程的方案?!纠?-2.5】字符串使用示例二 #include<stdio.h> #include<stdlib.h> #include<string.h> main() { chars0[6],s1[4],s2[2]; strcpy(s0,"hello"); printf("len=%d\ts0=[%s]\n",strlen("hello"),s0); strcpy(s2,"helloyou"); printf("s0=[%X],s1=[%X],s2=[%X]\n",s0,s1,s2); printf("s0=[%s],s1=[%s],s2=[%s]\n",s0,s1,s2); } 在VC++的環(huán)境下,運(yùn)行結(jié)果為: len=5 s0=[hello] s0=[12FF78],s1=[12FF74],s2=[12FF70] s0=[u],s1=[oyou],s2=[helloyou] 請(qǐng)分析輸出結(jié)果,并且提出應(yīng)該如何編程的方案。3.2.6指針和數(shù)組數(shù)組和指針的比較數(shù)組指針inta[3];int*pa;a為常量pa為變量a的值為數(shù)組首址pa值為目標(biāo)首址a=pa; /*非法賦值*/pa=a; /*合法賦值*/ 設(shè)數(shù)組a的首址為1000,令 pa=a; a[1]=15; 則 a+1,&a[1],pa+1,&pa[1] 均為1002 (a+1),a[1],*(pa+1),pa[1] 均為15 數(shù)值: a[1]<=>*(a+1) pa[1]<=>*(pa+1) 地址: &a[1]<=>a+1 &pa[1]<=>pa+1數(shù)組和指針的應(yīng)用【例3-2.6】庫(kù)函數(shù)strlen()的實(shí)現(xiàn)函數(shù)描述 函數(shù)名:strlen(s) 函數(shù)功能:返回字符串s中字符的個(gè)數(shù),不包括‘\0’。 形參說(shuō)明: (1) 數(shù)組形式 chars[]; 或者 (2) 指針形式 char*s;用數(shù)組形式實(shí)現(xiàn)形參的函數(shù)strlen(),程序?yàn)椋? intstrlen(s) chars[]; { inti=0; while(s[i]!=’\0’) i++; return(i); }用指針形式實(shí)現(xiàn)形參的函數(shù)strlen(),程序?yàn)椋? intstrlen(s) char*s; { inti; for(i=0;*s!=’\0’;i++) s++; return(i); }【例3-2.7】庫(kù)函數(shù)strcpy()的實(shí)現(xiàn)函數(shù)描述 函數(shù)名:char*strcpy(dst,src) 函數(shù)功能:將字符串從src復(fù)制到dst,包括‘\0’,返回dst的地址,即返回字符串的首地址。 形參說(shuō)明: (1) 數(shù)組形式 charsrc[],dst[]; 或者(2) 指針形式 char*src,*dst; 將src中的字符串復(fù)制到dst中,包括‘\0’,返回dst的地址。 將src目標(biāo)中的字符串復(fù)制到dst目標(biāo)中,包括‘\0’,返回dst的值。用數(shù)組形式實(shí)現(xiàn)形參的函數(shù)strcpy()用指針形式實(shí)現(xiàn)形參的函數(shù)strcpy()3.2.7多級(jí)指針多級(jí)指針和數(shù)組的定義 假設(shè)有以下定義: shorta[3], b[3][2],*c,**d,*e[3]; 表示定義了(一維)數(shù)組a,二維數(shù)組b,(一級(jí))指針c,二級(jí)指針d,以及指針數(shù)組e。多級(jí)指針和數(shù)組的存儲(chǔ)單元 假設(shè)通過(guò)以下語(yǔ)句動(dòng)態(tài)申請(qǐng)內(nèi)存(令R=3;C=2;): c=(short*)malloc(size(short)*R); d=(short**)malloc(size(short*)*R); for(i=0;i<R;i++) { d[i]=(short*)malloc(size(short)*C); e[i]=(short*)malloc(size(short)*C); } 問(wèn)題:各種數(shù)組的存儲(chǔ)單元有什么相同之處和不同之處?數(shù)組a和動(dòng)態(tài)數(shù)組c的比較數(shù)組a動(dòng)態(tài)數(shù)組(指針)c表示數(shù)組當(dāng)然可以性質(zhì)a是常量c是變量存儲(chǔ)單元sizeof(short)x3=6字節(jié)sizeof(short)x3+sizeof(short*)=6+4=10字節(jié)獲得空間根據(jù)定義動(dòng)態(tài)分配/指向目標(biāo)可擴(kuò)展性沒(méi)有任意二維數(shù)組、二級(jí)指針和指針數(shù)組的比較 由二級(jí)指針d和指針數(shù)組e分別生成了幾個(gè)數(shù)組? 動(dòng)態(tài)數(shù)組中各個(gè)元素之間的地址有什么關(guān)系? 各個(gè)數(shù)組在使用上有什么異同?二維數(shù)組、二級(jí)指針和指針數(shù)組的比較二維數(shù)組b二級(jí)指針d指針數(shù)組e表示數(shù)組當(dāng)然。1個(gè)二維數(shù)組可以。1個(gè)動(dòng)態(tài)指針數(shù)組,3個(gè)動(dòng)態(tài)數(shù)組可以。1個(gè)指針數(shù)組,3個(gè)動(dòng)態(tài)數(shù)組性質(zhì)b是常量d是變量e是變量存儲(chǔ)單元sizeof(short)x3x2=12字節(jié)sizeof(short)x3x2+sizeof(short*)x3+sizeof(short**)=12+12+4=28字節(jié)sizeof(short)x3x2+sizeof(short*)x3=12+12=24字節(jié)獲得空間根據(jù)定義動(dòng)態(tài)分配/指向目標(biāo)動(dòng)態(tài)分配/指向目標(biāo)可擴(kuò)展性沒(méi)有行和列都可以擴(kuò)展列可以擴(kuò)展各行長(zhǎng)度相同,固定可變可變行元素地址的連續(xù)性連續(xù)不連續(xù)不連續(xù)【例3-2.8】指針應(yīng)用示例:關(guān)鍵字查表程序 設(shè)計(jì)一個(gè)關(guān)鍵字表,存放六個(gè)關(guān)鍵字:begin,end,if,else,while和for。編制一段程序,每輸入一個(gè)字符串(標(biāo)識(shí)符),就去調(diào)用查表函數(shù)lookup。若標(biāo)識(shí)符與某個(gè)關(guān)鍵字匹配,就返回該關(guān)鍵字在表中的序號(hào)(從0到5),若找不到匹配的關(guān)鍵字,返回值為-1。 由于關(guān)鍵字的數(shù)量是已知的,因此可以在程序中定義一個(gè)字符指針數(shù)組Keyword,數(shù)組長(zhǎng)度為6,數(shù)組中的每一個(gè)元素都指一個(gè)關(guān)鍵字字符串的地址。 程序?yàn)椋? #include<stdio.h> #include<string.h> #defineBUFSIZE80 #defineTABLELEN6 char*Keyword[TABLELEN]={"begin","end","if","else","while","for"}; /*lookupstringinKeywordandreturnitsindex*/ lookup(string) char*string; { inti; for(i=0;i<TABLELEN;i++) if(strcmp(string,Keyword[i])==0) return(i); return(-1); } main() { shortid; /*keywordindex*/ charstring[BUFSIZE]; /*inputstring*/ printf("Enterastring:"); while(scanf("%s",string)==1) { id=(short)lookup(string); if(id!=-1) printf("IDof[%s]is%d\n",string,id); else printf("string'%s'isnotakeyword\n",string); printf("Enterastring:"); } }【例3-2.9】數(shù)組應(yīng)用示例:計(jì)算運(yùn)費(fèi)問(wèn)題(程序設(shè)計(jì)課程例題) 已知若干個(gè)城市之間存在的公路以及兩個(gè)城市間的運(yùn)費(fèi)(以圖示為例)。輸入發(fā)貨和收貨地名,如果它們之間存在公路,則輸出所需的運(yùn)費(fèi),否則輸出無(wú)法直接運(yùn)輸?shù)男畔ⅰ?考慮采用二維數(shù)組存儲(chǔ)城市之間的運(yùn)費(fèi)。假如已知共有7各城市,可建立一個(gè)二維數(shù)組cost[7][7],反映了一個(gè)運(yùn)費(fèi)矩陣C(7,7),其行數(shù)和列數(shù)均為城市的數(shù)量(7個(gè)),每個(gè)數(shù)組元素cost[s][d]等于發(fā)貨地(src)到收貨地(dst)間的運(yùn)費(fèi),如果沒(méi)有公路直接連接,cost[s][d]為0。數(shù)據(jù)定義 設(shè)置一個(gè)城市名數(shù)組city[7][10](假定由每個(gè)城市名的長(zhǎng)度不超過(guò)字符),并設(shè)置一個(gè)二維數(shù)組c[7][7],表示城市的公路連接和運(yùn)費(fèi)。定義為: #defineN7 charcity[N][10]; shortcost[N][N];存儲(chǔ)城市、公路連接以及運(yùn)費(fèi)的函數(shù)input()為: voidinput() { intr,c; /*r:row,c:column */ for(r=0;r<N;r++) { scanf("%s",city[r]); for(c=0;c<N;c++) scanf("%d",&cost[r][c]); } }輸入數(shù)據(jù)為 a 0404650 b 4040200 c 0400304 d 4000050 e 6230042 f 5005405 g 0040250求取運(yùn)費(fèi)的函數(shù)getCost() voidgetCost() { intr,c; /*r:row,c:column */ charsrc[10],dst[10]; printf("Inputsourcecityanddestinationcity:\t"); scanf("%s%s",&src,&dst); if((r=index(src))==-1||(c=index(dst))==-1||r==c) exit(0); /*無(wú)效的發(fā)貨城市或者收貨城市 */ if(cost[r][c]) /*存在公路,輸出運(yùn)費(fèi) */ printf("costfrom%sto%sis%d\n",src,dst,cost[r][c]); else /*不存在公路,無(wú)法直接運(yùn)貨 */ printf("nohighwayfrom%sto%s!\n",src,dst); } 其中,函數(shù)index()的功能是根據(jù)城市名查找在數(shù)組中的索引號(hào)。查找城市名的函數(shù)index() intindex(char*cityName) { intr; /*r:row,c:column */ for(r=0;r<N;r++) if(strcmp(cityName,city[r])) return(r); return(-1); }主函數(shù)main() main() { input(); getCost(); }3.3結(jié)構(gòu) 數(shù)據(jù)處理是編制計(jì)算機(jī)程序的主要工作,我們可以發(fā)現(xiàn)往往有些數(shù)據(jù)相互之間關(guān)系密切,它們組合在一起可以表達(dá)某種信息,而且總是需要一起處理。例如,處理人員工資的數(shù)據(jù)時(shí),人員的姓名、單位、基本工資、附加工資、扣發(fā)工資和實(shí)發(fā)工資等數(shù)據(jù)組合起來(lái)才能完整地表達(dá)一個(gè)人員的信息,而且這些數(shù)據(jù)的處理總是同時(shí)出現(xiàn)。假定用多個(gè)數(shù)組表示人員信息,對(duì)同一人員的各項(xiàng)數(shù)據(jù)用相同的下標(biāo)來(lái)表示。這樣的程序?qū)?shù)據(jù)的表達(dá)不夠清晰。特別地,在數(shù)據(jù)對(duì)象很復(fù)雜,描述對(duì)象的信息有多重層次關(guān)系時(shí),處理更為困難。 為此,C語(yǔ)言提供了一種方法,將若干個(gè)數(shù)據(jù)組合起來(lái),形成一種構(gòu)造性數(shù)據(jù)類型,稱為結(jié)構(gòu)。例如,將一個(gè)人員的信息定義為一種結(jié)構(gòu),結(jié)構(gòu)中含有人員的各個(gè)數(shù)據(jù),從而體現(xiàn)了這些數(shù)據(jù)之間密切的關(guān)系,并且易于編程和易于理解。3.3.1結(jié)構(gòu)的定義和存儲(chǔ)單元結(jié)構(gòu)的定義最簡(jiǎn)單的結(jié)構(gòu)類型定義 struct[結(jié)構(gòu)標(biāo)識(shí)符] /*結(jié)構(gòu)標(biāo)識(shí)符可以省略 */ { 成員定義 /*定義所有成員的數(shù)據(jù)類型 */ }; 例如:定義年月日為結(jié)構(gòu)類型的語(yǔ)句為用結(jié)構(gòu)類型定義結(jié)構(gòu)變量 struct { shortday; charmonth[3]; shortyear; }d1; struct { shortday; charmonth[3]; shortyear; }d2[3]; struct { shortday; charmonth[3]; shortyear; }*d3; 表示定義了一個(gè)結(jié)構(gòu)變量d1,一個(gè)含有結(jié)構(gòu)數(shù)組d2[3],以及一個(gè)指向結(jié)構(gòu)對(duì)象的結(jié)構(gòu)指針d3。這種結(jié)構(gòu)類型含有3個(gè)成員year,month和day。用結(jié)構(gòu)標(biāo)識(shí)符定義結(jié)構(gòu)變量 structdate { shortday; charmonth[3]; shortyear; }; structdated1,d2[3],*d3; 先定義結(jié)構(gòu)structdate。再用structdate定義結(jié)構(gòu)變量d1,結(jié)構(gòu)數(shù)組d2[3],以及結(jié)構(gòu)指針d3。用typedef定義結(jié)構(gòu)和變量 structdate { shortday; charmonth[3]; shortyear; }d1; typedefstructdateDATE; DATEd2[3],*d3; 表示先定義類型structdate(可以同時(shí)定義變量), 然后將structdate定義成類型DATE, 再用類型DATE來(lái)定義變量。用define定義結(jié)構(gòu)和變量 #defineDATEstructdate DATE { shortday; charmonth[3]; shortyear; }d1; DATEd2[3],*d3; 表示先將structdate定義成宏DATE, 然后用宏DATE定義類型(可以同時(shí)定義變量), 再用類型DATE來(lái)定義變量。結(jié)構(gòu)類型的存儲(chǔ)空間 結(jié)構(gòu)的存儲(chǔ)空間的大小等于其成員所占存儲(chǔ)空間的總和。 例如,結(jié)構(gòu)類型date所占存儲(chǔ)空間的字節(jié)數(shù)等于整型變量day、字符數(shù)組month以及整型變量year的字節(jié)數(shù)之和。 sizeof(structdate)=sizeof(day)+sizeof(month)+sizeof(year)=2+3+2=7 雖然sizeof(structdate)的理論計(jì)算為7字節(jié),但是由于還要考慮偶數(shù)字節(jié)的排齊,實(shí)際需要的存儲(chǔ)空間為8字節(jié)。結(jié)構(gòu)類型的嵌套定義 假定已用define語(yǔ)句定義了兩個(gè)結(jié)構(gòu)A和B,結(jié)構(gòu)類型的嵌套定義可以分成以下幾種情況。非法的直接嵌套定義 A { shorta; Ab; }; 在結(jié)構(gòu)類型A中含有同類的結(jié)構(gòu)變量b,從而無(wú)法確定結(jié)構(gòu)A所需的存儲(chǔ)空間。非法的間接嵌套定義 A { ……; Bx; }; B { ……; Ay; }; 在結(jié)構(gòu)類型A中含有結(jié)構(gòu)類型B的變量x,而在結(jié)構(gòu)類型B中含有結(jié)構(gòu)類型A的變量y,兩者相互依賴,從而無(wú)法確定結(jié)構(gòu)A和B所需的存儲(chǔ)空間。合法的嵌套定義 A { shorta; A*b; }; 在結(jié)構(gòu)類型A中,包含有同類結(jié)構(gòu)類型的指針變量b。由于指針變量b占4個(gè)字節(jié),從而可確定結(jié)構(gòu)A所需的存儲(chǔ)空間。3.3.2結(jié)構(gòu)與指針結(jié)構(gòu)與指針的定義 假設(shè)有以下定義: DATEd,*pe,*pf,*pg; 表示定義了結(jié)構(gòu)變量d,結(jié)構(gòu)指針pe、pf和pg。結(jié)構(gòu)指針的對(duì)象指向已知單元 例如:pe=&d;指向空 例如:pf=NULL;指向一個(gè)動(dòng)態(tài)申請(qǐng)的結(jié)構(gòu)變量 例如:pg=(DATE*)malloc(sizeof(DATE));指向若干個(gè)動(dòng)態(tài)申請(qǐng)的結(jié)構(gòu)(動(dòng)態(tài)結(jié)構(gòu)數(shù)組) 例如:ph=(DATE*)malloc(sizeof(DATE)*N);3.3.3結(jié)構(gòu)成員的引用結(jié)構(gòu)引用運(yùn)算符包括“.”和“->”。 假定已有以下語(yǔ)句: DATEd,*pd; pd=&d; 可有以下應(yīng)用的示例:結(jié)構(gòu)變量成員的引用符“.” d.day=17; d.month[0]=‘A’; d.month[1]=‘p’; d.month[2]=‘r’; d.year=2000;結(jié)構(gòu)指針對(duì)象成員的引用符“->” pd->day=17; pd->month[0]=‘A’; pd->month[1]=‘p’; pd->month[2]=‘r’; pd->year=2000;結(jié)構(gòu)引用符“.”和“->”的等價(jià) pd->year 等價(jià)于 (*pd).year pd->month[i] 等價(jià)于 (*pd).month[i]結(jié)構(gòu)賦值結(jié)構(gòu)成員的地址表示 &(d.year) 等價(jià)于 &((*pd).year) 等價(jià)于 &(pd->year) &(d.month[i]) 等價(jià)于 &((*pd).month[i]) 等價(jià)于 &(pd->month[i]) C語(yǔ)言不允許對(duì)結(jié)構(gòu)變量進(jìn)行整體賦值。例如有 DATEd1,d2,*pd; 其中,假定結(jié)構(gòu)指針pd已經(jīng)指向某個(gè)非空的結(jié)構(gòu)變量。 如果需要將d1成員的值賦給d2的成員或者賦給pd對(duì)象的成員,以下語(yǔ)句是非法的: d2=d1; *pd=d1; 應(yīng)該改為 d2.day=d1.day; for(i=0;i<=2;i++) d2.month[i]=d1.month[i]; d2.year=d1.year;或者 pd->day=d1.day; strcpy(pd->month,d1.month); pd->.year=d1.year;3.3.4結(jié)構(gòu)的應(yīng)用-鏈表鏈表的組成 鏈表是結(jié)構(gòu)的一個(gè)非常重要的應(yīng)用,其中一個(gè)重要的特點(diǎn)是在結(jié)構(gòu)的成員中含有結(jié)構(gòu)指針,通常是同類結(jié)構(gòu)類型的指針。 鏈表由若干個(gè)結(jié)點(diǎn)(node)組成,每個(gè)結(jié)點(diǎn)都是結(jié)構(gòu)類型的變量。其成員由兩部分組成,一部分是數(shù)據(jù)成員,另一部分是指針成員。用某個(gè)指針成員(通常定義為next)指向下一個(gè)結(jié)點(diǎn),各個(gè)結(jié)點(diǎn)逐個(gè)相連,從而構(gòu)成一個(gè)鏈表。 例如,定義一個(gè)結(jié)構(gòu)A,它的數(shù)據(jù)成員n存放結(jié)點(diǎn)的數(shù)據(jù),通過(guò)成員指針next,將多個(gè)結(jié)點(diǎn)逐個(gè)相連形成鏈表。 #defineAstructa A { shortn; A*next; };鏈表的構(gòu)成形式 鏈表的起始結(jié)點(diǎn)稱為鏈表頭/表頭/首結(jié)點(diǎn)。指向表頭的指針?lè)Q為首指針/表頭指針/表首指針。 鏈表的結(jié)尾結(jié)點(diǎn)稱為鏈表尾/表尾/尾結(jié)點(diǎn)。指向表尾的指針?lè)Q為表尾指針/尾指針。 若表尾的指針成員指向NULL,這樣的鏈表稱為單向鏈表。 若表尾的指針成員指向表頭,這樣的鏈表稱為循環(huán)鏈表。 首指針的設(shè)置不使用首指針 例如,結(jié)構(gòu)變量head就是鏈表頭,因此不需要使用首指針。用結(jié)構(gòu)變量的指針成員作為首指針 例如,定義結(jié)構(gòu)變量:Ahead; 用head.next作為首指針,指向表頭。用結(jié)構(gòu)指針作為首指針(最常用) 例如,定義結(jié)構(gòu)指針:A*first; 用first作為首指針,指向表頭。尾指針的設(shè)置不使用尾指針 在許多應(yīng)用中是不需要尾指針的,從而不一定設(shè)置尾指針。用結(jié)構(gòu)變量的指針成員作為尾指針 例如,定義結(jié)構(gòu)變量:Alast; 用last.next作為尾指針,指向表尾。用結(jié)構(gòu)指針作為尾指針(最常用) 例如,定義結(jié)構(gòu)指針:A*tail; 用tail作為尾指針,指向表尾。鏈表的前插入鏈表的設(shè)定 定義首指針: A*first; 假定不考慮哨兵和尾指針 初始鏈表為空表: first=NULL; 待插入結(jié)點(diǎn): 用指針node指向。 非空鏈表: first非空。表頭前插入(包括空表前插入)表中前插入操作 ①node->next=first; ①node->next=prev->next; ②first=node; ②prev->next=node;鏈表的后插入鏈表的設(shè)定 定義首指針和尾指針: A*first,*tail; 初始鏈表為空表: first=tail=NULL; 待插入結(jié)點(diǎn): 用指針node指向。空鏈表的表尾后插入 node->next=first; first=tail=node;或 node->next=NULL; first=tail=node;或 first=tail=node; node->next=NULL;非空鏈表的后插入 非空鏈表的后插入包括非空鏈表的表尾后插入和非空鏈表的表中后插入兩種情況。其中,可以把表尾后插入中的表尾指針tail看成是表中后插入的當(dāng)前結(jié)點(diǎn)指針now。 尾結(jié)點(diǎn)的成員next可以指向NULL(單向鏈表),也可以指向首結(jié)點(diǎn)(循環(huán)鏈表),因此在后插入時(shí)統(tǒng)一用#表示next的值。 ①node->next=now->next; ②now->next=node; ③now=node; /*假定需要更新指針now */3.3.5數(shù)組和指針應(yīng)用的討論 要存儲(chǔ)和處理N個(gè)數(shù)據(jù),可以根據(jù)數(shù)據(jù)量的情況,考慮采用數(shù)組或者鏈表以實(shí)現(xiàn)不同的編程方案。數(shù)據(jù)量N的情況N為先知:數(shù)據(jù)量N已知,在程序運(yùn)行時(shí)是固定的。N為后知:數(shù)據(jù)量N將在程序運(yùn)行中獲得,如通過(guò)輸入或者通過(guò)計(jì)算得到。N為未知:數(shù)據(jù)量N在程序運(yùn)行中是動(dòng)態(tài)變化的。可采用的方案定義數(shù)組:定義N個(gè)元素的數(shù)組 Aa[N];動(dòng)態(tài)數(shù)組:動(dòng)態(tài)申請(qǐng)N個(gè)單元 A*pa; pa=(A*)malloc(N*sizeof(A));采用鏈表:動(dòng)態(tài)申請(qǐng)結(jié)點(diǎn)方案數(shù)據(jù)量N為已知N為可知N為未知定義數(shù)組唯一方案××動(dòng)態(tài)數(shù)組更靈活比較適合×采用鏈表更靈活更靈活唯一方案3.5函數(shù)3.5.1函數(shù)間的數(shù)據(jù)通訊什么是數(shù)據(jù)通訊 在C語(yǔ)言中,函數(shù)是能夠完成獨(dú)立功能的程序段。也就是說(shuō),在函數(shù)的內(nèi)部或者外部,可以各自定義變量。但是,函數(shù)又需要對(duì)其他函數(shù)定義的變量進(jìn)行存取。例如,某個(gè)函數(shù)需要獲得其他函數(shù)的變量值,或者需要將函數(shù)定義的變量值傳遞給其他函數(shù)。因此,必須考慮各個(gè)函數(shù)之間的數(shù)據(jù)通訊(數(shù)據(jù)共享)問(wèn)題。 可以通過(guò)函數(shù)返回值、函數(shù)的虛實(shí)結(jié)合以及共享外部變量(靜態(tài)數(shù)據(jù))三種方式實(shí)現(xiàn)函數(shù)之間的數(shù)據(jù)通訊。函數(shù)返回值 通過(guò)函數(shù)的返回值,主調(diào)函數(shù)可以從被調(diào)函數(shù)獲得一個(gè)數(shù)據(jù),其實(shí)現(xiàn)的是被調(diào)函數(shù)向主調(diào)函數(shù)的單向傳遞。 在被調(diào)函數(shù)中,使用return語(yǔ)句,可以將一個(gè)基本類型的數(shù)據(jù)或者一個(gè)地址值返回(傳遞)給主調(diào)函數(shù),或者說(shuō)主調(diào)函數(shù)可以從被調(diào)函數(shù)獲得數(shù)據(jù),即獲得一個(gè)基本類型的數(shù)據(jù)或者一個(gè)地址值。函數(shù)的傳值調(diào)用 通過(guò)函數(shù)參數(shù)的虛實(shí)結(jié)合,被調(diào)函數(shù)可以從主調(diào)函數(shù)獲得若干個(gè)數(shù)據(jù),其實(shí)現(xiàn)的是通過(guò)主調(diào)函數(shù)的實(shí)參(實(shí)在參數(shù))向被調(diào)函數(shù)的形參(形式參數(shù))的單向傳遞。因此,函數(shù)參數(shù)的虛實(shí)結(jié)合又稱為函數(shù)的傳值調(diào)用。 形參的存儲(chǔ)單元是在函數(shù)執(zhí)行時(shí)獲得的。也就是說(shuō),在函數(shù)開始運(yùn)行之前(調(diào)用函數(shù)),或者函數(shù)結(jié)束運(yùn)行之后(函數(shù)返回),形參所占的存儲(chǔ)單元是不存在的。只有在該函數(shù)被調(diào)用的過(guò)程中,這些形參才會(huì)獲得存儲(chǔ)空間。因此,形參又被稱為動(dòng)態(tài)變量。 形參的值是在函數(shù)調(diào)用時(shí)由實(shí)參值傳遞來(lái)的,因此只有在函數(shù)調(diào)用時(shí),形參才能獲得數(shù)據(jù)。 無(wú)論被調(diào)函數(shù)中的形參和主調(diào)函數(shù)中的實(shí)參是否同名,它們必須在數(shù)量和數(shù)據(jù)類型上完全一致。 形參和實(shí)參在數(shù)據(jù)類型上的一致,可以表現(xiàn)為以下兩種情況:數(shù)據(jù)對(duì)應(yīng) 如果形參和實(shí)參都是變量,則不論是哪一種數(shù)據(jù)類型,只要是同一種數(shù)據(jù)類型,在函數(shù)調(diào)用時(shí),數(shù)據(jù)傳遞的過(guò)程將把實(shí)參的數(shù)值復(fù)制給形參。如果不是同一種數(shù)據(jù)類型,將按照數(shù)據(jù)轉(zhuǎn)換的隱式規(guī)則,先將實(shí)參轉(zhuǎn)換成形參的數(shù)據(jù)類型,然后復(fù)制數(shù)據(jù)。地址對(duì)應(yīng) 由于無(wú)論是數(shù)組還是指針,無(wú)論是一維數(shù)組還是二維數(shù)組,無(wú)論是指針數(shù)組還是二級(jí)指針,它們的值表達(dá)的都是地址。因此,如果形參和實(shí)參的值都是地址,則它們可以是數(shù)組或者指針。在函數(shù)調(diào)用時(shí),數(shù)據(jù)傳遞的過(guò)程總是將實(shí)參的數(shù)值復(fù)制給形參。所以,只要分辨出它們的地址是指向同一類對(duì)象(例如同一種整型、同一種結(jié)構(gòu)等等)的話,形參和實(shí)參就能夠做到地址對(duì)應(yīng)?!纠?-5.1】函數(shù)的傳值調(diào)用示例一:swap1main(){ shorta=5,b=3;① swap1(a,b); printf(“%d,%d\n”,a,b);}voidswap1(inta,inty){ intt;② t=a;③ a=y;④ y=t;}運(yùn)行結(jié)果 a=5,b=3 主調(diào)函數(shù)main中實(shí)參a和b是變量,被調(diào)函數(shù)swap1中的形參a和y也是變量。由于函數(shù)調(diào)用的語(yǔ)句為swap1(a,b),表示將main的a和b的數(shù)值傳遞給swap1的a和y。由于main:a和swap1:a占有不同的存儲(chǔ)單元,main:b和swap1:y也占有不同的存儲(chǔ)單元,因此在swap1中的變量交換操作沒(méi)有改變main中變量a和b的值。【例3-5.2】函數(shù)的傳值調(diào)用示例二:swap2 main中a和b是變量,實(shí)參&a和&b是地址,swap2中形參a和y是指針。由于調(diào)用語(yǔ)句為swap2(&a,&b),表示將main的變量a和b的地址傳遞給swap2的指針a和y,使swap2的a和y指向main的a和b,即main的a和b成為swap2的a和y的對(duì)象。因此swap2中對(duì)*a和*y的操作,實(shí)際上是對(duì)main的a和b進(jìn)行操作,從而改變了它們的數(shù)值。main(){ shorta=5,b=3;① swap2(&a,&b); printf(“%d,%d\n”,a,b);}voidswap2(int*a,int*y){ intt;② t=*a;③ *a=*y;④ *y=t;}運(yùn)行結(jié)果 a=3,b=5共享外部變量(靜態(tài)數(shù)據(jù)) 外部變量和外部靜態(tài)變量都是靜態(tài)數(shù)據(jù),它們的存儲(chǔ)空間位于內(nèi)存中的靜態(tài)數(shù)據(jù)區(qū)。根據(jù)它們的定義位置,可確定用權(quán)訪問(wèn)這些靜態(tài)數(shù)據(jù)的函數(shù),從而通過(guò)靜態(tài)數(shù)據(jù)的共享實(shí)現(xiàn)不同函數(shù)之間的數(shù)據(jù)通訊。這種方式通常稱為是通過(guò)外部變量實(shí)現(xiàn)的數(shù)據(jù)通訊。 根據(jù)以下示例的源文件中靜態(tài)數(shù)據(jù)的定義及位置,列出可共享數(shù)據(jù)的函數(shù),表示這些函數(shù)可以存取(訪問(wèn))與其相關(guān)的靜態(tài)數(shù)據(jù)。源文件c1.cinta,b;staticintc;externintg;A(){ externintd;}intd;staticinte;B(){}源文件c2.cexterninta;staticintb;C(){}intg;staticintc;D(){ externintd;}3.5.2遞歸函數(shù)函數(shù)的遞歸調(diào)用 函數(shù)直接或者間接地調(diào)用函數(shù)自己,稱為函數(shù)遞歸調(diào)用(直接遞歸或間接遞歸)。main(){ …... sub1(); …... sub2(); ……}sub2(){ …... sub3(); …... sub4(); ……}sub4(){ …... sub5(); …... sub2(); ……}sub5(){ …... sub5(); ……}遞歸函數(shù)的特點(diǎn)遞歸函數(shù)比較適用于可用遞歸方法描述的算法,應(yīng)該使每層的算法完全一致。 例如求階乘: if(n>1) n!=n?(n-1)! 例如用輾轉(zhuǎn)相除法求最大公約數(shù): if(a%b!=0) gcd(a,b)=gcd(b,a%b) 例如Hanoi塔問(wèn)題: if(n>1) { moveN(n-1,from,tmp,to); moveOne(n,from,to); moveN(n-1,tmp,to,from); }必須是有條件的遞歸,通常是伴有if語(yǔ)句。即在某一層上能夠結(jié)束,否則將引起死循環(huán)。 例如求階乘: if(n==1) n!=1 例如用輾轉(zhuǎn)相除法求最大公約數(shù): if(a%b==0) gcd(a,b)=b 例如Hanoi塔問(wèn)題: if(n==1) moveOne(1,from,to);必須設(shè)置是否遞歸的測(cè)試點(diǎn)和返回點(diǎn)。如果滿足遞歸條件,進(jìn)行遞歸調(diào)用;否則返回。 例如:#include<stdio.h>shortgcd(a,b)shorta,b;{ intr; if(a%(r=b)) /*遞歸測(cè)試*/ r=gcd(b,a%b); /*遞歸調(diào)用*/ return(r); /*返回點(diǎn)*/}main(){ shorta,b,r; scanf(“%d%d”,&a,&b); r=gcd(a,b); printf(“r=%d\n”,r);}遞歸方法不能節(jié)省空間,也不能節(jié)省時(shí)間,但是易于編程和易于理解算法。遞歸函數(shù)的適用性 遞歸函數(shù)比較適用于用遞歸算法描述的問(wèn)題(遞歸問(wèn)題),但也可以用來(lái)解決非遞歸問(wèn)題。而非遞歸函數(shù)不僅可以用來(lái)解決非遞歸問(wèn)題,也可以用來(lái)解決遞歸問(wèn)題。 或者說(shuō):遞歸問(wèn)題可以采用遞歸函數(shù)編程來(lái)解決問(wèn)題,也可以采用非遞歸函數(shù)。另外,非遞歸問(wèn)題也可以采用非遞歸函數(shù)或者遞歸函數(shù)?!纠?-5.3】遞歸函數(shù)示例一:Hanoi(漢諾)塔問(wèn)題 算法(問(wèn)題)描述: 利用C塔,將n個(gè)金片從A塔移到B塔。#include<stdio.h>intstep=0;moveOne(intn,charfrom,charto){ printf("step%3d:",++step); printf("movechip(%d)",n); printf("from%c",from); printf("to%c\n",to);}voidmoveN(n,from,to,tmp)intn;charfrom,to,tmp;{ if(n==1) moveOne(1,from,to); else { moveN(n-1,from,tmp,to); moveOne(n,from,to);main(){ shortn; printf("Entern:"); scanf("%d",&n); moveN(n,'A','B','C');} moveN(n-1,tmp,to,from); }}

【例3-5.4】遞歸函數(shù)示例二:用輾轉(zhuǎn)相除法求最大公約數(shù)(用遞歸算法描述的問(wèn)題)(1)用遞歸函數(shù)實(shí)現(xiàn)的程序 #include<stdio.h> shortgcd(shorta,shortb) { intr; if(a%b) r=gcd(b,a%b); else r=b; return(r); } main() { shorta,b,r; scanf(“%d%d”,&a,&b); r=gcd(a,b); printf(“r=%d\n”,r); }(2)用非遞歸函數(shù)實(shí)現(xiàn)的程序 #include<stdio.h> shortgcd(shorta,shortb) { intr; while(r=a%b) { a=b; b=r; } return(b); } main() { shorta,b,r; scanf(“%d%d”,&a,&b); r=gcd(a,b); printf(“r=%d\n”,r); }【例3-5.5】遞歸函數(shù)示例三:逆序打印鏈表結(jié)點(diǎn)(求解用非遞歸算法描述的問(wèn)題)(1)順序打印(采用非遞歸函數(shù)) #include<stdio.h> #defineNstructnode N{intn;N*next;}*first; voidprt(N*head) { N*node; for(node=head;node;node=node->next) printf(“n=%d\n”,node->n); } 調(diào)用函數(shù): prt(first);(2)逆序打印(采用遞歸函數(shù)) #include<stdio.h> #defineNstructnode N{intn;N*next;}*first; voidprt(N*head) { if(!head) return; else prt(head->next); printf(“n=%d\n”,node->n); }3.7C語(yǔ)言和shell的通信3.7.1命令行參數(shù) 命令行參數(shù)是指針數(shù)組和二級(jí)指針的一種應(yīng)用。 main函數(shù)的定義形式為: main([argc,argv]) 形參argc用于表示命令行參數(shù)的個(gè)數(shù),argv表示命令行參數(shù)的內(nèi)容。其中,argv可以用二級(jí)指針或者指針數(shù)組來(lái)表示。 (1)用指針數(shù)組表示 main(argc,argv) intargc;char*argv[]; (2)用二級(jí)指針表示 main(argc,argv) intargc;char**argv; 設(shè)可執(zhí)行文件為try,執(zhí)行命令為 $tryIamabc 則argc=4用指針數(shù)組表示argv 程序try.c的內(nèi)容為: main(argc,argv) intargc; char*argv[]; { inti; for(i=0;i<argc;i++) { printf(“argv[%d]=%s\t”,i,argv[i]); printf(“argv[%d][0]:<%c>\n”,i,argv[i][0]); } } 其中,argv[i]是字符數(shù)組的首地址,argv[i][0]是字符數(shù)組的第一個(gè)元素。 通過(guò)編譯生成可執(zhí)行文件try。在命令行中運(yùn)行及結(jié)果為: $tryIamABC argv[0]=try argv[0][0]:<t> argv[1]=I argv[1][0]:<I> argv[2]=am argv[2][0]:<a> argv[3]=ABC argv[3][0]:<A>用二級(jí)指針表示argv 程序try.c的內(nèi)容為: main(argc,argv) intargc; char**argv; { inti; for(i=0;i<argc;i++,argv++) { printf(“argv[%d]=%s\t”,i,*argv); printf(“*argv[0]:<%c>\n”,*argv[0]); } } 其中,*argv是字符數(shù)組的首地址,*argv[0]是字符數(shù)組的第一個(gè)元素。 通過(guò)編譯生成可執(zhí)行文件try。在命令行中運(yùn)行及結(jié)果為: $tryIamABC argv[0]=try *argv[0]:<t> argv[1]=I *argv[0]:<I> argv[2]=am *argv[0]:<a> argv[3]=ABC *argv[0]:<A>3.8程序設(shè)計(jì)標(biāo)準(zhǔn)(實(shí)施要求) 在編程的實(shí)踐中逐步提高認(rèn)識(shí),認(rèn)同編程的標(biāo)準(zhǔn)和規(guī)范,做到能夠編寫結(jié)構(gòu)合理、風(fēng)格良好的軟件?;疽?要求在本課程的練習(xí)和考試時(shí)按照講義“程序設(shè)計(jì)標(biāo)準(zhǔn)”進(jìn)行編程。數(shù)據(jù)類型、常量和運(yùn)算符命名規(guī)則變量、指針的初始化函數(shù)排版注釋高級(jí)要求數(shù)據(jù)管理調(diào)試程序風(fēng)格程序和軟件維護(hù)3.8.1數(shù)據(jù)類型、常量和運(yùn)算符基本數(shù)據(jù)類型 在開始使用某個(gè)計(jì)算機(jī)的編程環(huán)境時(shí),最好先明確基本數(shù)據(jù)類型(short,long,char,float,double)所占的字節(jié)數(shù)。 盡量少用自然(缺省)整數(shù)類型int,而明確地使用short和long類型的整數(shù)類型。常量 在程序中盡量避免出現(xiàn)常數(shù),而先定義符合常量,然后在程序中使用該符合常量。例如:不要寫成shortgroup[100];不要寫成for(i=1;i<50;i++)應(yīng)該改為#defineLEN100shortgroup[LEN];;應(yīng)該改為#defineLAST50for(i=1;i<LAST;i++)或者#defineFIRST1#defineLAST50for(i=FIRST;i<LAST;i++)數(shù)據(jù)類型轉(zhuǎn)換 在對(duì)不同類型的數(shù)據(jù)進(jìn)行混合運(yùn)算時(shí),盡量避免使用缺省(隱式)的數(shù)據(jù)類型轉(zhuǎn)換,而使用顯式的數(shù)據(jù)類型轉(zhuǎn)換。例如: 不要寫成 3*4.25 應(yīng)該根據(jù)實(shí)際需要而改為 3*(int)4.25 或者 (float)3*4.25運(yùn)算符的分隔 在一個(gè)表達(dá)式中,應(yīng)該合理地加空格來(lái)分隔運(yùn)算符。不應(yīng)該使用空格分隔的的運(yùn)算符 負(fù)數(shù)運(yùn)算符:-, 自增減運(yùn)算符:++,--, 取值取址運(yùn)算符:*,& 結(jié)構(gòu)成員引用符:->,.,以及!,~,(類型),sizeof()等 例如:不要寫成 -a 應(yīng)該寫成 -a i++ i++需要使用空格分隔的的運(yùn)算符 以下運(yùn)算符需要在其左右加空格以分隔: 雙目運(yùn)算符:+,-,*,/,%, 移位運(yùn)算符:<<,>>, 賦值運(yùn)算符:= 關(guān)系運(yùn)算符:<,<=,>,>=,==,!=, 邏輯運(yùn)算符:&&,|| 復(fù)合賦值運(yùn)算符:⊕=,條件運(yùn)算符:?:,按位運(yùn)算符:&,^,| 例如:不要寫成 b*b-4*a*c 應(yīng)該寫成 b*b-4*a*c需要在左右一側(cè)加空格的運(yùn)算符 在左一側(cè)加空格的運(yùn)算符:(,[,{ 在右一側(cè)加空格的運(yùn)算符:),],},分號(hào)運(yùn)算符:;,逗號(hào)運(yùn)算符:, 以上運(yùn)算符如果連續(xù)出現(xiàn),可以在之間加空格,也可以不加空格。 例如:以下兩種寫法都是合理的: if((node=(NODE*)(malloc(sizeof(NODE)))==NULL) 或者 if((node=(NODE*)(malloc(sizeof(NODE)))==NULL) shortdate[3][2]={{4,3},{5,6},7,8}}; 或者 sho

溫馨提示

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

評(píng)論

0/150

提交評(píng)論