版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第4章數(shù)組
4.1一維數(shù)組4.2二維數(shù)組
4.3字符數(shù)組和字符串
4.4典型例題精講
4.1一維數(shù)組
4.1.1一維數(shù)組的定義
數(shù)組元素可以有多個(gè)下標(biāo),下標(biāo)的個(gè)數(shù)表示數(shù)組的維數(shù),只有一個(gè)下標(biāo)時(shí)表示該數(shù)組為一維數(shù)組。數(shù)組的使用也必須遵循“先定義,后使用”這一原則。一維數(shù)組定義的一般形式如下:類型標(biāo)識符數(shù)組名[常量表達(dá)式];數(shù)組定義包含以下幾個(gè)要點(diǎn):
(1)類型標(biāo)識符用來指明數(shù)組元素的類型,同一數(shù)組的元素其類型相同;類型標(biāo)識符可以是任意一種基本數(shù)據(jù)類型或者構(gòu)造數(shù)據(jù)類型。
(2)數(shù)組名的命名規(guī)則與普通變量相同,但不得與其他變量或數(shù)組同名;數(shù)組名表示該數(shù)組在內(nèi)存中存放的首地址,是一個(gè)地址常量。
(3)方括號“[]”是數(shù)組的標(biāo)志,方括號中的常量表達(dá)式表示數(shù)組的元素個(gè)數(shù),即數(shù)組的長度(大小)。
(4)常量表達(dá)式是整型常量、符號常量及由它們組成的表達(dá)式,但不允許出現(xiàn)變量。
例如:
inta[5];在此,數(shù)組a共有5個(gè)元素:a[0]、a[1]、a[2]、a[3]和a[4],且每個(gè)元素都是整型的。特別要注意的是,數(shù)組元素的下標(biāo)從0開始,直至數(shù)組元素的個(gè)數(shù)減1,數(shù)組a的內(nèi)存分配示意見圖4-1,從圖中可以看到:數(shù)組名a實(shí)際上就是數(shù)組元素a[0]的地址。C語言的編譯器不對數(shù)組的越界問題進(jìn)行檢查,直到運(yùn)行時(shí)才給出出錯(cuò)信息,這一點(diǎn)要特別注意。圖4-1inta[5]的內(nèi)存分配示意例4.1指出下面的數(shù)組定義中哪些是正確的,哪些是錯(cuò)誤的。
intx[40],y[20],z(10);
floatb[7.5],s[8];
intm;
charm[15],ch[m];
[解]對本題的數(shù)組定義說明如下:
(1)對“intx[40],y[20],z(10);”,其中數(shù)組x、y的定義是正確的,而數(shù)組z的定義有錯(cuò),因?yàn)閿?shù)組的標(biāo)志是方括號“[]”,而不是圓括號“()”。
(2)對“floatb[7.5],s[8];”,其中數(shù)組s定義是正確的,而數(shù)組b因其表示數(shù)組元素個(gè)數(shù)的常量表達(dá)式是一浮點(diǎn)型常量,而不是整型常量,因此出錯(cuò)。
(3)對“charm[15],ch[m];”,數(shù)組m因?yàn)榕c整型變量m同名而出錯(cuò),數(shù)組ch的常量表達(dá)式是一變量m,而不是常量,因此出錯(cuò)。4.1.2一維數(shù)組的引用和初始化數(shù)組必須先定義、后使用,并且只能逐個(gè)引用數(shù)組元素而不能一次引用整個(gè)數(shù)組。數(shù)組元素的引用格式為:數(shù)組名[下標(biāo)]其中,方括號“[]”中的下標(biāo)只能是整型常量或整型表達(dá)式。例如:
a[5]
b[i+2*j]/*i和j均為整型變量*/
c[i+1]/*i為整型變量*/都是合法的數(shù)組元素。程序在引用數(shù)組元素的值之前,必須先給數(shù)組元素置初始值。數(shù)組元素的初始值可以由鍵盤輸入,也可以通過賦值語句來設(shè)置。在程序每次運(yùn)行時(shí)數(shù)組元素的初值都固定不變的情況下,可以在數(shù)組定義時(shí)就給定其元素的初值;這種方式稱為數(shù)組的初始化。數(shù)組初始化可以有以下幾種方法:
(1)在數(shù)組定義時(shí)給數(shù)組所有元素賦初值。例如:
inta[5]={0,1,2,3,4,};將數(shù)組元素的初值用“,”分隔依次寫在一對花括號“{}”內(nèi)。經(jīng)過上面的定義和初始化之后,就有:
a[0]=0,a[1]=1,a[2]=2,a[3]=3,a[4]=4如果想使一個(gè)數(shù)組中全部元素的初值均為0,則可寫成:
inta[10]={0,0,0,0,0,0,0,0,0,0};或者:
inta[10]={0};此時(shí),a[0]被賦初值0,而其余未賦初值的數(shù)組元素均由系統(tǒng)給其賦0。注意,如果寫成:
inta[10]={2};則a[0]被賦初值2,而其余數(shù)組元素均由系統(tǒng)給其賦初值0。
(2)數(shù)組定義時(shí)只給前面一部分元素賦初值。例如:
intb[10]={0,1,2,3};定義b數(shù)組有10個(gè)元素,其中前4個(gè)元素賦予了初值,而后6個(gè)元素值自動(dòng)被賦以“0”值(僅對數(shù)值型數(shù)組)。
(3)如果數(shù)組的全部元素都設(shè)置了初值,則定義中可不指定數(shù)組的長度。例如:
inta[5]={1,2,3,4,5};可以寫成:
inta[]={1,2,3,4,5};此時(shí),系統(tǒng)會根據(jù)花括號“{}”中的初值個(gè)數(shù)來確定數(shù)組的長度,但是數(shù)組的標(biāo)志“[]”不能省略。此外,如果提供的初值個(gè)數(shù)小于希望的數(shù)組長度,則方括號中的常量表達(dá)式不能省略。例如,需要定義數(shù)組a長度為10,但初值前5個(gè)為1、2、3、4、5,則不能寫成:
inta[]={1,2,3,4,5};而必須寫成:
inta[10]={1,2,3,4,5};除了數(shù)組初始化之外,通常是通過for語句循環(huán)為數(shù)組的每一個(gè)元素讀入數(shù)據(jù)或者輸出數(shù)據(jù)。例如:
inta[10],i;
for(i=0;i<10;i++)
scanf("%d",&a[i]);為數(shù)組a的每一個(gè)元素輸入數(shù)據(jù),或者通過下面的for語句輸出每一個(gè)數(shù)組元素的值:
for(i=0;i<10;i++)
printf("%4d",a[i]);例4.2已定義數(shù)組a如下:
inta[6]={1,2,3,4,5,6};現(xiàn)通過下面兩種輸出語句來輸出數(shù)組a中每一個(gè)元素的值:
(1)?printf("%4d",a[6]);
(2)?printf("%4d",a);請指出它們的錯(cuò)誤并給出正確的輸出語句。
[解]語句(1)只是輸出了下標(biāo)序號為6這個(gè)數(shù)組元素的值,而沒有輸出所有數(shù)組元素的值,并且數(shù)組a只有a[0]~a[5]?這6個(gè)數(shù)組元素而并不存在a[6],所以該語句是錯(cuò)誤的。語句(2)輸出的變量是數(shù)組名a,而a是一個(gè)地址常量,它代表數(shù)組a的首地址,所以該語句也無法輸出所有數(shù)組元素值而僅輸出了數(shù)組a的首地址。正確的輸出語句如下:
for(i=0;i<=5;i++)
printf("%d",a[i]);例4.3給數(shù)組a輸入任意一組數(shù)據(jù),然后實(shí)現(xiàn)數(shù)組元素的逆置,最后輸出逆置后的數(shù)組元素。
[解]實(shí)現(xiàn)數(shù)組元素的逆置示意見圖4-2。圖4-2實(shí)現(xiàn)數(shù)組元素的逆置示意因此,對n個(gè)數(shù)據(jù)元素進(jìn)行逆置的for語句只能循環(huán)n/2次。實(shí)現(xiàn)逆置的程序如下:#include<stdio.h>voidmain(){ inta[20],i,n,x; printf("Inputnumberofelements:");
scanf("%d",&n); printf("Inputelement:\n"); for(i=0;i<n;i++) /*輸入數(shù)據(jù)*/
scanf("%d",&a[i]); printf("Before:\n"); /*輸出輸入的數(shù)據(jù)*/ for(i=0;i<n;i++) printf("%4d",a[i]); printf("\n"); for(i=0;i<n/2;i++) /*實(shí)現(xiàn)逆置*/ {
x=a[i]; a[i]=a[n-i-1]; a[n-i-1]=x; } printf("After:\n"); for(i=0;i<n;i++) printf("%4d",a[i]); printf("\n");}運(yùn)行結(jié)果:Inputnumberofelements:10↙Inputelement:12345678910↙Before:12345678910After:10987654321
例4.4用數(shù)組實(shí)現(xiàn)Fibonacci數(shù)列前20項(xiàng)數(shù)據(jù)的輸出。
[解]在第3章中求Fibonacci數(shù)列的方法是每求出兩個(gè)值時(shí)就進(jìn)行輸出,然后繼續(xù)求后繼的兩個(gè)值。這里,我們每求出一個(gè)值就保存于數(shù)組f中;當(dāng)求出所需長度的Fibonacci數(shù)列后(已保存于數(shù)組f中),再通過for循環(huán)輸出數(shù)組f中保存的Fibonacci數(shù)列值。程序編寫如下:#include<stdio.h>voidmain(){ inti; intf[20]={1,1}; for(i=2;i<20;i++) f[i]=f[i-2]+f[i-1]; for(i=0;i<20;i++){ if(i%5==0)/*每輸出5項(xiàng)換一行*/ printf("\n"); printf("%12d",f[i]); } printf("\n");}運(yùn)行結(jié)果:
11235813213455891442333776109871597258441816765例4.5任意輸入一個(gè)十進(jìn)制數(shù),將其轉(zhuǎn)換成二進(jìn)制數(shù)并按位保存于數(shù)組中,最后輸出數(shù)組中所保存的二進(jìn)制數(shù)。
[解]由十進(jìn)制數(shù)轉(zhuǎn)換為二進(jìn)制數(shù)的方法可知:將十進(jìn)制數(shù)每次除2,其余數(shù)按先后順序逆序排列即為該十進(jìn)制數(shù)對應(yīng)的二進(jìn)制數(shù)。因此,我們采用的方法如下:當(dāng)十進(jìn)制數(shù)n不等于0時(shí),先對2取余(即“%”),將余數(shù)存于數(shù)組a中,然后對n除以2,再重復(fù)剛才的這兩步操作,直到n等于0;這樣最終a[0]、a[1]、…、a[i-1]保存著該十進(jìn)制數(shù)對應(yīng)二進(jìn)制數(shù)的最低位、次低位、……、最高位的值。程序編制如下:#include<stdio.h>voidmain(){ inti=0,j,n,a[20]; printf("Inputdata:"); scanf("%d",&n);
while(n!=0) { a[i]=n%2; n=n/2; i++;} printf("Output:\n"); for(j=i-1;j>=0;j--)/*二進(jìn)制數(shù)由高位到低位輸出*/ printf("%4d",a[j]); printf("\n");}運(yùn)行結(jié)果:Inputdata:11↙Output:10114.2二維數(shù)組
4.2.1二維數(shù)組的定義
如果一維數(shù)組看做是同一類型變量的一個(gè)線性排列,那么二維數(shù)組則可認(rèn)為是同一類型變量的一個(gè)平面排列,即行和列。實(shí)際上也是這樣,二維數(shù)組元素有兩個(gè)下標(biāo),一個(gè)是行下標(biāo),一個(gè)是列下標(biāo)。由于二維數(shù)組是多維數(shù)組中比較容易理解的一種,并且它可以代表多維數(shù)組處理的一般方法,所以,在此主要介紹二維數(shù)組。二維數(shù)組定義的一般形式如下:類型標(biāo)識符數(shù)組名[常量表達(dá)式1][常量表達(dá)式2];其中,常量表達(dá)式1表示第一維的長度(即行數(shù)),常量表達(dá)式2表示第二維的長度(即列數(shù))。二維數(shù)組元素的總數(shù)為常量表達(dá)式1與常量表達(dá)式2的乘積。例如:
inta[3][4];
定義了一個(gè)3行4列的數(shù)組,數(shù)組名為a,其數(shù)組元素的類型為整型,該數(shù)組共有3?×?4個(gè)元素,這些元素排列如下:
a[0][0],a[0][1],a[0][2],a[0][3]
a[1][0],a[1][1],a[1][2],a[1][3]
a[2][0],a[2][1],a[2][2],a[2][3]注意,二維數(shù)組的定義不能寫成:inta[3,4];
與一維數(shù)組的定義相同,二維數(shù)組定義中的兩個(gè)常量表達(dá)式必須是常量,不能是變量。二維數(shù)組在內(nèi)存中是以一維線性方式排列的,并且采用行優(yōu)先原則:先存儲第一行元素,然后在第一行元素之后順序存儲第二行元素,依此類推,直至存儲完二維數(shù)組中的全部元素。對于定義了3行4列的“inta[3][4];”來說,其內(nèi)存分配示意如圖4-3所示。圖4-3對應(yīng)“inta[3][4];”的內(nèi)存分配示意
由圖4-3可知,數(shù)組名a是二維數(shù)組a的起始地址,也就是數(shù)組元素a[0][0]?的地址;而a[0]、a[1]、a[2]?則分別是二維數(shù)組a各行的起始地址;即a[0]?對應(yīng)數(shù)組元素a[0][0]?的地址、a[1]?對應(yīng)數(shù)組元素a[1][0]?的地址,而a[2]?則對應(yīng)數(shù)組元素a[2][0]?的地址。我們可以這樣理解,即把二維數(shù)組看做是一種特殊的一維數(shù)組,這個(gè)數(shù)組中的每個(gè)元素又是一個(gè)一維數(shù)組。也就是說,我們把二維數(shù)組a看做是一個(gè)一維數(shù)組,它有3個(gè)元素a[0]、a[1]?和a[2],而每一個(gè)元素又是一個(gè)包含了4個(gè)元素的一維數(shù)組,而a[0]、a[1]?和a[2]?就是其對應(yīng)的數(shù)組名。因此,a[0]、a[1]?和a[2]?在二維數(shù)組中是數(shù)組名(即為一個(gè)地址),而決不能當(dāng)作元素使用,并且a[0]?和a都是指向a[0][0]?這個(gè)數(shù)組元素的地址。4.2.2二維數(shù)組的引用和初始化
二維數(shù)組元素的引用方式為:數(shù)組名[行下標(biāo)1][列下標(biāo)2]其中,方括號“[]”中的行、列下標(biāo)既可以是整型常量也可以是整型表達(dá)式。二維數(shù)組也必須先定義后使用,并且也只能逐個(gè)引用數(shù)組元素。二維數(shù)組存在著行和列,因此二維數(shù)組的行下標(biāo)是在0到數(shù)組行數(shù)減1之間變化,而列下標(biāo)是在0到數(shù)組列數(shù)減1之間變化。同樣,C語言也不對二維數(shù)組做越界檢查,所以要特別注意。例如,對二維數(shù)組的定義:
inta[2][2];則
a[1][0]=5;
a[0][1]=a[1][1]+8;都是正確的,而
a[1][2]=10;/*列越界*/
a[0,0]=7;/*行下標(biāo)和列下標(biāo)都必須放在方括號“[]”中*/是錯(cuò)誤的。
二維數(shù)組的初始化可以有以下幾種方法:
(1)按行分段給每個(gè)元素賦初值。例如:
inta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};這種賦初值方法比較直觀,行和列都很清楚。
(2)按數(shù)組元素在內(nèi)存中的排列順序給每個(gè)元素賦值。例如:
inta[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
(3)給部分元素賦初值。當(dāng)“{}”中值的個(gè)數(shù)少于二維數(shù)組的元素個(gè)數(shù)時(shí),只給前面的部分元素賦值,而后面的元素自動(dòng)取“0”值。例如:
inta[3][3]={{1},{2,3},{4}};它等價(jià)于:
inta[3][3]={{1,0,0},{2,3,0},{4,0,0}};
(4)給全部元素賦初值。此時(shí)定義二維數(shù)組的第一維(行)大小可以省略,但第二維(列)大小不能省略。否則無法知道行和列各自的大小。例如:
inta[][4]={1,2,3,4,5,6,7,8,9};則系統(tǒng)根據(jù)每行放4個(gè)元素,放下這9個(gè)值必須大于等于9個(gè)元素,故需要3行;即二維數(shù)組a為3行4列。又如:
inta[][4]={{1,2,3},{1,2},{4}};對于這種按行分段賦值方式,系統(tǒng)會根據(jù)最外面的花括號內(nèi)有幾個(gè)花括號“{}”來確定行數(shù);因此系統(tǒng)認(rèn)為二維數(shù)組a有3行。例4.6一程序如下:#include<stdio.h>voidmain(){ intx[3][2]={0},i;
for(i=0;i<3;i++) scanf("%d",x[i]);
printf("%d%d%d\n",x[0][0],x[0][1],x[1][0]);}若運(yùn)行時(shí)輸入:246↙則輸出的結(jié)果為
。A)200B)204C)240D)246
[解]我們知道,x[0]、x[1]?和x[2]?分別對應(yīng)二維數(shù)組x各行的首地址,即數(shù)組元素x[0][0]、x[1][0]?和x[2][0]?的地址(x[i]?即為?&x[i][0])。所以,語句“scanf("%d",x[i]);”寫法正確(因x[i]?為一地址);這樣當(dāng)輸入為“246↙”時(shí),相應(yīng)的數(shù)組元素x[0][0]?的值為2、x[1][0]的值為4、x[2][0]?的值為6,而其余數(shù)組元素的值不變?nèi)詾椤?”。最后,我們得到輸出結(jié)果應(yīng)為:204,因此選B。例4.7定義一個(gè)3行4列的二維數(shù)組,并逐行輸入二維數(shù)組元素值,再逐行輸出二維數(shù)組的元素值。
[解]我們知道,一維數(shù)組元素值的輸入輸出都是通過一個(gè)for語句實(shí)現(xiàn)的;而二維數(shù)組的輸入和輸出則需要用兩個(gè)for語句組成的兩層循環(huán)來實(shí)現(xiàn),即外層for語句控制行的變化,而內(nèi)層for語句控制列的變化。實(shí)現(xiàn)的程序如下:#include<stdio.h>voidmain(){ inta[3][4],i,j; printf("Inputdata:\n"); for(i=0;i<3;i++)
for(j=0;j<4;j++) scanf("%d",&a[i][j]);
printf("Outputdata:\n"); for(i=0;i<3;i++) { for(j=0;j<4;j++) printf("%5d",a[i][j]); printf("\n"); }}運(yùn)行結(jié)果:Inputdata:1234↙5678↙9101112↙Outputdata:
123456789101112
例4.8輸入年、月、日,求這一天是該年的第幾天。
[解]為確定一年中的第幾天,需要一張每月的天數(shù)表,該表給出每個(gè)月的天數(shù)。由于二月份的天數(shù)因閏年和平年相差一天。所以把月份天數(shù)表設(shè)計(jì)成2行12列的二維數(shù)組;數(shù)組的第0行給出平年各月份的天數(shù),數(shù)組的第1行給出閏年各月份的天數(shù)。為了計(jì)算某月某日是這年的第幾天,則首先確定這一年是平年還是閏年,然后根據(jù)各月份的天數(shù)表將前幾個(gè)月的天數(shù)與當(dāng)月的日期累加,就得到了某年某月某日是該年的第幾天。程序編制如下:#include<stdio.h>voidmain(){ intdays[][12]={{31,28,31,30,31,30,31,31,30,31,30,31}, {31,29,31,30,31,30,31,31,30,31,30,31}};intyear,month,day,leap=0,i; printf("Inputyear、month、day:\n");
scanf("%d%d%d",&year,&month,&day); if((year%4==0&&year%100!=0)||year%400==0) leap=1; for(i=0;i<month-1;i++) day=day+days[leap][i]; printf("date=%d\n",day);}運(yùn)行結(jié)果:Inputyear、month、day:2010310↙date=694.3字符數(shù)組和字符串
用來存放字符數(shù)據(jù)的數(shù)組被稱為字符數(shù)組。在C語言中沒有專門的字符串類型,而是采用字符數(shù)組來存放一串連續(xù)的字符。通常使用的字符數(shù)組是一維數(shù)組(當(dāng)然也可是多維數(shù)組),其數(shù)組元素的類型為字符類型;也即,字符數(shù)組中的每一個(gè)元素存放一個(gè)字符。4.3.1字符數(shù)組的定義、引用及初始化
1.字符數(shù)組的定義字符數(shù)組本質(zhì)上與前面介紹的數(shù)組相同,只不過它的類型標(biāo)識符是char類型。字符數(shù)組的定義方式如下:
char數(shù)組名[常量表達(dá)式];/*定義一維字符數(shù)組*/或者
char數(shù)組名[常量表達(dá)式1][常量表達(dá)式2]; /*定義二維字符數(shù)組*/例如:
charc[5];
表示定義了一個(gè)一維字符數(shù)組,數(shù)組名為c,最多可以存放5個(gè)字符。如果給字符數(shù)組c賦值如下:
c[0]=′C′;c[1]=′h′;c[2]=′i′;
c[3]=′n′;c[4]=′a′;則字符數(shù)組c的存儲如圖4-4所示。圖4-4字符數(shù)組存放字符后的情況由圖4-4可知,字符數(shù)組的存儲也是占用內(nèi)存一段連續(xù)的空間,其存儲及表示方法與前面介紹的數(shù)值型數(shù)組相同。
2.字符數(shù)組的引用字符數(shù)組的引用不同于數(shù)值型數(shù)組僅能逐個(gè)元素的引用,字符數(shù)組既可以逐個(gè)元素的引用,又可以通過字符串形式來整體引用。
(1)對字符數(shù)組元素的引用。對字符數(shù)組元素的引用與對數(shù)值型數(shù)組元素的引用完全相同。字符數(shù)組元素的引用方式為:數(shù)組名[下標(biāo)]其中方括號中“[]”的下標(biāo)只能是整型常量或整型表達(dá)式。例如:
chara[10];
a[0]=′a′;
(2)對字符數(shù)組的整體引用。例如:
charc[5]={′a′,′b′,′c′};
printf("%s",c);在printf語句中,字符數(shù)組c是以數(shù)組名整體引用的。
3.字符數(shù)組的初始化如果在定義字符數(shù)組時(shí)不進(jìn)行初始化,那么字符數(shù)組中各元素的值是不確定的??梢酝ㄟ^下列方法對字符數(shù)組進(jìn)行初始化:
(1)逐個(gè)為字符數(shù)組中的元素賦初值。例如:
chars[10]={′P′,′r′,′o′,′g′,′r′,′a′,′m′};或者:
charc[6];
c[0]=′C′;c[1]=′h′;c[2]=′i′;c[3]=′n′;c[4]=′a′;或者:
charx[10];
inti;
for(i=0;i<10;i++)
scanf("%c",&x[i]);
(2)將一個(gè)字符串整體賦給一個(gè)字符數(shù)組。例如:
chara[]={"Program"};也可以去掉花括號寫成:
chara[]="Program";注意,字符串是以空字符
′\0′(ASCII碼值為0)作為結(jié)束標(biāo)志的。因此,這個(gè)空字符也放入了字符數(shù)組a,即字符數(shù)組a的元素個(gè)數(shù)是8而不是7。當(dāng)然,我們也可如下定義字符數(shù)組a:
chara[8]="Program";另外一種整體賦值方法如下:
charx[10];
scanf("%s",x);即通過scanf語句給字符數(shù)組讀入一個(gè)字符串。對字符數(shù)組的初始化一定要注意以下幾點(diǎn):
(1)如果給字符數(shù)組賦初值的字符個(gè)數(shù)大于字符數(shù)組長度,則按語法錯(cuò)誤處理。例如:
charc[5]="China";
charx[5]={′P′,′r′,′o′,′g′,′r′,′a′,′m′};
前者以字符串形式賦給字符數(shù)組c,雖然在計(jì)算字符串長度時(shí),′\0′?不計(jì)入字符串的長度,但?′\0′?卻占用一個(gè)字符位置;因此,字符串“China”雖然長度為5,但占用6個(gè)字符元素位置,而字符數(shù)組c只能放下5個(gè)字符,故此出錯(cuò)。后者花括號中“{}”提供的初值個(gè)數(shù)已大于字符數(shù)組x的長度,因此也是錯(cuò)誤的。
(2)如果給字符數(shù)組賦初值的字符個(gè)數(shù)小于字符數(shù)組長度,則將這些字符賦給字符數(shù)組前面的那些元素,而后面未賦值的元素則由系統(tǒng)自動(dòng)賦以空字符?′\0′。例如:
charc[10]="China";則字符數(shù)組c的存儲情況見圖4-5。圖4-5數(shù)組c的存儲情況例4.9下面哪些字符數(shù)組的定義是錯(cuò)誤的,指出出錯(cuò)的原因。
(1)?chara[5]={′a′,′b′,′c′,′d′,′e′};
(2)
charb[5]="abcde";
(3)
charc[5]="a\0";
(4)
chard[5];d="abc";
[解]第(1)項(xiàng)定義正確,即逐個(gè)為字符數(shù)組中的元素賦初值,且賦初值的字符個(gè)數(shù)已等于字符數(shù)組的長度,故無空余的數(shù)組元素來存放待添加的?′\0′?字符(這一點(diǎn)與給字符數(shù)組賦一個(gè)字符串不同)。第(2)項(xiàng)定義出錯(cuò)。字符串?"abcde"?加上?′\0′?字符應(yīng)占6個(gè)元素的位置,而字符數(shù)組b的定義是元素個(gè)數(shù)為5(長度為5),故此出錯(cuò)。第(3)項(xiàng)定義正確,即將字符串?"a\0",也就是將字符?′a′?和轉(zhuǎn)義字符?′\0′?賦給字符數(shù)組c,然后再在其后添加一個(gè)字符串結(jié)束符?′\0′,因此是正確的。第(4)項(xiàng)定義錯(cuò)。給字符數(shù)組賦值,只能在定義時(shí)將雙引號括起來的字符串賦給字符數(shù)組,而不能在定義之后再通過賦值語句將字符串賦給字符數(shù)組名。例4.10下面是幾種將字符序列“ABC”賦給字符數(shù)組的方法,請指出它們在存儲上的異同。
(1)charx[6]={′A′,′B′,′C′};
(2)charx[6]="ABC";
(3)charx[6];inti;
for(i=0;i<3;i++)
scanf("%c",&x[i]);
輸入:ABC↙
(4)charx[6];
scanf("%s",x);
輸入:ABC↙
(5)?charx[6];x[0]=′A′;x[1]=′B′;x[2]=′C′;
[解](1)、(2)兩種輸入方式的存儲狀態(tài)如圖4-6(a)所示,即存儲的是字符串“ABC”,(3)、(5)的存儲狀態(tài)如圖4-6(b)所示,未存儲字符的那些數(shù)組元素其值不確定,(4)和后面將要介紹的gets(x)(輸入:ABC↙)函數(shù)存儲如圖4-6(c)所示。圖4-6不同輸入方式下字符數(shù)組x的存儲4.3.2字符串
在C語言中,字符串常量是一個(gè)用雙引號“""”括起來的有效字符序列。并且,對字符串的處理只能通過字符數(shù)組進(jìn)行。也即,一個(gè)字符串可以用一個(gè)一維字符數(shù)組來存放;若干個(gè)字符串則可以用一個(gè)二維字符數(shù)組來存放,且用每一行來存放一個(gè)字符串。
C語言規(guī)定了字符串必須以字符?′\0′?結(jié)束。也即,當(dāng)遇到字符?′\0′?時(shí)表示字符串到此結(jié)束,而它之前出現(xiàn)的字符序列則組成一個(gè)字符串。注意,′\0′?是一個(gè)轉(zhuǎn)義字符,它的ASCII值為“0”,由于它不對應(yīng)任何顯示和操作,所以又稱為空字符。系統(tǒng)在每一個(gè)字符串常量的后面自動(dòng)加上了一個(gè)表示字符串結(jié)束的字符?′\0′。因此,要將一個(gè)字符串存入一個(gè)字符數(shù)組時(shí),這個(gè)字符數(shù)組的長度不能小于該字符串的實(shí)際字符數(shù)(即長度)加1。例如:
printf("Howareyou?\n");該語句的功能是輸出一個(gè)字符串。那么,系統(tǒng)是如何實(shí)現(xiàn)這種輸出呢?實(shí)際上,在內(nèi)存存放該字符串時(shí),系統(tǒng)已經(jīng)自動(dòng)地在該字符串的最后一個(gè)字符?′\n′?之后加上了一個(gè)?′\0′?作為字符串結(jié)束的標(biāo)志;并且在執(zhí)行printf輸出語句時(shí),每輸出一個(gè)字符時(shí)都需檢查該字符是否是?′\0′,如果是?′\0′,則停止輸出。
有了字符串結(jié)束標(biāo)志?′\0′?后,字符數(shù)組的長度就無關(guān)緊要,在程序中通常是靠檢測?′\0′的位置來判斷字符串是否結(jié)束,而字符數(shù)組的長度通常是無法判斷字符串的結(jié)束(字符串通常放不滿字符數(shù)組)。在采用字符串方式后,字符數(shù)組的輸入輸出就變得更加簡單了。除了前面講述的用字符串賦初值外,還可以使用printf函數(shù)和scanf函數(shù)一次性輸出或輸入一個(gè)字符數(shù)組中的字符串,而不必再通過循環(huán)語句逐個(gè)字符地輸出或輸入。例4.11字符串的輸入輸出。#include<stdio.h>voidmain(){charst1[10],st2[10];printf("Inputstring:\n");scanf("%s%s",st1,st2);printf("Outputstring:\n");printf("%s%s\n",st1,st2);}運(yùn)行結(jié)果:Inputstring:ChinaXi′an↙Outputstring:ChinaXi′an在使用scanf和printf語句中采用格式字符“%s”輸入輸出字符串時(shí),應(yīng)注意以下幾點(diǎn):
(1)輸入輸出字符串時(shí)都使用數(shù)組名,這一點(diǎn)與scanf或printf輸入輸出其他單個(gè)字符或數(shù)值型的值不同(scanf要求的是變量的地址,而printf要求的是變量)。
(2)在輸入兩個(gè)字符串時(shí),中間必須使用空格隔開。
(3)輸入字符串時(shí),必須注意字符串的最大長度不得大于或等于字符數(shù)組的長度(最多到字符數(shù)組長度減1)。此外,要注意不是每個(gè)字符數(shù)組保存的字符序列都是一個(gè)字符串,例如下面的程序在輸出時(shí)就會出錯(cuò):include<stdio.h>voidmain(){ charst1[5]; st1[0]=′C′;st1[1]=′h′;st1[2]=′i′;st1[3]=′n′;st1[4]=′a′; printf("%s",st1);}
由于字符數(shù)組stl存放的字符序列并不是字符串(在“China”之后并沒有存儲?′\0′?字符),故在采用格式字符“%s”輸出時(shí),輸出了“China”之后仍將繼續(xù)輸出內(nèi)存中存放在“China”之后的其他數(shù)據(jù),直至遇到?′\0′?時(shí)才結(jié)束輸出。因此,一定要避免這樣的錯(cuò)誤出現(xiàn)。4.3.3常用字符串處理函數(shù)
C語言提供了豐富的字符串處理函數(shù),這些字符串處理函數(shù)可以分為字符串的輸入、輸出、修改、比較、復(fù)制(拷貝)、轉(zhuǎn)換、搜索等幾類。在編寫程序中使用用于輸入、輸出的字符串函數(shù)時(shí),程序應(yīng)包含“stdio.h”頭文件,而使用其他字符串函數(shù)時(shí),則程序還應(yīng)包含“string.h”頭文件。下面介紹幾種常用的字符串函數(shù)。
1.字符串輸出函數(shù)puts調(diào)用格式:
puts(字符數(shù)組名);其功能是將一個(gè)保存在字符數(shù)組中的以′\0′結(jié)束的字符串進(jìn)行輸出顯示,輸出時(shí)將字符串結(jié)束標(biāo)志′\0′轉(zhuǎn)換成′\n′,因此輸出完字符串后自動(dòng)換行。例如:chars[]="student";puts(s);輸出結(jié)果為:
student因此語句:“puts(s);”相當(dāng)于執(zhí)行以下的程序段:i=0;while(s[i]!=′\0′){ printf("%c",s[i]);
i++;}printf("\n");也即,函數(shù)puts完全可以由函數(shù)printf取代;當(dāng)需要按指定格式進(jìn)行輸出時(shí)則采用函數(shù)printf。此外,用puts輸出的字符串中也可以包含轉(zhuǎn)義字符,如:chars[]="Computer\nProgram";puts(s);則輸出結(jié)果為:ComputerProgram
2.字符串輸入函數(shù)gets調(diào)用格式:
gets(字符數(shù)組名);其功能是從鍵盤上輸入一個(gè)字符串直到
′\n′?為止,并將這個(gè)字符串存入函數(shù)gets指定的字符數(shù)組中,存放時(shí)系統(tǒng)自動(dòng)將?′\n′?置換成?′\0′?。例如:
charc[20];
gets(c);從鍵盤上輸入:
ComputerofChina↙則將字符串“ComputerofChina”存入到字符數(shù)組c中。因此,語句“gets(c);”相當(dāng)于執(zhí)行以下的程序段(當(dāng)輸入的字符不是“↙”時(shí)):
i=0;
scanf("%c",&c[i]);
while(c[i]!=′\n′)
{
i++;
scanf("%c",&c[i]);
}
c[i]=′\0′;
注意:“gets(c);”與“scanf("%s",c);”是有區(qū)別的;對于輸入的字符串“ComputerofChina”,scanf語句只能讀入了字符串“computer”,即函數(shù)scanf是以空格或回車符′\n′作為輸入字符串的結(jié)束標(biāo)志,而函數(shù)gets只以回車符′\n′作為輸入字符串的結(jié)束標(biāo)志。
3.字符串連接函數(shù)strcat調(diào)用格式:
strcat(字符數(shù)組1名,字符數(shù)組2名);其功能是將字符數(shù)組2中的字符串連接到字符數(shù)組1中字符串的后面,形成一個(gè)包含這兩個(gè)字符串的新字符串(也即,連接后原第一個(gè)字符串后面無?′\0′?,而替代順序放入第二個(gè)字符串的字符,但連接后形成的新字符串后面由系統(tǒng)加入一個(gè)?′\0′?)。函數(shù)調(diào)用后得到一個(gè)函數(shù)值,就是字符數(shù)組1的首地址。需要注意以下兩點(diǎn):
(1)函數(shù)strcat的第一個(gè)參數(shù)必須是字符數(shù)組名,而第二個(gè)參數(shù)可以是字符數(shù)組名也可以是用雙引號“""”括起來的字符串。
(2)由于連接的結(jié)果放在字符數(shù)組1中,因此,字符數(shù)組1的長度必須足夠大。
例4.12當(dāng)輸入為:123↙時(shí),給出下面程序的輸出結(jié)果。
#include<stdio.h>
#include<string.h>
voidmain()
{
charst1[10]="abcde";
scanf("%s",st1);
strcat(st1,"fgh");
printf("%s\n",st1);
}
[解]該程序執(zhí)行過程中其字符數(shù)組的存儲變化見圖4-7。其中,圖4-7(a)為定義字符數(shù)組st1時(shí)的存儲情況,圖4-7(b)為執(zhí)行scanf語句后的存儲情況,而圖4-7(c)則是調(diào)用strcat函數(shù)后的存儲情況。由圖4-7可知,最后輸出的結(jié)果是:123fgh。圖4-7字符數(shù)組st1存儲變化情況例4.13用程序?qū)崿F(xiàn)函數(shù)strcat功能。#include<stdio.h>voidmain(){ chara[40]="Iamateacher!"; charb[20]="Youareastudent!"; inti=0,j=0; while(a[i]!=′\0′) /*找到字符數(shù)組a中的字符串尾*/ i++;
while(b[j]!=′\0′) /*實(shí)現(xiàn)連接功能*/ a[i++]=b[j++]; a[i]=′\0′; /*賦字符串結(jié)束標(biāo)志*/ puts(a); /*輸出連接后的字符串*/}運(yùn)行結(jié)果:Iamateacher!Youareastudent!
4.字符串拷貝函數(shù)strcpy調(diào)用格式:
strcpy(字符數(shù)組1名,字符數(shù)組2名);其功能是將字符數(shù)組2中的字符串以及其后的那個(gè)?′\0′?一起拷貝到字符數(shù)組1中。需要注意的是,第二個(gè)參數(shù)“字符數(shù)組2名”可以是字符數(shù)組名也可以是雙引號括起來的字符串,此外,字符數(shù)組1要能放得下將要拷貝的字符串。例4.14字符串拷貝函數(shù)的應(yīng)用。
#include<stdio.h>
#include<string.h>
voidmain()
{
chars1[20]=“Thank
you!",s2[]="OK!";
strcpy(s1,s2);
puts(s1);
}運(yùn)行結(jié)果:
OK!
5.字符串比較函數(shù)strcmp調(diào)用格式:
strcmp(字符數(shù)組1名,字符數(shù)組2名);其功能是對字符數(shù)組1中的字符串1和字符數(shù)組2中的字符串2,從左至右逐個(gè)字符的進(jìn)行ASCII碼值比較,直到字符不同或遇到?′\0′?為止。
函數(shù)strcmp的返回值如下:字符串1=字符串2,則返回0值;字符串1>字符串2,則返回正值;字符串1<字符串2,則返回負(fù)值。需要注意的是,strcmp參數(shù)中的“字符數(shù)組1名”和“字符數(shù)組2名”都可以是字符數(shù)組名或雙引號括起來的字符串。例4.15比較兩個(gè)字符串的大小。#include<stdio.h>#include<string.h>voidmain(){ chars1[]="abc",s2[]="acbe"; intx; x=strcmp(s1,s2); if(x==0) printf("s1==s2\n");
else if(x>0) printf("s1>s2\n"); else printf("s1<s2\n");}運(yùn)行結(jié)果:s1<s2注意:strcmp是帶返回值的函數(shù),不像strcat、strcpy、gets和puts作為語句使用那樣,它只能出現(xiàn)在表達(dá)式中。
6.字符串長度測試函數(shù)strlen調(diào)用格式:
strlen(字符數(shù)組名);其功能是測出字符串的實(shí)際長度(不包含字符串結(jié)束標(biāo)志?′\0′?字符),并作為該函數(shù)的返回值。注意,函數(shù)strlen參數(shù)“字符數(shù)組名”可以是字符數(shù)組名,也可以是雙引號括起來的字符串。例4.16測字符串長度。#include<stdio.h>#include<string.h>voidmain(){ chars[]="Iamastudent."; intn; n=strlen(s); printf("Thelengthofthestringis:%d\n",n);}運(yùn)行結(jié)果:Thelengthofthestringis:15
例4.17給一維數(shù)組輸入數(shù)據(jù),然后將數(shù)組元素循環(huán)右移k位,并且只用一個(gè)變量輔助實(shí)現(xiàn)這種移動(dòng)。
[解]由于只允許使用一個(gè)變量輔助實(shí)現(xiàn)數(shù)組元素的移動(dòng),所以將該題轉(zhuǎn)化為每次將數(shù)組元素循環(huán)右移一位并且進(jìn)行k次來實(shí)現(xiàn)。因此,需用兩層for循環(huán):外層的for循環(huán)控制k次移位,內(nèi)層的for循環(huán)控制整個(gè)數(shù)組元素循環(huán)右移一位。數(shù)組元素循環(huán)右移一位的示意如圖4-8所示。圖4-8數(shù)組元素循環(huán)右移一位示意實(shí)現(xiàn)程序如下:#include<stdio.h>voidmain(){ inta[20],i,j,k,n,x; printf("Pleaseinputnumberofelements:"); scanf("%d",&n); printf("Pleaseinputelements:\n");
for(i=0;i<n;i++) scanf("%d",&a[i]);for(i=0;i<n;i++)
printf("%4d",a[i]); printf("\n");
printf("Pleaseinputnumberofmoves:");
scanf("%d",&k); for(i=1;i<=k;i++)
{ x=a[n-1]; for(j=n-2;j>=0;j--)
a[j+1]=a[j]; a[0]=x; }printf("Outputaftermoves:\n"); for(i=0;i<n;i++) printf("%4d",a[i]); printf("\n");}運(yùn)行結(jié)果:Pleaseinputnumberofelements:8↙Pleaseinputelements:12345678↙12345678Pleaseinputnumberofmoves:3↙Outputaftermoves:67812345
例4.18利用數(shù)組求2到1000之間的完數(shù),完數(shù)即其因子之和等于該數(shù)自身的數(shù)。例如:6?=?1?×?2?×?3?=?1?+?2?+?3。
[解]在第3章中我們已經(jīng)求解過完數(shù),但是由于當(dāng)時(shí)沒有用數(shù)組保存一個(gè)數(shù)所找到的每個(gè)因子,而是將找到的因子求和保存;故當(dāng)判斷出這個(gè)數(shù)的所有因子和等于該數(shù)時(shí)(即為完數(shù)),還需再一次求出每一個(gè)因子用于輸出。這里,我們采用數(shù)組來保存判斷某數(shù)是否為完數(shù)過程中所找出的每一個(gè)因子,一旦確定這個(gè)數(shù)為完數(shù)就可直接輸出已保存在數(shù)組中的因子。程序中,我們用變量k來指示數(shù)組f中下一個(gè)存放因子的位置。實(shí)現(xiàn)程序如下:#include<stdio.h>voidmain(){ intf[10],i,j,k,s; for(i=2;i<=1000;i++) { s=0; /*用于保存因子之和*/
k=0; for(j=1;j<i;j++)if(i%j==0) { f[k]=j; /*保存找到的一個(gè)因子*/ s=s+j; /*求因子的累加和*/ k++; }
if(i==s) { printf("%4ditsfactorsare",i); for(j=0;j<k;j++) printf("%4d",f[j]); printf("\n"); } }}運(yùn)行結(jié)果:
6itsfactorsare12328itsfactorsare124714496itsfactorsare1248163162124248例4.19用數(shù)組存儲的方式實(shí)現(xiàn)求解素?cái)?shù)問題。
[解]在此我們采用篩法求素?cái)?shù)的方法。用數(shù)組實(shí)現(xiàn)篩法求素?cái)?shù)的思想是:先設(shè)一整型數(shù)組,并認(rèn)為每一個(gè)數(shù)組元素的下標(biāo)值即代表一個(gè)整數(shù);這樣,這個(gè)數(shù)組的下標(biāo)即可表示某一范圍的全部整數(shù)。初始時(shí)假定該數(shù)組下標(biāo)對應(yīng)的全部整數(shù)都是素?cái)?shù),并置該數(shù)組的每一個(gè)元素值為“1”。篩法求素?cái)?shù)的過程是,先從該數(shù)組中取出第一個(gè)元素,根據(jù)其下標(biāo)值(它代表一個(gè)整數(shù))將這個(gè)下標(biāo)所有倍數(shù)的下標(biāo)所指數(shù)組元素置“0”值(即篩去一個(gè)整數(shù)對應(yīng)的全部倍數(shù)整數(shù));然后,繼續(xù)順序取出數(shù)組中的第二個(gè)元素,同樣根據(jù)其下標(biāo)值找出其所有倍數(shù)下標(biāo)的數(shù)組元素,將其置“0”;這樣反復(fù)進(jìn)行,就好像過“篩子”一樣,每一遍都篩去一些不是素?cái)?shù)的數(shù)組元素(即將其置“0”),也即篩去的是與這些數(shù)組元素下標(biāo)相同的整數(shù)。當(dāng)篩到數(shù)組中的最后一個(gè)元素時(shí),該數(shù)組中元素值為“1”的那些元素就是我們所求的素?cái)?shù),而那些非素?cái)?shù)已經(jīng)在反復(fù)過“篩”中被篩掉(即置為“0”了)。程序設(shè)計(jì)如下:#include<stdio.h>voidmain(){ intb[1000],i,j; for(i=2;i<1000;i++) b[i]=1; for(i=2;i<1000;i++) if(b[i]) for(j=2;i*j<1000;j++)/*b[i]非0時(shí)則i為素?cái)?shù)*/ b[i*j]=0;/*篩去i的所有倍數(shù)*/printf("Outputprime:\n"); j=1; for(i=2;i<1000;i++) { if(b[i]) { printf("%5d",i); if(j%10==0) printf("\n"); j++; } } printf("\n");}運(yùn)行結(jié)果:Outputprime:2357111317192329313741434753596167717379838997101103107109113127131137139149151157163167173179181191193197199211223227229233239241251257263269271277281…………例4.20數(shù)組元素的排序。輸入n個(gè)整數(shù),然后將它們由小到大進(jìn)行排序并輸出排序的結(jié)果。
[解]排序的思想是:對n個(gè)數(shù)a1,a2,…,an,先以an開始由右至左對每兩個(gè)相鄰數(shù)進(jìn)行比較,若為逆序(即aj-1?>?aj)則交換這兩個(gè)數(shù)的位置;這種操作反復(fù)進(jìn)行,直到所有數(shù)都比較、交換過。經(jīng)過這樣一趟排序,最小的數(shù)就被安置在第一個(gè)位置上。然后,對剩余的n?-?1個(gè)數(shù)重復(fù)上述排序過程,則第二趟排序的結(jié)果是將次小數(shù)放置在第二個(gè)位置上?!@樣,在經(jīng)過n?-?1趟排序之后,就得到了已經(jīng)由小到大排好序的n個(gè)數(shù)。由于每趟排序總是使參與比較的數(shù)據(jù)中其值最小者放在前面,這就好像水中的氣泡一樣,較輕的氣泡總是先冒出水面,故此形象地稱這種排序方法為“冒泡排序法”。為了便于觀察每趟排序的過程,在程序中,我們安排了每趟排序后輸出當(dāng)時(shí)n個(gè)數(shù)的排列情況,并且,內(nèi)循環(huán)for語句“for(j=n-1;j>=i;j--)”保證了每趟排序都將參與此趟排序的最小數(shù)移到本趟比較中的最前面位置。程序設(shè)計(jì)如下:#include<stdio.h>voidmain(){ inta[20],i,j,n,temp;
printf("Pleaseinputnumberofelements:"); scanf("%d",&n); printf("Inputelements:\n"); for(i=0;i<n;i++) scanf("%d",&a[i]); for(i=0;i<n;i++)
printf("%4d",a[i]);printf("\n"); for(i=1;i<=n-1;i++)/*進(jìn)行n-1趟排序*/ { for(j=n-1;j>=i;j--) if(a[j-1]>a[j]) { temp=a[j-1]; a[j-1]=a[j]; a[j]=temp; }
printf("-%d-",i); for(j=0;j<n;j++) printf("%4d",a[j]); printf("\n"); }}運(yùn)行結(jié)果:Pleaseinputnumberofelements:9↙Inputelements:1173942651↙11??73942651-1-1117394265-2-1211739456-3-1231174956-4-1234117596-5-1234511769-6-1234561179-7-1234567119-8-1234567911例4.21約瑟夫(Josephus)問題敘述如下:設(shè)有n個(gè)人圍成一圈并按順時(shí)針方向1~n編號;由第s個(gè)人開始進(jìn)行1到m的報(bào)數(shù),數(shù)到m的人出圈;接著再從他的下一個(gè)人重新開始1到m的報(bào)數(shù);直到所有的人出圈為止。請輸出出圈人的出圈次序。
[解]首先,我們把1~n個(gè)人的順序編號存入一維數(shù)組p中,數(shù)組元素的下標(biāo)表示每個(gè)人的當(dāng)前排列位置,因此將出圈者后面參與報(bào)數(shù)的人順序前移一個(gè)元素位置,所空出的第i個(gè)位置p[i]?放置這個(gè)出圈人的編號;再一次報(bào)數(shù)就從出圈人之后的第一人(此人已移至出圈人的位置上)開始報(bào)數(shù),且參與報(bào)數(shù)的人數(shù)也隨之減少一個(gè),即為i?-?1;然后重復(fù)前述報(bào)數(shù)過程。這樣,每次循環(huán)報(bào)數(shù)都將有一人出圈,i值也隨之減小;當(dāng)僅剩最后一人時(shí),出圈次序就全部排定。由于每次循環(huán)報(bào)數(shù)的出圈人是將其編號放入p[i]?中,而這個(gè)i值的變化是由n到2;所以,出圈人的編號按由先到后的出圈次序被順序存放在p[n]、p[n-1]、…、p[2]、p[1]?中。在程序中,用變量s記錄每次報(bào)數(shù)時(shí)開始人的位置;即參與報(bào)數(shù)的i個(gè)人從位置s開始由1報(bào)數(shù)至m時(shí),其對應(yīng)位置上的人即出圈,這個(gè)出圈位置是:(s+m-1)%i;其后,由于出圈人后面參與報(bào)數(shù)人的位置順序前移,則當(dāng)前出圈人的位置就是下一次報(bào)數(shù)時(shí)的開始位置,即語句“s=(s+m-1)%i;”指出了下一次報(bào)數(shù)的開始位置。此外,當(dāng)(s+m-1)%i等于0時(shí),因出圈人的位置不可能為0,這意味著s?+?m?-?1之值與i值相等,即出圈人的位置是i;也就是說,其余參與報(bào)數(shù)人的位置都在出圈人之前;因此這種情況下,其余報(bào)數(shù)人的位置是不移動(dòng)的;這在程序中表現(xiàn)為內(nèi)層for語句中的循環(huán)初值s(s等于i)大于循環(huán)終值i?-?1,故并不執(zhí)行這個(gè)for語句的循環(huán)體。最后,程序以出圈人的出圈先后次序每行輸出10個(gè)人的編號。實(shí)現(xiàn)程序如下:#include<stdio.h>voidmain(){ intp[40],i,j,n,m,s,t; printf("Totalnumber,Startnumber,Repeatnumber(nsm):\n");
scanf("%d%d%d",&n,&s,&m);
for(i=1;i<=n;i++) p[i]=i;
for(i=n;i>=2;i--) { s=(s+m-1)%i; /*出圈位置確定*/ if(s==0) s=i; t=p[s]; /*出圈人編號暫存于t*/ for(j=s;j<=i-1;j++) /*出圈人后面的位置順序前移一位*/ p[j]=p[j+1]; p[i]=t; /*存放出圈人的編號于p[i]中*/ } printf("Sequencecomingoutfromthequeueis:\n");
for(i=n;i>=1;i--) { printf("%4d",p[i]);
if((n-i+1)%10==0) printf("\n"); }}運(yùn)行結(jié)果:Totalnumber,Startnumber,Repeatnumber(nsm):2068↙Sequencecomingoutfromthequeueis:
1319187178201252161519411103146
例4.22找出5?×?5矩陣中每行絕對值最大的元素,并與同行中對角線上的元素交換位置。
[解]矩陣運(yùn)算必須用二維數(shù)組實(shí)現(xiàn),外層for語句確定行,而內(nèi)層for循環(huán)則完成尋找該行絕對值最大的數(shù)組元素(確定列)。我們用變量k來記錄當(dāng)前行中絕對值最大的數(shù)組元素位置,即開始時(shí)假定第0列位置上的數(shù)組元素其絕對值最大,然后依次檢查該行中其余數(shù)組元素的絕對值是否大于由k標(biāo)識的這個(gè)數(shù)組元素的絕對值;如果大于,則k記錄下這個(gè)大于的數(shù)組元素位置;當(dāng)檢查完該行所有數(shù)組元素時(shí),k值即為本行中絕對值最大的數(shù)組元素位置;然后,看這個(gè)k的位置是否為對角線位置,如果不是,則將k指示的數(shù)組元素與本行對角線上的數(shù)組元素對調(diào)。
此外,程序中還用到了求絕對值的函數(shù)abs,因此要在程序開始處包含上“math.h”頭文件。程序編寫如下:#include<stdio.h>#include<math.h>voidmain(){ inta[5][5],i,j,k,t; printf("Inputdataofa[5][5]:\n"); for(i=0;i<5;i++) /*輸入5×5矩陣元素值*/
for(j=0;j<5;j++) scanf("%d",&a[i][j]); for(i=0;i<5;i++) /*對每一行進(jìn)行操作*/ { k=0; for(j=1;j<5;j++) if(abs(a[i][j])>abs(a[i][k])) k=j; /*記錄下新的絕對值最大的元素位置*/ if(k!=i) /*當(dāng)k位置不是對角線位置時(shí)*/ { t=a[i][i]; a[i][i]=a[i][k]; a[i][k]=t; } } printf("Output:\n"); for(i=0;i<5;i++)
{ for(j=0;j<5;j++) printf("%4d",a[i][j]); printf("\n"); }}運(yùn)行結(jié)果:Inputdataofa[5][5]:31-857↙20?311-1210↙-1?525-64↙-1037-32940↙33-413-418↙Output:-8135732011-1210-1525-64-1037?-3240933183-4-41例4.23用字符數(shù)組a保存字符串“Iamateacher!”,用字符數(shù)組b保存字符串“youarestudents!”,要求編程實(shí)現(xiàn)下述功能:
(1)對數(shù)組a和數(shù)組b實(shí)現(xiàn)strcmp功能;
(2)將數(shù)組b中的字符串連接到數(shù)組a中,即實(shí)現(xiàn)strcat功能;
(3)將連接后的數(shù)組a拷貝到數(shù)組c中。
[解]編程實(shí)現(xiàn)如下:#include<stdio.h>voidmain(){ chara[40]="Iamateacher!"; charb[20]="Youareastudent!";
charc[40]; inti=0,j=0,n; while(a[i]==b[i])/*實(shí)現(xiàn)strcmp功能*/
{ if((a[i]==′\0′)||(b[i]==′\0′)) break; i++; } n=a[i]-b[i];
if(n==0) printf("a=b\n");
else if(n>0) printf("a>b\n");
else printf("a<b\n");i=0;j=0;while(a[i]!=′\0′)/*實(shí)現(xiàn)strcat功能*/ i++; while(b[j]!=′\0′) a[i++]=b[j++]; a[i]=′\0′; i=0;
while(c[i]=a[i++]);/*實(shí)現(xiàn)strcpy功能*/ printf("Output:\n"); puts(a); puts(b); puts(c);}運(yùn)行結(jié)果:a<bOutput:Iamateacher!Youareastudent!Youareastudent!Iamateacher!Youareastudent!
對上述程序我們作如下說明:
(1)在實(shí)現(xiàn)strcmp功能中,while語句里的表達(dá)式“a[i]==b[i]”是順序比較數(shù)組a和數(shù)組b各自字符串中對應(yīng)的字符;如果相等,即條件“a[i]==b[i]”滿足,則執(zhí)行“i++;”后繼續(xù)判斷“a[i]==b[i]”,即比較兩字符串的對應(yīng)的下一個(gè)字符,直到出現(xiàn):①a[i]不等于b[i];②?a[i]=′\0′?或者b[i]=′\0′?或者a[i]、b[i]?都是?′\0′。對于①,當(dāng)a[i]-b[i]?>?0時(shí),則數(shù)組a中字符串?>?數(shù)組b中的字符串;反之則結(jié)果相反。對于②,如果僅a[i]=′\0′?,則a[i]-b[i]?<?0(因′\0′?的值為0小于任何其他字符),也即數(shù)組a中字符串?<?數(shù)組b中的字符串;如果僅b[i]=′\0′?,則結(jié)果相反;如果a[i]?與b[i]?都是?′\0′,則a[i]-b[i]=0,即兩數(shù)組中的字符串一樣。綜上所述,兩個(gè)數(shù)組的字符串大小判定都可以在跳出while循環(huán)之后,由a[i]-b[i]得出。
(2)實(shí)現(xiàn)strcat功能時(shí),首先是通過執(zhí)行“while(a[i]!=′\0′)i++;”語句找到數(shù)組a中字符串結(jié)束符?′\0′?的位置,然后再通過“while(b[j]!=′\0′)a[i++]=b[j++];”語句將數(shù)組b中的字符串逐個(gè)字符的拷貝到數(shù)組a中字符串的后面。注意,a[i++]?中的下標(biāo)i開始時(shí)是指向數(shù)組a中字符串結(jié)束符?′\0′?的位置,即由這個(gè)位置開始逐個(gè)字符的拷貝數(shù)組b中字符串的字符;而被拷貝的b[j++]?中的j初值為0,即指向數(shù)組b中字符串的第一個(gè)字符位置;在拷貝過程中,每拷貝完一個(gè)字符,i值和j值就相應(yīng)增1(即i++?和j++),再繼續(xù)下一個(gè)字符的拷貝,直到j(luò)指向數(shù)組b中字符串的結(jié)束符?′\0′?為止,此時(shí)就完成了將數(shù)組b中的字符串全部拷貝到數(shù)組a中字符串之后的工作。
(3)實(shí)現(xiàn)strcpy的功能其實(shí)很簡單,它就是通過執(zhí)行“while(c[i]=a[i++]);”這一條語句來實(shí)現(xiàn)的。由于while語句的循環(huán)體為空,因此拷貝的全部功能就由表達(dá)式“c[i]=a[i++]”來完成。注意,表達(dá)式“c[i]=a[i++]”是一個(gè)賦值表達(dá)式,它兼有賦值和判斷兩種功能。而c和a數(shù)組中的下標(biāo)i則是同一個(gè)i,其初值為0。因此,“while(c[i]=a[i++]);”的功能就是:①先將a[i]?賦給c[i];②判斷此時(shí)的c[i]?是否為?′\0′?(′\0′?的值為0);③執(zhí)行i++?使i值增1;④根據(jù)②的判斷結(jié)果:如果非0則執(zhí)行循環(huán)體語句“?;?”然后轉(zhuǎn)①,否則結(jié)束循環(huán)。
也即,開始時(shí)先將a[0]?賦給c[0]?并判斷此時(shí)的c[0]是否為?′\0′?,如果此時(shí)c[0]?不等于?′\0′?則意味著繼續(xù)執(zhí)行while循環(huán),即先執(zhí)行“i++”使i值為1然后執(zhí)行循環(huán)體語句“;”;由于剛才已判斷c[0]?不等于?′\0′?則繼續(xù)循環(huán),即接著執(zhí)行“c[i]=a[i++]”,先將a[1]?賦給c[1],再判斷c[1]?是否為?′\0′,直到某一時(shí)刻a[i]?的值為?′\0′?(即字符串結(jié)束標(biāo)志),并將這個(gè)a[i]?值賦給了c[i],這時(shí)對c[i]?進(jìn)行判斷則因其值為?′\0′?而結(jié)束循環(huán)。此外,表達(dá)式“c[i++]=a[i]”和表達(dá)式“c[i]=a[i++]”的作用完全一樣,因此表達(dá)式也可以寫成“c[i++]=a[i]”。4.4典型例題精講
例4.17給一維數(shù)組輸入數(shù)據(jù),然后將數(shù)組
溫馨提示
- 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)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 費(fèi)用報(bào)銷制度
- 評優(yōu)評先制度
- 2025 小學(xué)四年級科學(xué)下冊合作學(xué)習(xí)的組織與評價(jià)課件
- 老年人護(hù)理用專業(yè)與愛心守護(hù)長者健康
- 2026北京人保財(cái)險(xiǎn)分公司校園招聘參考考試題庫附答案解析
- 2026年度青島市市南區(qū)所屬事業(yè)單位公開招聘工作人員(25名)參考考試題庫附答案解析
- 2026山東事業(yè)單位統(tǒng)考威海經(jīng)濟(jì)技術(shù)開發(fā)區(qū)鎮(zhèn)街招聘初級綜合類崗位15人參考考試試題附答案解析
- 2026交通運(yùn)輸部所屬事業(yè)單位第四批招聘160人參考考試題庫附答案解析
- 2026山東濟(jì)寧金鄉(xiāng)縣事業(yè)單位招聘初級綜合類崗位人員備考考試題庫附答案解析
- 2026臨沂職業(yè)學(xué)院招聘教師和教輔人員22人參考考試試題附答案解析
- 項(xiàng)目論證制度
- 股東合作協(xié)議模板
- Y -S-T 732-2023 一般工業(yè)用鋁及鋁合金擠壓型材截面圖冊 (正式版)
- GB/T 43829-2024農(nóng)村糞污集中處理設(shè)施建設(shè)與管理規(guī)范
- 萬科物業(yè)服務(wù)指南房屋和設(shè)施維修管理
- 高一英語完型填空10篇實(shí)戰(zhàn)訓(xùn)練及答案
- 施工吊籃工程監(jiān)理實(shí)施細(xì)則
- 10kV架空線路現(xiàn)場驗(yàn)收表
- 抗體偶聯(lián)藥物(ADC)專題分析報(bào)告
- 浙江省生態(tài)環(huán)境專業(yè)工程師職務(wù)任職資格量化評價(jià)表
- 成都市計(jì)劃生育條例
評論
0/150
提交評論