




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第8章數組類型8.1一維數組8.2二維數組與多維數組8.3字符數組與字符串8.4重命名類型8.5程序設計舉例8.1一維數組8.1.1一維數組的定義形式:存儲類別類型標識符數組名[常量];類型標識符描述的是數組分量的類型,是定義數組類型的基類型,可以是任何類型。數組名代表數組所占存儲空間的首地址。常量表示數組的大小(長度),即數組中分量的個數。與PASCAL語言不同,以上實際定義的是數組量,而非數組類型,數組類型隱含其中。提到數組,可能是指數組量,也可能是指數組類型,注意根據上下文區分。例如,定義數組,描述下列數據:(1)100個整數:intnum[100];(2)1000個學生C語言課程的成績:floatccj[1000];(3)一年中每月的天數:intmonth[12];(4)100種商品的價格:floatprice[100];(5)500個字符類型的數據:charch[500];
說明:
(1)數組名命名規則和變量名命名規則相同,都遵循標識符命名規則。
(2)數組的長度可以用符號常量描述,但不能用變量描述,C語言不提供動態數組。
(3)數組以線性方式將數組分量依次存儲,所占空間等于各分量所占空間之和,即數組分量個數乘以基類型數據所占空間。數組名代表存放數組的首地址。8.1.2一維數組的引用
下標變量的形式為:數組名[下標表達式]
例如,對以上定義的num數組、ccj數組:
num數組的100個分量為num[0]、num[1]、…、num[i]、…、num[99],每個分量存放一個整數,num[i]相當于一個int型變量。
ccj數組的1000個分量為ccj[0]、ccj[1]、…、ccj[i]、…、ccj[999],每個分量對應一個學生的成績,ccj[i]相當于一個float型變量。
說明:
(1)下標的取值范圍從0到數組長度減1。
(2)下標變量相當于基類型變量,能進行基類型量的一切運算操作。
(3)下標往往對應于循環控制變量,通過循環、通過下標的變化完成對數組所有分量的操作,即完成對整個數組的操作。
(4)下標往往對應特定的含義。
(5)對于下標出界,C語言不進行語法檢查,務請小心。(6)如果希望下標為i的分量對應第i個數據,可將定義的數組大小增1。例如:intnum[101];
floatccj[1001];
100個整數用num數組的分量num[1]、num[2]、…、num[100]描述,num[i]對應于第i個整數。
1000個學生的C語言成績用ccj數組的分量ccj[1]、ccj[2]、…、ccj[1000]描述,ccj[i]對應于第i個學生的成績。下標為0的分量未使用。8.1.3一維數組的初始化數組的初始化可以在執行時進行,也可以在編譯階段進行。執行時初始化可通過賦值運算或賦值語句、或輸入函數進行,但只能對數組分量進行,要占用運行時間。例如:輸入數據給數組num、ccj。for(i=0;i<101;i++)scanf("%d",&num[i]);for(i=0;i<1001;i++)scanf("%f",&ccj[i]);對靜態存儲數組和外部存儲數組,數組的初始化可以在編譯階段進行,即在程序運行之前初始化,節約運行時間。初始化形式:存儲類別類型數組名[常量]={常量1,常量2,…,常量n};各分量依次初始化為常量1、常量2、…、常量n。注意初始化數據必須用花括號括起。例如:①staticintmonth[12]={31,29,31,30,31,30,31,31,30,31,30,31};則month[0]=31,month[1]=29,month[2]=31,…,month[12]=31。②staticcharch[5]={'a','e','i','o','u'};則ch[0]='a',ch[1]='e',ch[2]='i',ch[3]='o',ch[4]='u'。說明:
(1)對靜態存儲數組和外部存儲數組,默認初值為0。
(2)可以只給一部分數組分量初始化。例如:staticinta[50]={70,75,60,80,90};相當于a[0]=70,a[1]=75,a[2]=60,a[3]=80,a[4]=90,沒有給定初值的分量取默認初值。
(3)若對數組中所有分量給定了初值,則定義數組時可以不給出數組長度。數組的長度為給出的初值個數。例如:staticfloatx[?]={1.5,2.5,3.5,4.5,5.5};給了數組5個初值,則數組長度為5。
(4)若僅給數組部分分量初值,則不能省略數組長度。例8–1
求10個數的最大值與最小值,10個數用數組描述。程序如下:/*程序8-1,求10個數的最大值與最小值*/main(?){floata[10];/*存放10個數的數組*/inti;floatmax=?1e20,min=1e20;for(i=0;i<=9;i++)/*輸入10個數到數組*/scanf("%f",&a[i]);for(i=0;i<=9;i++)/*求最大值與最小值*/{if(a[i]>max)max=a[i];
if(a[i]<min)min=a[i];
}for(i=0;i<=9;i++)/*輸出數組中的10個數*/printf("%8.2f",&a[i]);printf("\n最大值=%f,最小值=%f",max,min);}
例8–2
求某班50個學生C語言課程的平均成績及每個學生與平均成績之差。算法提示:
(1)50個學生C語言課程的成績及每個學生與平均成績之差都是大量類型相同的數據,可分別用一個一維數組作整體描述。
(2)下標為0的分量沒有使用,同時用下標對應學號。
(3)數組的整體操作轉化成對數組分量進行,其實就是將對50個學生的成績處理轉化成對每個學生進行。/*程序8-2,求C語言課程的平均成績及每個學生與平均成績之差*/main(?){floatccj[51];/*C語言成績數組*/inti;floattcj=0.0;/*總成績*/floatav,cav[51];/*平均成績av,與平均成績之差數組cav*//*輸入學生成績*/for(i=1;i<=50;i++){printf("請輸入第%d個學生成績:",i);
scanf("%f",&ccj[i]);
}/*求總成績、平均成績*/for(i=1;i<=50;i++)tcj+=ccj[i];av=tcj/50;/*求與平均成績之差*/for(i=1;i<=50;i++)cav[i]=ccj[i]??av;/*輸出*/printf("C語言課程的平均成績=%5.2f\n",av);for(i=1;i<=50;i++)printf("第%d個學生與平均成績之差=%5.2\n",i,cav[i]);}
例8-3
用一維數組求Fibonacci數列前20項,要求每行輸出5個數。/*程序8-3,求Fibonacci數列前20項*/main(){staticinta[20]={1,1};/*存放Fibonacci數列前20項的數組*/inti;for(i=2;i<20;i++)
f[i]=f[i-1]+f[i-2];printf(″Fibonacci數列前20項如下:\n″);for(i=2;i<20;i++)
{printf(″%8d″,f[i]);
if(i%5==0)printf(″\n″);/*if語句用來控制換行*/}}/*程序8-3,求Fibonacci數列前20項*/main(){staticinta[20]={1,1};/*存放Fibonacci數列前20項的數組*/inti;
for(i=2;i<20;i++)
f[i]=f[i-1]+f[i-2];
printf(″Fibonacci數列前20項如下:\n″);
for(i=2;i<20;i++)
{printf(″%8d″,f[i]);
if(i%5==0)printf(″\n″);/*if語句用來控制換行*/}}運行結果:Fibonacci數列前20項如下:
112358132134558914423337761098715972584418167658.1.4一維數組作函數參數
數組作函數參數有數組元素作函數參數和整個數組作函數參數兩種情況。數組元素作函數參數只能是作函數的實參,與基類型變量作函數一樣處理。整個數組作函數參數,此時實參與形參都應用數組名或后介紹的指針量,而且基類型應該一致。整個數組作函數參數,傳遞的是數組的首地址,即將實參數組的首地址傳遞給形參數組,形參數組與實參數組共享存儲單元。在函數中改變了形參數組的值,實參數組將同時改變,因而數據是雙向傳遞的。例8-4
將例8-2中求C語言課程平均成績改用函數實現。函數如下:floatavf(xcj)/*求C語言課程平均成績*/floatxcj[51];{inti;
floatsum=0.0,tav;
for(i=1;i<=50;i++)
sum+=xcj[i];
tav=sum/50;
return(tav);}
主函數中調用函數avf()來求平均成績:av=avf(ccj);此時,實參數組為ccj,對應的形參數組為xcj,調用時將實參數組ccj首地址傳遞給形參數組xcj。請注意本例中數組的第一個分量ccj[0]、xcj[0]無意義。對形參數組可以不指定數組大小,在定義數組時數組名后跟空的中括號。在函數中另設一個參數,傳遞數組元素的個數。如此在函數中實現變相動態數組。
例8-5
將上例中函數延伸考慮為求n個學生C語言課程平均成績。函數如下:floatavf(xcj,n)/*求n個學生C語言課程平均成績*/floatxcj[],n;{inti;
floatsum=0.0,tav;
for(i=1;i<=n;i++)
sum+=xcj[i];
tav=sum/n;
return(tav);}
例8-2求50個學生C語言課程平均成績可用如下函數調用:
av=avf(ccj,50);最后請注意一點,C語言編譯系統對形參數組大小不作檢查。如果形參數組小于實參數組,這時形參數組得到實參數組的部分值。如果希望形參數組得到實參數組的全部值,則應指定形參數組不小于實參數組。8.2二維數組與多維數組8.2.1二維數組的定義
形式:存儲類別類型標識符數組名[常量1][常量2];
n維數組的定義形式:存儲類別類型標識符數組名[常量1][常量2]…[常量n];類型標識符描述的同樣是數組分量的類型,是定義數組類型的基類型,它可以是任何類型。數組名代表數組所占存儲空間的首地址。常量分別表示數組相應維的大小,數組分量個數等于常量1、常量2、…、常量n之積。(1)上述100個班,每班50個學生一門課程的成績,定義如下二維數組描述:
floatcj[100][50];/*第一維對應班級,第二維對應學生*/(2)1000個學生,30門課程的成績,定義如下二維數組描述:
floatacj[1000][30];/*第一維對應學生,第二維對應課程*/(3)上述某高校社會實踐調查數據,定義如下三維數組描述:intb[3][2][3];/*第一維對應年級,第二維對應性別,第三維對應交通工具*/
說明:
(1)二維數組相當于用一張表格描述數據,第一維對應表格的行,第二維對應表格的列。
(2)二維數組以線性代數中的矩陣作為典型數學背景,矩陣在程序中用二維數組描述。
(3)二維數組還可看成由一維數組拓展而來,相當于一個基類型為一維數組的一維數組。例如,二維數組cj相當于基類型為floatx[50]、具有100個分量的一維數組。(4)對于多維數組,同樣可看成由低維數組拓展而來。
(5)多維數組同樣將數組各分量依次連續存儲,即按下標1、下標2、…、下標n存儲,所占空間等于各分量所占空間之和,即數組分量個數乘以基類型數據所占空間。對于二維數組,也就是按行、按列存儲。數組名代表存放數組的首地址。8.2.2二維數組的引用二維數組下標變量的形式為:數組名[下標表達式1][下標表達式2]多維數組下標變量的形式為:數組名[下標表達式1][下標表達式2]?…?[下標表達式n]例如,以上定義的acj數組的3000個分量為:acj[0][0]、acj[0][1]、…、acj[0][29]acj[1][0]、acj[1][1]、…、acj[1][29],
acj[999][0]、acj[999][1]、…、acj[999][29]…
說明:
(1)每個下標的取值范圍從0到數組長度減1,下標變量同樣相當于基類型變量。
(2)對于多維數組整體操作的完成需用多重循環,一個下標對應于一重循環控制變量。二維數組的整體操作用兩重循環完成,外重循環對應下標1,內重循環對應下標2。
(3)其它類似于一維數組處理。8.2.3二維數組的初始化
初始化形式:存儲類別類型數組名[下標1][下標2]={常量1,常量2,…,常量n};例如:staticinta[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};初始化的結果是:a[0][0]=1,a[0][1]=2,a[0][2]=3,a[0][3]=4,a[1][0]=5,a[1][1]=6,a[1][2]=7,a[1][3]=8,a[2][0]=9,a[2][1]=10,a[2][2]=11,a[2][3]=12
說明:
(1)二維數組的初始化可以分行進行。例如,上面的a數組初始化還可以表示為:
staticinta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};而定義4行3列的b數組可以表示為:
staticintb[4][3]={{1,2,3},{4,5,6},{7,8,9},{10,11,12}};(2)可以只對數組中部分分量進行初始化。例如:staticinta[3][4]={{1,2},{5},{9}};初始化的結果是:
a[0][0]=1,a[0][1]=2,a[1][0]=5,a[2][0]=9,其它分量初值取默認值,為0。(3)如果對二維數組中全部元素初始化,則定義數組時第一維的長度可以省略,但第二維的長度不能省略。例如:
staticinta[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};可以寫成
staticinta[][4]={1,2,3,4,5,6,7,8,9,10,11,12};但不能寫成
staticinta[][]={1,2,3,4,5,6,7,8,9,10,11,12};因為兩個維數都省略時,可以理解為1*12、12*1、3*4、4*3、2*6、6*2等多種形式,會發生混淆,故只能省略第一個維數。(4)如果對二維數組按行進行初始化,?則定義數組時第一維的長度也可以省略。例如:
staticinta[][4]={{1,2},{5},{9}};二維數組與多維數組作函數參數跟一維數組作函數參數類同處理,但對形參數組,只有第一維的大小可以省略,第二維及其它高維的大小均不能省略。
例8-6
從鍵盤輸入50個學生8門課程成績,求每個學生的總成績與平均成績。/*程序8-6,求總成績及平均成績*/main(){floatcj[51][9];
inti,j;
floattcj[51],acj[51];
voidtcjf();
voidacjf();
for(i=1;i<=50;i++)/*輸入成績*/{printf(″請輸入第%d個學生8門課程成績:″,i);
for(j=1;j<=8;j++)
scanf(″%f″,&cj[i][j]);
}tcjf(cj,tcj);/*調用函數tcjf()求總成績*/acjf(tcj,acj);/*調用函數acjf()求平均成績*/printf(″所求學生總成績與平均成績如下:\n″);/*輸出處理結果*/for(i=1;i<=50;i++)
printf(″第%d個學生總成績=%6.2f,平均成績=%5.2f\n″,tcj[i],acj[i]);}voidtcjf(xcj,xtcj)/*求總成績函數*/floatxcj[51][9],xtcj[51];{inti,j;
for(i=1;i<=50;i++)
for(xtcj[i]=0.0,j=1;j<=8;j++)
xtcj[i]+=xcj[i][j];
}voidacjf(xtcj,xacj)/*求平均成績*/floatxtcj[51],xacj[51];{inti;
for(i=1;i<=50;i++)
xacj[i]=xtcj[i]/8;}例8-7
編寫程序,計算兩個3×4的整數矩陣之和。算法提示:(1)兩個3×4的矩陣用兩個二維數組a、b描述。(2)和亦是一個3×4的矩陣,同樣用一個二維數組c描述。
(3)和矩陣元素等于矩陣對應元素之和。/*程序8-7,求兩個3×4的矩陣之和*/main(){inta[3][4],b[3][4];
inti,j;
intc[3][4];
for(i=0;i<3;i++)/*輸入矩陣a*/for(j=0;j<4;j++)
scanf(″%d″,&a[i][j]);
for(i=0;i<3;i++)/*輸入矩陣b*/for(j=0;j<4;j++)
scanf(″%d″,&b[i][j]);
for(i=0;i<3;i++)/*計算矩陣c*/ for(j=0;j<4;j++) c[i][j]=a[i][j]+b[i][j];printf("所求和矩陣為:\n");for(i=0;i<3;i++)/*輸出矩陣c*/{for(j=0;j<4;j++)printf("%6d",c[i][j]);
printf("\n");
}}輸入數據:111111111111 222222222222運行結果:所求和矩陣為:
3333333333338.3字符數組與字符串8.3.1字符數組1.字符數組的定義
字符數組的定義和上面講述的數組定義形式完全一樣,只是字符數組的基類型為特定的字符類型。例如:
charch1[10],ch2[3][4],ch3[2][3][4];
定義了一個一維字符數組ch1,含有10個元素;定義了一個二維字符數組ch2,含有12個元素;定義了一個三維字符數組ch3,含有24個元素。2.字符數組的引用字符數組的引用通過字符數組的下標變量進行。字符數組的下標變量相當于字符類型的變量。
3.字符數組的初始化對于字符數組的初始化,最易理解的方式是將字符一一賦給字符數組分量,或整體作為字串處理。如果只給字符數組的一部分分量初始化,那么沒有給出值的字符數組分量取默認初值空格字符。例如:①staticcharcity[8]={'c','h','a','n','g','s','h','a'};②charcity[8];city[0]='c',city[1]='h',city[2]='a',city[3]='n',city[4]='g';city[5]='s',city[6]='h',
city[7]='a';8.3.2字符串
注意:
(1)字符串數據用雙引號表示,而字符數據用單引號表示。
(2)字符串的長度可以根據串中字符的個數臨時確定,而字符數組的長度必須事先給定。
(3)對于字符串,系統在串尾加'\0'作為其結束標志,而字符數組并不要求最后一個字符是'\0'。(4)用字符數組來處理字符串時,字符數組的長度應比要處理的字符串長度大1,以存放串尾結束符'\0'。例如:
staticcharcity[9]={'c','h','a','n','g','s','h','a','\0'};用字符串描述為:
staticcharcity[9]={''changsha''}或?''changsha'';以上兩條語句可分別理解為用字符數組來處理字符串,用字符串對字符數組初始化。
(5)千萬不能在程序中給字符數組賦值。例如:
city=''changsha'';/*絕對錯誤*/1.輸入/輸出輸入/輸出分別用scanf(?)、printf(?)函數完成,采用“%s”格式。輸入、輸出參數用字符數組名。例如,有如下程序:
main(?){charcomp[9];
scanf("%s",comp);/*本身就是地址,不需加地址運算符*/printf("COMP=%s",comp);}輸入數據:CHINAONE
運行結果:COMP=CHINAONE
說明:
(1)輸入字符串數據時不需用界定符。
(2)輸入多個字符串數據時,以空格分隔數據。如果字符串數據本身包含有空格字符,需使用gets()函數。
(3)輸出時先找到存放字符串的字符數組的首地址,遇串尾結束符'\0'結束。輸出字符不包括串尾結束符'\0'。
(4)如果字符數組中包含多個'\0',則輸出遇到第一個'\0'時結束。
(5)如果字符數組長度大于字符串實際長度,也只輸出到'\0'結束。2.字符串處理函數
puts()與gets()函數包含在頭文件stdio.h中,字符串處理函數包含在頭文件string.h中,用#include"string.h"指明。在以下函數中,參數str、str1、str2為字符數組或指向字符的指針。
(1)字符串輸出函數puts(str):輸出指定字符串。參數可以為字符串常量。
(2)字符串輸入函數gets(str):從鍵盤輸入字符串至字符數組str中,輸入的字符串可以包含空格。函數的返回值是字符數組str的首地址。
(3)字符串復制函數strcpy(str1,str2):將str2的值復制到str1中,實際上完成字符串的賦值操作。要求str1的長度大于str2的長度,第二個參數可以是字符串常量。(4)字符串連接函數strcat(str1,str2):將str2的值連接到str1中原有值的后面。注意str1必須足夠大,以便能容納兩個字符數組中的所有值。連接完成后,兩個字符串并成一個字符串,第一個字符串后面的原結束符自動取消。
(5)字符串比較函數strcmp(str1,str2):比較str1和str2,若兩者相同,則返回函數值為0;若str1大于str2,則返回函數值為一個正整數;若str1小于str2,則返回函數值為一個負整數。兩個參數可以是字符串常量。字符串比較規則與其它語言相同,將兩個字符串中的字符從左至右依次比較,如果全部字符相同,則認為相等;若出現不同字符,則以第一個不同字符比較結果為準。(6)strlen(str):函數的返回值為字符串的實際長度。(7)strlwr(str):將字符串中大寫字母轉換成小寫字母。(8)strupr(str):將字符串中小寫字母轉換成大寫字母。8.3.3字符串數組對于多個字符串的處理需用字符串數組描述,字符串數組相當于二維字符數組。例如:
(1)100個城市名:
charcity[100][17];/*假定城市名不超過16個字符*/100個城市名分別用city[0]、city[1]、…、city[99]描述,city[i]相當于一個字符數組。(2)1000本書名:
charbook[1000][31];/*假定書名不超過30個字符*/1000本書名分別用book[0]、book[1]、…、book[999]描述,book[i]相當于一個字符數組。例8-8
用字符數組輸出下面的圖案。***********程序如下:/*程序8-8,用字符數組輸出圖案*/main(){staticcharch[3][5]={"***","*****","***"};
puts(ch[0]);
printf("\n");
puts(ch[1]);
printf("\n");
puts(ch[2]);
printf("\n");
}
例8-9輸入一行字符,統計數字字符、字母字符及其它字符的個數。算法提示:
(1)一行字符用一維字符數組line描述。數字字符、字母字符及其它字符的個數用大小為3的一維整型數組num描述。
(2)對line數組的分量依次判斷,若是數字字符,則數字字符數加1;若是字母字符,則字母字符數加1;否則,其它字符的個數加1。程序如下:/*程序8-9,統計數字字符、字母字符及其它字符的個數*/main(){charline[81];/*假定一行不超過80個字符*/inti;
intnum[3]={0,0,0};
gets(line);/*讀入一行字符*/for(i=0;line[i]!='\0';i++)if(line[i]>='0'&&line[i]<='9')num[0]++;
elseif((line[i]>='a'&&line[i]<='z')||(line[i]>='A'&&line[i]<='Z')num[1]++;
elsenum[2]++;
printf("數字字符數=%d字母字符數=%d其它字符數=%d",num[0],num[1],num[2]);}
例8-10
求80個字符串中的最大者。算法提示:
(1)80個字符串用二維字符數組str描述。
(2)字符串最大者的求法與求最大值的方法完全相同,但比較、賦值操作需用函數strcmp()、strcpy()完成。程序如下:/*程序8-10,求80個字符串中的最大者*/main(){charstr[80][21];/*假定字符串的最大長度不超過20個字符*/inti;
charmstr[21];/*存放最大者*/for(i=0;i<80;i++)gets(str[i]);
strcpy(mstr,str[0]);/*最大者初始化為第一個字符串*/for(i=1;i<80;i++)/*求最大者*/if(strcmp(str[i],mstr)>0)strcpy(mstr,str[i]);
printf("字符串中的最大者=%s",mstr);}8.4重命名類型8.4.1重命名類型的方法一般形式:
typedef已有類型新類型名;一旦重命名類型,就可以用新類型名來描述數據。習慣上新類型名用大寫字母表示。例如:①typedefintinteger;/*重命名整型integer*/integeri,j;/*定義整型變量i、j*/②typedefintCOUNT;/*命名一計數類型COUNT*/COUNTn1,n2;/*定義計數型變量n1、n2*/③typedefintNUM[100];/*命名一整型數組類型NUM*/NUMn;/*定義NUM型數組n*/④typedefcharSTRING[81];/*命名一字符串類型STRING*/STRINGstr1,str2;/*定義STRING型變量str1、str2*/⑤typedefstruct{intday;
intmonth;
intyear;
}DATE;/*命名一結構體類型DATE*/DATEdate1,date2;/*定義DATE型變量date1、date2*/8.4.2重命名類型的作用重命名類型的作用如下:
(1)有利于加強數據描述的針對性,增加程序的可讀性。如用上面的重命名類型COUNT來定義計數器變量,用途一目了然。(2)有利于程序的通用和移植。
C語言程序設計有時可能會依賴于具體的計算機。例如,整型數據在某種機器上可能占2字節內存單元,在另外一種機器上又可能占4字節的內存單元,若將程序從2字節的機器移植到4字節的機器,則要將所有int說明改成long說明,修改的部分可能較多,程序的移植性較差。在整型數占2字節的機器上,若用typedef重命名類型:typedefintinteger;,則可用integer定義變量。若要將程序移植到整型數占4字節的機器上,只要用long代替原來的int即可,這時可再用typedef重命名類型:typedeflonginteger;。
(3)有利于減少程序書寫的工作量。若程序中有不少地方要用到同一種復雜數據類型,書寫起來比較復雜,通過重命名類型,可減少重復勞動。8.4.3幾點說明
(1)用typedef只能對已有類型增加一個名字,而不能定義一個新的類型。
(2)用typedef可以對各種已有類型增加新的類型名,但不能用來定義變量。
(3)重命名類型可以將數組類型與數組變量分離開來。
(4)重命名類型與編譯預處理不同,它是在編譯時處理的,實際上也并不是作簡單的字符串替換。
(5)常將一些常用的重命名類型單獨放在一個文件中,需要時用#include指令將它們包含至程序中。8.5程序設計舉例
例8-11
求n個實數的和、積、最大值及最小值。本題的算法我們已很清楚,這里是在考察在用數組描述數據的情況下的實現。求和、積、最大值、最小值均用數組作參數的函數完成。引入數組后,最大值、最小值可用其下標來描述,先假定最大值、最小值是數組的第一個分量。程序如下:/*程序8-11,求n個數的和、積、最大值、最小值*/#defineN100main(){floata[N];
intn;
inti;
floatsf();/*函數申明*/floatmf();
floatmax();
floatmin();
scanf("%d",&n);/*輸入n個數*/for(i=1;i<=n;i++)scanf("%f",&a[i]);printf("和=%8.3f\n",sf(a,n));/*輸出結果*/printf("積=%8.3f\n",mf(a,n));printf("最大值=%8.3f\n",max(a,n));printf("最小值=%8.3f\n",min(a,n));}
floatsf(xa,xn)/*求和*/floatxa[];intxn;{inti;
floats=0;for(i=1;i<=xn;i++)s+=xa[i];
return(s);}
floatmf(xa,xn)/*求積*/floatxa[];intxn;{inti;
floatm=1;
for(i=1;i<=xn;i++)m*=xa[i];
return(m);}floatmax(xa,xn)/*求最大值*/floatxa[];intxn;{inti,k=1;/*k存放最大值下標*/for(i=2;i<=xn;i++)if(xa[i]>xa[k])k=i;
return(xa[k]);}
floatmax(xa,xn)/*求最小值*/floatxa[];intxn;{inti,k=1;/*k存放最小值下標*/for(i=2;i<=xn;i++)if(xa[i]<xa[k])k=i;
return(xa[k]);}
例8-12
給定一個4×3的整數矩陣,求矩陣中最小值及最小值所在行的行號和列號。程序如下:/*程序8-12,求矩陣中最小值及其位置*/main(){inta[4][3];/*存放矩陣*/inti,j;
intmin,row,col;/*存放最小值及最小值所在行的行號、列號*/for(i=0;i<4;i++)/*輸入矩陣*/for(j=0;j<3;j++)scanf("%d",&a[i][j]);row=0;col=0;min=a[0][0];/*初始化最小值及最小值所在行的行號、列號*/for(i=0;i<4;i++)/*求最小值及最小值所在行的行號、列號*/for(j=0;j<3;j++)if(a[i][j]<min){min=a[i][j];
row=i;col=j;
}printf("最小值為%d,處在%d行%d列",min,row,col);
例8-13
將n個實數由大到小排序。
n個實數用數組a描述。本例提供用選擇排序方法與冒泡排序方法分別實現n個實數由大到小排序的函數。算法一:選擇排序。選擇排序需反復進行求最大值與交換兩個數這兩種基本操作。對a[0]、a[1]、…、a[n?1]由大到小排序:先求所有數的最大值,然后將最大值與a[0]進行交換;再求a[1]至a[n-1]這些數的最大值,然后將最大值與a[1]進行交換;再求a[2]至a[n-1]這些數的最大值,然后將最大值與a[2]進行交換……最后求a[n-2]與a[n-1]這些數的最大值,然后將最大值與a[n?2]進行交換。如此經過n-1輪處理完成排序。排序函數如下:voidsort1(a,n)/*選擇排序函數*/floata[];intn;{intk,i,j;/*k最大值下標,i、j循環控制變量*/floatt;/*中間變量,用于兩個數的交換*/for(i=0;i<n?1;i++){k=i;/*求最大值下標*/for(j=i+1;j<n;j++)if(a[j]>a[k])k=j;
t=a[i];a[i]=a[k];a[k]=t;/*進行交換*/}}
算法二:冒泡排序。冒泡排序需反復進行相鄰兩個數的比較與交換這兩種基本操作。對相鄰的兩個數進行比較時,如果后面的數大于前面的數,將這兩個數進行交換,大的數往前冒。將所有相鄰的兩個數比較一遍,稱為一輪比較。如果一輪比較中無交換,則排序完成。有無交換用一標志變量描述,一輪比較用for循環完成,整個排序利用標志變量用條件循環控制。排序函數如下:voidsort2(a,n)/*冒泡排序函數*/floata[];intn;{inti;/*一輪比較的循環控制變量*/intflag;/*標志變量,為1有交換,為0無交換*/floatt;/*中間變量,用于兩個數的交換*/do{flag=0;/*先假定無交換,已排好序*/for(i=0;i<n-2;i++)if(a[i+1]>a[i]){t=a[i];a[i]=a[i+1];a[i+1]=t;/*進行交換*/flag=1;/*有交換,標志變量的值改變為1*/}}while(flag);}
例8-14
篩法求2~1000之間的所有素數。算法提示:
(1)建立篩子,在這里正好利用數組作篩子,下標對應于數,相應下標變量的值標志是否在篩子中,為1表示在篩子中,為0表示已被篩去,不在篩子中。
(2)找每一輪篩選種子,篩選種子是完成一輪篩選后的下一個最小的素數,初值為2。
(3)對每一輪篩選種子,篩去其所有倍數,即將相應下標變量的值賦值為0。倍數初值為篩選種子的2倍。
(4)篩選完成,篩子中剩下的即為素數。程序如下:/*程序8-14,篩法求2~1000之間的所有素數*/main(){inta[1000]; /*篩子數組*/inti;
intminp,double; /*minp篩選種子,double倍數*/intn=0; /*素數個數,用于輸出格式控制*/for(i=2;i<1000;i++) /*建立篩子*/a[i]=1;
minp=2; /*篩選種子初始化*/while(minp<500) /*完成整個篩選*/{double=2*minp; /*倍數初始化*/while(double<1000) /*完成一輪篩選*/{a[double]=0; /*篩去當前倍數*/double+=minp; /*計算下一個倍數*/}do /*計算下一輪篩選種子*/{minp++;
}while(a[minp]==0);}printf("2~1000之間的所有素數如下:\n");/*輸出*/for(i=2;i<1000;i++)if(a[i]==1){printf("%6d",i);
n++;
if(n%5==0)printf("\n"); /*5個素數輸出在一行*/}}
例8-15
求10~1000之間的回文數。算法提示:
(1)要判斷一個數是不是回文數,先將其數字分離,用一數組a存放,然后將相應數字進行比較。
(2)引入一標志變量flag,為1表示是回文數,為0表示不是回文數。程序如下:/*程序8-15,求10~1000之間的回文數*/main(){inti,x;
inta[8],j;
intb,e;
intflag;
for(i=10;i<1000;i++){j=0;x=i; /*將數i的數字分離,用數組a存放*/while(x>0){a[j]=x%10;
x/=10;
j++;
}flag=1; /*先假定i為回文數*/b=0;e=j?1;
while(b<e&&flag) /*判斷i是否為回文數*/if(a[b]!=a[e])flag=0; /*將對應位數字進行比較*/else{b++;e--;}if(flag)printf("%6d",i); /*i是回文數,輸出*/}}
例8-16
從n個數據中查找指定數。
n個數據用一數組a描述,查找對象用x描述。算法一:將n個數據與查找對象依次比較,進行順序查找,請讀者編程實現。
算法二:比順序查找進一步的是折半查找或稱二分查找。折半查找要求n個數據已排好序,排序的目的就是為了快速查找。假定n個數據已經由小到大排好序。查找到的數據用其下標k表示,是否找到用一標志變量flag描述。查找問題轉化成在區間[0,n-1]中找k。折半查找時先計算其中點d,如果a[d]=x,則k=d,找到;如果a[d]>x,則查找區間縮小為[0,d];如果a[d]<x,則查找區間縮小為[d,n-1]。要么找到,要么查找區間縮小一半,繼續折半查找。折半查找函數如下:floatsearch(a,n,x) /*折半查找函數*/floata[],x;intn;{intk,flag;
intb=0,e=n?1,d;
flag=0; /*找到標志*/do{d=(b+e)/2;
if(a[d]==x){k=d;flag=1;}elseif(a[d]>x)e=d;
elseb=d;
}while(b<e&&!flag);
if(flag==0)k=-1; /*沒找到*/return(k);}
例8-17
某班有50個學生,期終考試考了8門課程。求每個學生的總成績及平均成績,并按總成績由高到低排序。算法提示:
(1)每個學生包括姓名和8門課程成績,50個學生的數據分別用二維字符數組st、二維實型數組cj描述,通過第一個下標進行關聯。
(2)50個學生的總成績和平均成績用二維實型數組tacj描述,同樣通過第一個下標與其姓名、8門課程成績進行關聯。
(3)排序采用冒泡排序方法。
(4)整個程序由輸入input()、計算總成績及平均成績count()、排序sort()、輸出output()四個模塊組成。
(5)使用外部數組完成數據傳遞。程序如下:/*程序8-17,成績處理程序*/charst[51][12]; /*采用外部數組實現數據傳遞*/floatcj[51][9];floattacj[51][3];main(){voidinput(); /*函數申明*/voidcount();
voidsort();
voidoutput();
input(); /*調用輸入函數*/count(); /*調用計算函數*/sort(); /*調用排序函數*/output(); /*調用輸出函數*/}voidinput() /*輸入函數*/{inti,j;
for(i=1;i<=50;i++){printf("請輸入第%d個學生姓名,成績:\n",i);
scanf("%s",st[i]);
for(j=1;j<=8;j++)scanf("%f",&cj[i][j]);
}}voidcount() /*計算函數*/{inti,j;
for(i=1;i<=50;i++){tacj[i][1]=0;
for(j=1;j<=8;j++)tacj[i][1]+=cj[i][j];
tacj[i][2]=tacj[i][1]/8;
}}voidsort() /*排序函數*/{inti,flag;
charts[12];
floatt;
do{flag=0;
for(i=1;i<=49;i++)if(tacj[i+1][1]>tacj[i][1]){strcpy(ts,st[i]);strcpy(st[I],st[i+1]);strcpy(st[i+1],st);/*交換姓名*/for(j=1;j<=8;j++) /*交換8門課程成績*/{t=cj[i][j];cj[i][j]=cj[i+1][j];cj[i+1][j]=t;}t=tacj[i][1];tacj[i][1]=tacj[i+1][1];tacj[i+1][1]=t;/*交換總成績*/t=tacj[i][2];tacj[i][2]=tacj[i+1][2];tacj[i+1][2]=t;/*交換平均成績*/flag=1;
}}while(flag);}voidoutput()/*輸出函數*/{inti;
printf("50個學生成績處理結果如下:\n");
printf("姓名課程1課程2課程3課程4課程5課程6課程7課程8總成績平均成績名次\n");
for(i=1;i<=50;i++){printf("%8s",st[i]);
for(j=1;j<=8;j++)printf("%7.2f",cj[i][j]);
printf("%7.2f%7.2f%5d",tacj[i][1],tacj[i][2],i);
printf("\n");
}}
例8-18
用遞歸的方法計算n個數的最大公約數和最小公倍數。算法提示:
(1)定義外部數組a存放n個數,假定n不超過50。
(2)先計算頭兩個數的最大公約數和最小公倍數;再計算求出的最大公約數和最小公倍數與第3個數的最大公約數和最小公倍數;再計算與第4個數的最大公約數和最小公倍數……直至求出與最后一個數的最大公約數和最小公倍數即為所求。
(3)定義遞歸函數gysfn()計算n個數的最大公約數,遞歸函數gbsf()計算n個數的最小公倍數。其中都調用求兩個數的最大公約數函數gysf2()。
(4)主函數中僅進行n個數的輸入和計算結果的輸出。程序如下:/*例8-18,用遞歸的方法計算n個數的最大公約數和最小公倍數*/intn,a[50]; /*數組a存放n個數*/intgysf2(); /*計算兩個數的最大公約數*/intgysfn(); /*計算n個數的最大公約數*/intgbsf(); /*計算n個數的最小公倍數*/main(){inti;
clrscr();
printf("輸入數的個數:");scanf("%d",&n);
for(i=0;i<n;i++){printf("輸入第%d個數:",i);scanf("%d",&a[i]);}printf("\n\n");printf("最大公約數=%d\n",gys
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 上海海事大學工程熱力學課件第3章 理想氣體的性質
- 教育技術如何助力學生個性化學習需求
- 南陽農業職業學院《合唱排演賽二》2023-2024學年第二學期期末試卷
- 全球教育技術市場的發展與挑戰
- 從心理角度探討學習者的成功因素
- 繪本小種子講課件
- 沈陽師范大學《醫學寄生蟲》2023-2024學年第二學期期末試卷
- 2024年度河南省護師類之社區護理主管護師題庫練習試卷B卷附答案
- 廣州華立學院《世紀外國文學專題》2023-2024學年第二學期期末試卷
- 甘肅醫學院《現代分子生物學實驗技術與儀器分析》2023-2024學年第二學期期末試卷
- 江西省贛州市2024-2025學年高一物理下學期期末考試試題
- 2024研學旅行合同書
- 探監證明樣本范文(篇一)
- 湖南省長沙市雨花區2023-2024學年三年級下學期期末考試英語試題
- 5 搭石 第一課時(教學設計)統編版語文五年級上冊
- 體育指導員協會籌備
- MOOC 新媒體文化十二講-暨南大學 中國大學慕課答案
- 廣西博物館2024事業單位招聘通過歷年高頻考題難、易錯點模擬試題(共500題)附帶答案詳解
- 展廳講解員培訓方案
- 物流服務營銷策略分析
- MOOC 光纖通信-南京郵電大學 中國大學慕課答案
評論
0/150
提交評論