




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
C語言程序設計2第5章數組從前面幾章所介紹的內容可以看到,我們在進行程序設計時僅涉及C語言的根本數據類型。在實際應用過程中僅僅有根本數據類型是遠遠不夠的,為了解決這一矛盾,C語言還提供了多種構造數據類型;數組是C語言提供的一種常用的構造數據類型。數組是把具有相同類型的假設干變量按有序(指位置上有序)的形式組織起來的同類數據元素的集合,它的每一個元素是由數組名和下標來唯一標識的。C語言的數組類型具有兩個特點:一是數組元素的個數必須是確定的,不允許隨機變動,但元素值是可變的;二是數組元素的類型必須相同,不允許是混合類型,即一個數組的元素只能取一種數據類型,可以是整型、浮點型、字符型、指針類型、結構體類型等。數組又可分為一維數組和多維數組,本章介紹數值數組和字符數組定義和使用方法,其余的在以后各章陸續介紹。5.1一維數組根據標識符的定義規那么自行確定數組的名稱;確定數組的大小,即數組中元素的個數;說明數組的基類型,即其元素的類型。在使用一個數組之前,同前面講到的變量一樣必須對它先行定義。一般來說,數組的定義語句出現在函數體的開頭,它的任務是:
5.1.1—維數組的定義
當數組中每個元素只帶有一個下標時,這樣的數組稱為一維數組。在C語言中,定義一維數組的一般形式如下:類型說明符數組名[常量表達式],…;其中,類型說明符是指數組的基類型,也就是每個數組元素的類型。常量表達式是一個其值為正整數的表達式,用來表示該數組含有的元素個數,即定義了數組的大小。例如:longarray[20];它表示數組名為array,該數組有20個long型元素,它們是array[0]、array[1]、array[2]…array[19]。在定義一維數組時要注意以下幾點:①數組名的命名規那么遵守標識符的命名規那么。②常量表達式指出數組的長度,長度為n時,數組元素下標只能從0到n-1,即數組中第一個元素的下標是0,數組中的最后一個元素的下標應該是n-1〔稱為數組下標的上界〕。③常量表達式可以包含常量和符號常量,但不能包含變量。也就是說,不允許對數組的大小作動態的改變。例如:intn=20;inta[n];此種定義形式是錯誤的,因為n是變量而不是常量。④在一個定義數組的語句中,可以有多個數組說明符,它們之間用逗號隔開。例如:floats[10],t[20],w[30];以上語句定義了三個分別名為s、t、w的單精度〔即float〕類型數組,其中數組s包含10個元素,數組下標的上界為9;數組t包含20個元素,數組下標的上界為19;數組w包含30個元素,數組下標的上界為29。5.1.2一維數組元素的引用
數組定義好之后,便可使用它了。但是,數組是一種構造類型,它的使用與簡單類型的使用是不一樣的。C語言中數組名實質上是數組的首地址,是一個常量地址,不能對它進行賦值,因而不能利用數組名來整體引用一個數組,只能單個地使用數組元素。數組元素的描述與引用是由數組名加方括號中的下標組成。①其中下標可以是整型常量、整型變量或整型表達式,要求變量和表達式要有確定的值,并且其起始值最小為0,最大為元素總個數減1。例如:array[3]=array[2]+array[1]+array[2-2]②一個數組元素實質上等同于一個變量,代表內存中的一個存儲單元。它具有和相同類型單個變量一樣的屬性,可以對它進行賦值和參與各種運算。一個數組占有一串連續的存儲單元,而變量即使連續定義,其存儲位置不一定連續。③在C語言中,數組作為一個整體,不能參與運算,只能對單個的元素進行處理。一維數組元素的引用方式為:數組名[下標]說明:注意:在引用時,下標不要超過數組的范圍。例如,array數組的長度為5,那么下標值只能在0~4之間。特別需要強調的是,由于C語言對程序設計的語法限制不太嚴格,所以C編譯不作下標越界檢查,即使引用array[5],,編譯時系統也不會提示錯誤,是把array[4]后面的一個單元中的內容作為array[5]來引用,如圖5.1所示。而array[4]后面的單元并不是我們想要引用的數組元素,如果我們對其進行修改,有可能會造成數組以外的其他變量的值無法使用。所以,必須保證使用的下標值在數組定義的范圍內。12345array[0]array[1]array[2]array[3]array[4]array[5]圖5.1一維數組元素的引用
5.1.3一維數組的初始化
變量在定義的同時可以進行初始化,數組也可在定義的同時對其各元素指定初始值,即初始化。一維數組的初始化有以下幾種方式:①對數組的全部元素賦初值。例如:staticintnum[5]={1,2,3,4,5};用花括號把要賦給各元素的初始值括起來,數據之間用逗號分隔。關鍵字static是“靜態存儲〞的含義,可以省略,但意義不同,對于靜態存儲將在第6章介紹。該語句執行之后有:num[0]=1,num[1]=2,num[2]=3,num[3]=4,num[4]=5。②對數組的局部元素賦初值。例如:intnum[5]={1,2,3};該語句執行之后有:num[0]=1,num[1]=2,num[2]=3,num[3]=0,num[4]=0。③對數組的全部元素賦初值時,可以省略數組長度說明,c編譯系統會根據元素實際個數自行確定。例如:intnum[]={1,2,3,4,5};該語句執行之后num數組的長度自動確定為5,并有:num[0]=1,num[1]=2,num[2]=3,num[3]=4,num[4]=5。假設定義數組長度大于元素個數,那么不能省略數組長度的定義。5.1.4一維數組應用舉例
例5.1建立一個存放10個數據的數組,假設數組元素值為此數組元素下標的10倍,然后將全部元素按正序和逆序分別輸出。本例的程序如下:
#include<stdio.h>voidmain(){inti,a[10];/*定義一個整型變量i和一個具有十個元素的數組a*/for(i=0;i<10;i++)a[i]=i*10;/*通過for循環確定數組元素的值*/for(i=0;i<=9;i++)printf("%5d",a[i]);/*通過for循環輸出數組元素的值*/printf("\n");/*為了輸出時格式清晰,程序控制換一行*/for(i=9;i>=0;i--)printf("%5d",a[i]); /*通過for循環倒序輸出數組元素的值*/printf("\n");/*為了輸出時格式清晰,程序控制換一行*/}運行結果如下:010203040 50 60 70 80 909080706050403020100
例5.2從鍵盤任意輸入10個整數,求它們中的最大值、總和和平均值。本例的程序如下:#include<stdio.h>voidmain(){inti,a[10],sum=0,max;floatave;printf("input10number:\n");for(i=0;i<10;i++)scanf("%d",&a[i]);max=a[0];/*假設第一個元素最大*/for(i=0;i<10;i++){
if(a[i]>max)max=a[i]; /*求最大值*/sum+=a[i]; /*求總和*/}ave=sum/10.0; /*求平均值*/printf("max=%d,sum=%d,ave=%f\n",max,sum,ave);}運行結果如下:input10number:77879468725690648285↙max=94,sum=698,ave=69.800003例5.3用一維數組計算Fibonacci數列的前20項。Fibonaccti數列有如下特點:第1,第2兩個數為1,1。從第3個數開始,該數是其前面兩個數之和。數列定義如下:f(1)=1〔n=1〕f(2)=1〔n=2〕f(n)=f(n-1)+f(n-2)
〔n≥3〕思考一下:在求平均值時,假設寫成ave=sum/10,結果會有怎樣變化?由于數組的下標從0開始,為了符合人們的習慣,只用1~20,這里定義一個有21個元素的數組f[21],而f[0]沒有使用。本例的程序如下:
#include<stdio.h>voidmain(){intf[21],i;f[1]=1;f[2]=1;for(i=3;i<=20;i++)f[i]=f[i-1]+f[i-2];for(i=1;i<=20;i++){ if((i-1)%5==0)printf("\n"); /*5個數據換行*/printf("%10d",f[i]);}}本程序的執行結果如下:1 1 2 3 58 13 21 34 5589 144 233 377 610987 159725844181 6765思考一下,如果想求Fibonaccti數列的前40項,程序該如何修改?例5.4判定用戶輸入的正整數是否為“回文數〞。所謂回文數是指正讀反讀都相同的數。把用戶輸入的數的各位數字別離出來進行比較。本例的程序如下:#include<stdio.h>voidmain(){inta[10],i,k=0,b;longnumber,n;printf("輸入一正整數:");scanf("%ld",&number);n=number;do /*利用循環別離正整數的各位數字*/{a[k++]=n%10;/*把別離出來的數字放在定義好的數組中*/n=n/10;}while(n!=0);b=1; /*設定標志用以判定該數是否為回文數*/for(i=0;i<=(k-1)/2;i++)if(a[i]!=a[k-1-i])b=0;/*標志變量被賦值為0*?if(b)/*假設b不等于0*?printf("%ld\n是回文數",number);else/*假設b等于0*/printf("%ld\n不是回文數",number);}本程序的兩次執行結果如下:輸入一正整數:1234321↙1234321是回文數輸入一正整數:123321↙123321是回文數輸入一正整效:12345621↙12345621不是回文數例5.5輸入任意10個數,對其進行從小到大排序。方法1:用起泡排序法。起泡排序是將相鄰的兩個數進行比較,假設為逆序,那么將兩個數據交換。小的數據就好似水中氣泡逐漸向上漂浮,大的數據好似石塊往下沉。如圖5.2所示。49383838383838383838384949494949494949496464646464646464646496969696757575757575757575759613131313131313131313962727272727272727272796525252525252525252529634343434343434343434962222222222222222222296第1趟第2趟第3趟第4趟第5趟第6趟第7趟第8趟第9趟結果圖5.2起泡排序
假設有10個數,第1次將49和38交換,第2次將49和64交換……共進行9次,得到38、49、64、75、13、27、52、34、22、96的順序。經過這樣的交換,那么最大的數96已經像石塊一樣沉到底,為最下面的一個數,而小數像水中氣泡一樣向上浮起到一個位置。經過第一趟〔共9次〕比較后,得到最大的數96。然后進行第二趟〔共8次〕比較,得到一個次大的數75,依次進行下去,對余下的數按上面的方法進行比較,共需要9趟。如果有n個數,那么要進行n-1趟比較。在第一趟中要進行n-1次比較,在第j趟進行n-j次比較。程序如下:#include<stdio.h>voidmain() {intdata[10]; /*定義一個一維整型數組data*/ inti,j,temp; /*定義循環變量和臨時變量*/ printf("Pleaseinput10numbers:\n"); for(i=0;i<10;i++) scanf("%d",&data[i]);/*冒泡法排序*/for(i=0;i<10-1;i++) /*外循環:控制比較趟數*/for(j=0;j<10-i;j++) /*內循環:進行每趟比較*/if(data[j]>data[j+1]) /*如果data[j]大于data[j+1],交換兩者的位置*/ {temp=data[j]; data[j]=data[j+1]; data[j+1]=temp;};printf("\ntheresultofsort:\n");/*輸出排序后的數據*/ for(i=0;i<10;i++) printf("%d",data[i]); }本程序的執行結果如下:Pleaseinput10numbers:49386496751127523422↙theresultofsort:11222734384952647596方法2:用選擇排序法。選擇排序法是從10個數據中找出最小數與第1個元素值交換,在后9個數據中找出最小數與第2個元素值交換……在后2個數據中找出最小數與第9個元素值交換,即每比較一次,找出一個未排序數中的最小值。共比較9輪,如圖5.3所示。values
[0]
values
[0]values
[0]values
[0]values
[0]values
[0]values
[0]values
[0]values
[0]values
[0]493864967511275234221138649675492752342211226496754927523438112227343849526496751122273438495264967511222734384952647596圖5.3選擇排序程序如下:#include<stdio.h>voidmain(){intvalues[10],i; /*定義一個一維整型數組values*/inttemp,current,j; /*定義循環變量和臨時變量*/printf("Pleaseinput10numbers:\n");for(i=0;i<10;i++) scanf("%d",&values[i]);for(current=0;current<10;current++) /*選擇法排序*/for(j=current+1;j<10;j++)if(values[current]>values[j]){temp=values[current];values[current]=values[j];values[j]=temp;}printf("\ntheresultofsort:\n"); /*輸出排序后的數據*/for(i=0;i<10;i++)printf("%d",values[i]);}本程序的執行結果如下:Pleaseinput10numbers49386496751127523422↙theresultofsort:11222734384952647596需要特別說明的是:以上兩個排序程序并不是最優化的,在掌握上述程序之后,有興趣的讀者可以對上述兩個程序分別進行優化。5.2二維數組和多維數組前面介紹的數組只有一個下標,稱為一維數組,其數組元素也稱為單下標變量。在實際問題中有很多量是二維的或多維的,因此C語言允許構造多維數組。多維數組元素有多個下標,以標識它在數組中的位置,所以也稱為多下標變量。本小節只介紹二維數組,多維數組可由二維數組類推而得到。二維數組類型說明二維數組類型說明的一般形式是:5.2.1二維數組和多維數組的定義類型說明符數組名[常量表達式1][常量表達式2]…;其中常量表達式1表示第一維下標的長度,常量表達式2表示第二維下標的長度。例如:intarray[3][5];說明了一個三行四列的數組,數組名為array,其下標變量的類型為整型。該數組的下標變量共有3×5個,即下面15個元素〔注意括號中的數值的范圍〕:array[0][0],array[0][1],array[0][2],array[0][3],array[0][4]array[1][0],array[1][1],array[1][2],array[1][3],array[1][4]array[2][0],array[2][1],array[2][2],array[2][3],array[2][4]
二維數組在概念上是二維的,即是說其下標在兩個方向上變化,下標變量在數組中的位置也處于一個平面之中,而不是象一維數組只是一個向量。但是,實際的硬件存儲器卻是連續編址的,也就是說存儲器單元是按一維線性排列的。如何在一維存儲器中存放二維數組,可有兩種方式:一種是按行排列,即放完一行之后順次放入第二行。另一種是按列排列,即放完一列之后再順次放入第二列。在C語言中,二維數組是按行排列的。按行順次存放,先存放array[0]行,再存放array[1]行,最后存放array[2]行。每行中有四個元素也是依次存放。由于數組array說明為int類型,該類型占兩個字節的內存空間,所以每個元素均占有兩個字節。
值得說明的是:可以把array看作是一個有3個元素的一維數組,而每個一維數組中的元素又是一個大小為5的一維數組。如圖5.4所示,即定義了一個3×5(3行5列)的二維數組array。array[0]→12345array[1]→678910array[2]→1112131415圖5.4二維數組的含義
定義二維數組時要注意以下幾點:①二維數組中元素的順序是按行存放,即在內存中先順序存放第一行的元素,再存放第二行的元素,依此類推。如圖5.5所示。②從二維數組的排列順序可以計算數組元素在數組中的順序號。假設為n×m的二維數組,其中第i行第j列元素在數組中的位置公式為i×m+j+1。③二維數組可看成是一個特殊的一維數組,它的元素又是一維數組。多維數組的定義與二維數組的定義相似。例如:intarray[2][3][2];定義了一個三維數組array,array是含有2個元素的二維數組,array的每個元素是含有3個元素的一維數組,而array的每個元素中的元素是含有2個整數,那么array中共包括2×3×2=12個整型元素,結構如圖5.6所示。其在內存中的排列如圖5.7所示。
圖5.5二維數組元素存放順序array[0]→array[0][0]array[1][0]array[2][0]array[0][1]array[1][1]array[2][1]array[1]→array[0][0]array[1][0]array[2][0]array[0][1]array[1][1]array[2][1]
圖5.6三維數組的含義array[0][0][0]array[0][0][1]array[0][1][0]array[0][1][1]array[0][2][0]array[0][2][1]array[1][0][0]array[1][0][1]array[1][1][0]array[1][1][1]array[1][2][0]array[1][2][1]圖5.7三維數組元素存放順序可以看到,第三維的下標變換得最快,其次為第二維的下標,最慢的是第一維的下標。注意:對于初學者而言,掌握到二維數組就可以了。5.2.2二維數組和多維數組的引用數組必須先定義,然后才能使用。二維數組元素的引用方式為:數組名[下標][下標]其中:下標可以是整型常量、變量或整型表達式,但每一維的下標值都不能超過定義時的范圍。例如:array[2-1][2]但要區別定義數組array[2][3]和引用array[2][3]的含義,前者表示定義數組的維數和各維的大小,后者array[2][3]中的2和3是下標值,array[2][3]形式上代表某一個元素,但對于給定定義intarray[2][3]而言,引用array[2][3]時是不合法的。多維數組的引用方式和二維數組元素的引用方式相似。例如:array[1][2][0]注意每一維的下標都用方括號括起來,每一維的下標值都不能超過定義時的范圍。5.2.3二維數組和多維數組的初始化
二維數組的初始化有如下幾種方式:(1)對數組的全部元素賦初值,分以下幾種情況①分行給二維數組賦初值,例如:把第一個花括弧內的數據賦給第一行元素,把第二個花括弧內的數據賦給第二行元素……依次按行賦值。該語句執行之后有:array[0][0]=1,array[0][1]=2,array[0][2]=3,array[1][0]=4,array[1][1]=5,array[1][2]=6,②按數組在實際存儲時的排列順序賦初值,例如:intarray[2][3]={1,2,3,4,5,6};該語句執行之后有:array[0][0]=1,array[0][1]=2,array[0][2]=3,array[1][0]=4,array[1][1]=5,array[1][2]=6,③允許省略第一維長度的說明,但第二維的長度不能省。例如:intarray[][3]={1,2,3,4,5,6};array[0][0]=1,array[0][1]=2,array[0][2]=3,array[1][0]=4,array[1][1]=5,array[1][2]=6,③分行給二維數組局部元素賦初值時,也可以省略第一維長度的說明,但第二維的長度不能省。例如:intarray[][3]={{1,2},{4,5}};該語句執行之后,系統會根據內部花括號的個數確定為2行。并且未被賦值的元素自動賦0值,因此有:array[0][0]=1,array[0][1]=2,array[0][2]=0,array[1][0]=4,array[1][1]=5,array[1][2]=0,多維數組的初始化和二維數組的初始化相似。三維數組的初始化有如下幾種方式:①分行給三維數組賦初值,例如:intarray[2][3][2]={{{1,2},{3,4},{5,6}},{{7,8},{9,10},{11,12}}};把array看作是兩個二維數組,每個二維數組是3行2列,按每個二維數組按行賦初值的方法,分別用花括號把各行元素值括起來,再將第三行的初值再用花括號括起來。②按數組在存儲時的排列順序賦初值,例如:intarray[2][3][2]={1,2,3,4,5,6,7,8,9,10,11,12};③允許省略第一維長度,例如:intarray[][3][2]={1,2,3,4,5,6,7,8,9,10,11,12};系統自動算出第一維的大小為2,但第二維和第三維不能省。5.2.4二維數組和多維數組的舉例例5.6輸入一個3×3的矩陣,分別計算并輸出矩陣主對角線和周邊元素的和。本例的程序如下:#include<stdio.h>voidmain(){inta[3][3],sum1=0,sum2=0,i,j; printf("PleaseinputA:\n"); /*輸入矩陣A*/ for(i=0;i<3;i++) for(j=0;j<3;j++)scanf("%d",&a[i][j]); printf("caculatesumofcatercornerandaround:\n"); for(i=0;i<3;i++) for(j=0;j<3;j++) {if(i==j)sum1+=a[i][j];/*計算矩陣A對角線元素之和*/if(i==0||j==0||i==2||j==2)/*計算矩陣A周邊元素之和*/sum2+=a[i][j];} printf("sum1=%5d,sum2=%5d\n",sum1,sum2);運行結果如下:PleaseinputA:123456789↙caculatesumofcatercornerandaround::sum1=15,sum2=40例5.7向三維數組中輸入值并輸出此數組中的元素值。本例的程序如下:#include<stdio.h>voidmain(){ inta[2][3][2],i,j,k;printf("PleaseinputA\n"); /*輸入三維數組A*/ for(i=0;i<2;i++) for(j=0;j<3;j++) for(k=0;k<2;k++) scanf("%d",&a[i][j][k]); printf("PleaseoutputA\n"); /*輸出三維數組A*/for(i=0;i<2;i++) for(j=0;j<3;j++) for(k=0;k<2;k++)printf("a[%d][%d][%d]=%d\n",i,j,k,a[i][j][k]);}運行結果如下:PleaseinputA123456789101112↙PleaseoutputAa[0][0][0]=1a[0][0][1]=2a[0][1][0]=3a[0][1][1]=4a[0][2][0]=5a[0][2][1]=6a[1][0][0]=7a[1][0][1]=8a[1][1][0]=9a[1][1][1]=10a[1][2][0]=11a[1][2][1]=12例5.8求一個4×4矩陣的次對角線元素之積。本例的程序如下:#include<stdio.h>voidmain(){inta[4][4]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16},i,j;ints=0;/*設定累加和變量并設初值為0*/ for(i=0;i<4;i++) for(j=0;j<4;j++)if(i+j==3)s*=a[i][j];printf("s=%d\n",s);}運行結果如下:s=34例5.9編寫一個程序統計某班3門課程的成績,它們是語文、數學和英語。先輸入學生人數,然后按從小到大的編號順序依次輸入學生成績,最后統計每門課程全班的總成績、平均成績以及每個學生課程的總成績和平均成績。依題意,本程序定義一個二維數組score[50][5]。score[i][0]、score[i][1]、score[i][2]分別存儲3門課程的分數,score[i][3]和score[i][4]分別存儲計算出來的個人總分和平均分。total[3]和avg[3]分別存儲全班各科總分和平均分,本例程序如下:#include<stdio.h>voidmain(){intscore[50][5],total[3],avg[3];inti,j,n;printf("學生人數:");scanf("%d",&n); /*輸入小于50的數*/printf("輸入成績\n");for(i=0;i<n;i++){printf("第%5d個學生:",i+1);
scanf("%d%d%d",&score[i][0],&score[i][1],&score[i][2]);}for(i=0;i<n;i++){score[i][3]=0;for(j=0;j<3;j++)score[i][3]+=score[i][j];score[i][4]=score[i][3]/3;}for(j=0;j<3;j++){total[j]=0;for(i=0;i<n;i++)total[j]+=score[i][j];avg[j]=total[j]/n;}printf("\n編號語文數學英語總分平均分\n");for(i=0;i<n;i++){printf("%5d",i+1);for(j=0;j<5;j++)printf("%7d",score[i][j]);printf("\n");}printf("總分:");for(i=0;i<3;i++)printf("%7d",total[i]);printf("\n平均分:");printf("總分:");for(i=0;i<3;i++)printf("%7d",total[i]);printf("\n平均分:");for(i=0;i<3;i++)printf("%7d",avg[i]);}本程序的一次執行結果如下:學生人數:3↙輸入成績1657670↙2827985↙3928295↙編號語文數學英語總分平均分1 65 76 70 211 702 82 79 85 246 823 92 82 95 269 89總分: 239 237 250平均分: 79 79 835.3字符數組和字符串
5.3.1字符數組字符數組是用來存放字符的數組,其定義和引用方式與前面介紹的數組形式相同,只是定義的數據類型為字符型,并且利用字符數組處理字符串時具有一定得特殊性和便利性,字符數組既可以是一維的,也可以是多維的。1.字符數組的定義形式一維字符數組的定義形式:char數組名[常量表達式];例如:charstr[5];二維字符數組的定義形式:char數組名[常量表達式][常量表達式];例如:charstr[5][20];2.字符數組的引用數組必須先定義,然后才能使用。一維字符數組的引用形式:數組名[下標]例如:str[2]=str[2*2];二維字符數組的引用形式:數組名[下標][下標]其中下標可以是整型常量、變量或整型表達式,但每一維的下標值都不能超過定義時的范圍。例如:str[2][1]=str[1*2][0];3.字符數組的初始化一維字符數組的初始化可以逐個地將字符賦給數組中每個元素,例如:charstr[10]={'C',','L','a','n','g','u','a','g','e'};該語句執行之后有:str[0]=‘C’,str[1]=‘’,
str[2]=‘L’,str[3]=‘a’,str[4]=‘n’,str[5]='g',str[6]='u',
str[7]='a',str[8]='g',str[9]='e'如果花括號中提供的初值個數大于數組長度,那么按語法錯誤處理。如果初值個數小于數組長度,那么只將這些字符賦給數組中前面的那些元素,其余的元素自動定為空字符〔即'\0'〕,例如:charstr[11]={'C','','L','a','n','g','u','a','g','e'};數組的狀態如圖5.8所示str[0]str[1]str[2]str[3]str[4]str[5]str[6]str[7]str[8]str[9]CLanguage圖5.8全部元素初始化該語句執行之后有:str[0]='C',str[1]='',str[2]='L',str[3]='a',str[4]='n',str[5]='g',str[6]='u',str[7]='a',str[8]='g',str[9]='e'數組的狀態如圖5.8所示。str[0]str[1]str[2]str[3]str[4]str[5]str[6]str[7]str[8]str[9]CLanguage圖5.8全部元素初始化如果花括號中提供的初值個數大于數組長度,那么按語法錯誤處理。如果初值個數小于數組長度,那么只將這些字符賦給數組中前面的那些元素,其余的元素自動定為空字符〔即'\0'〕,例如:charstr[11]={'C','','L','a','n','g','u','a','g','e'};該語句執行之后有:str[0]='C',str[1]='',str[2]='L',str[3]='a',str[4]='n',str[5]='g',str[6]='u',str[7]='a',str[8]='g',str[9]='e',str[10]='\0',數組的狀態如圖5.9所示。str[0]str[1]str[2]str[3]str[4]str[5]str[6]str[7]str[8]str[9]str[10]CLanguage\0圖5.9局部元素初始化二維字符數組的初始化有以下兩種方式:①逐個字符賦給數組中每個元素,這一點和數值型數組相同,例如:charstr[2][5]={{'b','o','o','k','s'},{'c','o','m','e','s'}};該語句執行之后有:str[0][0]='b',str[0][1]='o',str[0][2]='o',str[0][3]='k',str[0][4]='s',str[1][0]='c',str[1][1]='o',str[1][2]='m',str[1][3]='e',str[1][4]='s',數組的狀態如圖5.10(a)所示。②局部字符賦給數組中每個元素,例如:charstr[2][5]={{'b','o','o','k'},{'c','o','m','e'}};該語句執行之后有:str[0][0]='b',str[0][1]='o',
str[0][2]='o',str[0][3]='k',str[0][4]='\0',str[1][0]='c',str[1][1]='o',
str[1][2]='m',str[1][3]='e',str[1][4]='\0',str[0]→booksstr[1]→comes(a)數組的狀態如圖5.10(b)所示。str[0]→book\0str[1]→come\0(b)圖5.10二維字符數組初始化5.3.2字符串
1.字符串的意義從邏輯意義上說,字符串就是一串字符文字,從物理意義上說,字符串就是用一個字符數組來存儲的一組字符。但不能說字符數組就是字符串,因為數組中的每一個數據元素在邏輯上是獨立的,而字符串在邏輯上是一段相關的文字內容,不是一個個獨立的字符。C語言沒有字符串變量,字符串不是存放在一個變量中而是存放在一個字符數組中。C語言規定以“\0〞作為字符串的結束標志。“\0〞是ASCII代碼值為0的字符。ASCII代碼值為0的字符不是一個普通的可顯示字符,而是一個“空操作〞字符,它不進行任何操作,只是作為一個標記。它占內存空間,但不計入字符串的長度。2.用字符串給字符數組賦初值charstr[8]="Goodbye";charstr[2][5]={"book","come"};說明:①用字符串賦初值可以省略花括號。②如果字符串的字符個數大于數組的長度,系統報錯。③如果字符串的字符個數小于數組的長度,那么最后一個字符后添加“\0〞作為字符串的結束標志。④在用字符串給一維數組賦初值時也可以省略數組長度,對二維數組賦初值時可以省略第一維的長度,但和數值型數組有所不同;例如:charstr[]=〞Goodbye〞,雖然引號內是7個字符,但中括號內隱含的數是8,因為字符串有一個結束標志’\0’也要占據存儲空間;而數值型數組有幾個數中括號內就是熟的總數。3.通過賦初值確定數組長度charstr1[]={'G','o','o','d','b','y','e'};charstr2[]="Goodbye";str1是長度為7的字符數組,如圖5.11(a)所示,str2是長度為8的字符數組(包括結尾的“\0〞),如圖5.11(b)所示。str1[0]Gstr2[0]Gstr1[1]ostr2[1]ostr1[2]ostr2[2]ostr1[3]dstr2[3]dstr1[4]bstr2[4]bstr1[5]ystr2[5]ystr1[6]estr2[6]Estr2[7]\0圖5.11字符數組的長度注意:字符串存放在字符數組中,但字符數組與字符串可以不等長。字符串以“\0〞作為結束標志,字符數組不要求其末尾必須為“\0〞。C語言對下標運算中的下標值不做越界檢查,下標運算中所提供的下標值如果超過定義的空間范圍,在語法上也不算錯,即字符數組中所存儲的字符串的長度如果超出了字符數組的定義空間,編譯時不會有錯,但在運行時,卻可能由于溢出而導致不可預測的后果5.3.3字符串處理函數
為了便于字符串的處理,C語言的庫函數中提供了一些字符串處理函數:1.字符串的輸入輸出函數(1)逐個字符輸入輸出〔利用已講過的函數〕在輸入、輸出字符串時使用格式符“%c〞。例如:charstr[10];scanf("%c",&str[4]);printf("%c",str[4]);向數組元素str[4]中輸入和輸出一個字符,其方法與數值型數組的輸入和輸出一樣。(2)將整個字符串一次輸入輸出使用格式符“%s〞整體輸入輸出〔利用已講過的函數〕在輸入字符串時使用格式符“%s〞,輸入的字符串是以“\0〞結尾,即輸入的字符串中不能包含“\0〞字符,否那么輸入結束。輸入字符串時,字符數組名前不要加“&〞前綴。由于數組名代表數組的起始地址,所以不用加“&〞前綴〔其實&是C語言中計算變量地址的運算符〕。在輸入、輸出字符串時從該起始地址開始逐個輸入、輸出字符,直到遇到字符結束標志‘\0’為止。在輸入、輸出字符串時從該起始地址開始逐個輸入、輸出字符,直到遇到字符結束標志‘\0’為止。在輸出字符串時使用格式符“%s〞,輸出的字符串是以‘\0’結尾,即輸出的字符串中不能包含‘\0’字符串中不能包含‘\0’字符,否那么輸出結束。例如:charstr[10];scanf("%s",str);printf("%s",str);說明:①如果數組長度大于字符串實際長度,也只輸出到“\0〞為止。②如果一個字符數組中包含一個以上“\0〞,那么遇到第一個“\0〞時輸出就結束。例如:charstring[15];scanf("%s",string);輸入數據:CLanguage↙在內存中的狀態如圖5.12(a)所示。那么輸出的結果只有“C〞,沒有“Language〞,因為空格是輸入函數的默認分隔符。③如果輸入多個字符串,那么字符串之間以空格分隔。例如:charstring1[5],string2[10];scanf("%s%s",string1,string2);輸入數據:CLanguage↙在內存中的狀態如圖5.12(b)所示。但是,如果字符串中含有空格,那么可以用字符串的輸入、輸出函數來完成。使用gets和puts函數gets(字符數組)——字符串輸入函數:功能:從終端輸入一個字符串到字符數組,該函數返回值是字符數組的起始地址。例如:功能:從終端輸入一個字符串到字符數組,該函數返回值是字符數組的起始地址。例如:charstring[11];gets(string);輸入:CLanguage↙將字符串“CLanguage〞送給字符數組string,函數返回值是字符數組string的起始地址。在內存中的狀態如圖5.12(c)所示。
(a)(b)C\0Language\0string1→C\0string2→Language\0圖5.12字符串輸入后的內存狀態說明:①gets()讀取的字符串,其長度沒有限制,編程者要保證字符數組有足夠大的空間,用于存放輸入的字符串。C
Language\0說明:
①gets()讀取的字符串,其長度沒有限制,編程者要保證字符數組有足夠大的空間,用于存放輸入的字符串。
②用gets函數可以讀入含有空格字符的字符串,而scanf那么不能。
③在輸入時,將“\n〞轉換成字符串結束標志“\0〞。
puts(字符串)——字符串輸出函數:
功能:將一個字符串輸出到終端。輸出的字符串可以包括轉義字符。例如:
charstring[]="Thisisanexample\noutputstring";
puts(string);
輸出:
Thisisanexample
outputstring
說明:
①在輸出時將字符串結束標志“\0〞轉換成“\n〞,即輸出完字符串后會換行,而printf函數換行時必須用轉義字符“\n〞。
②字符串可以是字符數組〔要求數組內部包含“\0〞〕或字符串常量。
③一次只能輸入/輸出一個字符串。2.strcat(字符數組1,字符數組2)——字符串拼接函數功能:連接兩個字符串,把第二個字符串連接到第一個字符串的后面,結果放在字符數組1中。該函數返回值是字符數組1的起始地址。例如:chardestination[25]="C++";charBorland[8]="Borland";strcat(destination,Borland);printf("%s\n",destination);輸出:C++Borland說明:①字符數組1必須足夠大,否那么出錯。②連接前,兩個字符串均以“\0〞結束;連接后,字符串1的“\0〞被去掉,新字符串最后加“\0〞如下圖。連接前destinationC++\0\0\0\0\0\0……\0\0BorlandBorland\0連接后destination的內容C++Borland\0……3.strcpy(字符數組1,字符串2)——字符串拷貝函數功能:將字符串2拷貝到字符數組1中。該函數返回值是字符數組1的起始地址。例5.10
voidmain(){charstring[10],str1[]="abcdefghi";strcpy(string,str1);printf("%s\n",string輸出:abcdefghi說明:①字符數組1的長度必須足夠長,能夠容納復制過來的字符串。否那么出錯。②字符數組1必須寫成數組名形式〔如string〕,字符串2可以是字符數組名,也可以是一個字符串常量。例如:strcpy(string,"abcdefghi");③復制時,連同結束標志“\0〞一起復制。④不能用賦值運算符“=〞將一個字符串直接賦值給一個字符數組,只能用strcpy()函數來處理。例如:charstr1[20],str2[20];str1={"Hello!"};str2=str1;上面兩種賦值方法均不正確,應改為:strcpy(str1,"Hello!");strcpy(str2,str1);在C語言中,數組的名字代表數組的首地址,是一個地址常量,即代表該數組的第一個元素的地址。然后依次存放該數組的后序元素,所以本程序中的賦值語句str="Hello!"是錯誤的,它表示把一個字符串賦給了一個常量。⑤用strcpy()函數將字符串2中的前面假設干字符復制到字符數組中。例5.11#include“conio.h〞
#include“stdio.h〞voidmain(){charstring[10],str1[]="abcdefghi";strncpy(string,str1,3);string[3]='\0';printf("%s\n",string);getch();{4.strcmp(字符串1,字符串2)——字符串比較函數功能:比較兩個字符串。對兩字符串從左向右逐個字符比較〔按ASCII碼值大小比較〕,直到遇到不同字符或“\0〞為止。如全部字符相同,那么字符串1和字符串2相等;假設出現不相同的字符,那么以第一個不相同的字符比較結果作為整個字符串比較的結果。例如:"computer">"compare","A"<"C"等。比較的結果用函數的返回值表示。假設字符串1=字符串2,那么函數返回0;假設字符串1<字符串2,那么返回-1;假設字符串1>字符串2,那么返回1。例5.12#include“string.h〞voidmain(){charbuf1[]="aaa",buf2[]="bbb",buf3[]="ccc";intptr;ptr=strcmp(buf2,buf1);if(ptr>0)printf("buffer2isgreaterthanbuffer1\n");elseprintf("buffer2islessthanbuffer1\n");ptr=strcmp(buf2,buf3);if(ptr>0)printf("buffer2isgreaterthanbuffer3\n");elseprintf("buffer2islessthanbuffer3\n");}輸出:buffer2isgreaterthanbuffer1buffer2islessthanbuffer3說明:兩個字符數組不能直接比較大小,應使用strcmp()函數。例如:if(str1>str2)printf(“1〞);是不正確的,應改為:if(strcmp(str1,str2)>0)printf("1");5.strlen(字符數組)——測試字符串長度函數功能:統計字符串中字符的個數。返回字符數組中包含的字符串的實際長度,不包括“\0〞在內。例5.13#include“string.h〞voidmain(){chars[]="\t\v\\\0will\n";printf("%d\n",strlen(s));}輸出:36.strlwr(字符串)——字符串小寫函數功能:將字符串中的大寫字母轉換成小寫字母。7.strupr(字符串)——字符串大寫函數功能:將字符串中的小寫字母轉換成大寫字母。以上介紹的幾種常用的字符串處理函數都是C語言所提供的庫函數,不需要用戶再來編寫這些函數,但這些庫函數的說明都包含在頭文件string.h中,如果要在程序中使用這些庫函數,那么需在程序的開頭參加:#include<string.h>初學者需要注意:應牢固掌握以上這些函數的功能和用法,并學會自己動手編寫這些函數。5.3.4字符數組的舉例本例的程序如下:#include<stdio.h>#include<string.h>voidmain(){chars1[20],s2[20],ch1,ch2;intm;printf("String:");gets(s1);printf("Old,Newcharis:");scanf("%c,%c",&ch1,&ch2);for(m=0;(s1[m]!='\0');m++)if(s1[m]==ch1)s2[m]=ch2;elses2[m]=s1[m];s2[m]='\0';printf("EndString:%s\n",s2);}本程序的執行結果如下:String:even↙Old,Newcharis:n,r↙EndString:ever例5.15判定一個字符串是否是另一個字符串的子串的程序。本例的程序如下:#include<stdio.h>#include<string.h>voidmain(){intm,n,k,index=0;chars1[20],s2[20];printf("String:");gets(s1);printf("SubString:");gets(s2);for(m=0;s1[m]!='\0';m++){for(n=m,k=0;s1[n]==s2[k];n++,k++)if(s2[k+1]=='\0'){index=m+1;break;}if(index!=0)break;}printf("index=%d\n",index);}本程序的執行結果如下:第一次運行:String:youareastudent.↙SubString:are↙index=5第二次運行:String:youareastudent.↙SubString:std↙index=0匹配過程如圖5.13所示。第1次youareastudent.\0are\0第2次youareastudent.\0are\0……
第5次youareastudent.\0are\0圖5.13字符串匹配過程
例5.16密碼檢測。本例的程序如下:#include<stdio.h>#include<string.h>#include<conio.h>voidmain(){charpass_str[80]; /*定義字符數組passstr*/inti=0,flag=1; /*檢驗密碼*/ while(flag) { printf("請輸入密碼\n"); gets(pass_str); /*輸入密碼*/ if(strcmp(pass_str,"password")!=0) /*輸入的字符串不等于"password"*/ {printf("口令錯誤,按任意鍵繼續\n"); getch();} /*輸入任意字母*/else flag=0; /*輸入正確的密碼,中止循環*/ i++; if(i==3){printf("您是非法用戶,強行退出!");exit(0);} /*連續輸入三次錯誤密碼,退出程序*/ } printf("口令正確,按任意鍵繼續");getch();/*其他語句……*/ /*輸入正確密碼所進入的程序段*/}本程序的執行結果如下:請輸入密碼pass↙口令錯誤,按任意鍵繼續password↙口令正確,按任意鍵確認printf("%-15s%-15s%-15s\n",num[m],name[m],tel[m]);}例5.17創立一個通訊錄。
本例的程序如下:#include<stdio.h>#include<string.h>voidmain(){intm;charnum[3][10],name[3][10],tel[3][10];for(m=0;m<3;m++){printf("\n請輸入第%d個記錄:\n",m+1);printf("學號:");gets(num[m]);printf("姓名:");gets(name[m]);printf(":");gets(tel[m]);}printf("學號 姓名 \n");for(m=0;m<3;m++)請輸入第1個記錄:學號:123↙姓名:zhangsan↙:123123123↙請輸入第2個記錄:學號:456↙姓名:lisi↙:456456456↙請輸入第3個記錄:學號:789↙姓名:wangwu↙:789789789↙學號 姓名 123 zhangsan123123123456 lisi456456456789 wangwu 789789789
本章小結
本章我們分別詳細介紹了一維數組、二維數組、字符數組的定義和引用方法。還簡要介紹了字符串的意義和字符串處理函數。數組是相同類型元素的集合,數組中的每一個元素均由數組名和下標來惟一標識的。把已定義的數組類型作為基類型,再構造出數組的數組,即為多維數組。多維數組中元素的存儲順序是:按行存放。對數組的賦值可以用數組初始化賦值,輸入函數動態賦值和賦值語句賦值三種方法實現。對數值數組不能用賦值語句整體賦值、輸入或輸出,而必須用循環語句逐個對數組元素進行操作,但字符數組例外。在定義數組的同時對數組的全部元素賦初值時,也可不指定數組長度,系統默認的長度就是初值個數,用字符串初始化字符數組時默認的長度是字符個數+1。C語言規定以“\0〞作為字符串的結束標志。C語言沒有字符串變量,字符串不是存放在一個變量中而是存放在一個字符數組中。字符串通常是作為整體被輸入和輸出。其他類型的數組那么不能作為整體進行輸入和輸出。字符串存放在字符數組中,但字符數組與字符串可以不等長。字符串以“\0〞作為結束標志,字符數組不要求其末尾必須為“\0〞。字符串的長度是指字符串的實際有效字符的個數。C語言提供了很多處理字符串的庫函數,用戶可以直接調用。習題5
以下程序的輸出結果是。#include“stdio.h〞voidmain(){inta[5]={0},i;for(i=0;i<5;i++)a[i]=i*i;printf(“a[%d]=%d〞,i,a[i]);}以下程序的輸出結果是。#include“stdio.h〞voidmain(){inti,a[3][3]={1,2,3,4,5,6,7,8,9};for(i=0;i<3;i++)printf(“%d,〞,a[i][2-i]);}3、以下程序的輸出結果是。#include“stdio.h〞voidmain(){inti,k=0,arr[10];for(i=0;i<10;i++)arr[i]=i;for(i=0;i<6;i++)k+=arr[i]+i;printf(“%d\n〞,k);}4、以下程序的輸出結果是。#include“stdio.h〞voidmain(){inti,j,k=1,a[3][3]={1,2,3,4,5,6,7,8,9};for(i=0;i<3;i++)for(j=0;j<3;j++)if(a[i][j]%2==0)k*=a[i][j];printf(“%d\n〞,k);}5、以下程序的輸出結果是。#include“stdio.h〞voidmain(){inti,j,k=1,a[3][3]={1,2,3,4,5,6,7,8,9};for(i=0;i<3;i++)for(j=0;j<3;j++)if(a[i][j]%2)k*=a[i][j];printf(“%d\n〞,k);}6、編程實現:輸入一行數字字符,用數組元素作為計數器來統計輸入的數字字符串中每個數字的個數,即‘0’的個數放在下標為0的元素里,‘1’的個數放在下標為1的元素里,……7、設有一個5×5的方陣,利用輸入函數動態賦初值后分別計算方陣每行、每列及兩對角線上的元素之和。8、設有一個二維數組array[][4]={89,56,85,78,69,82,43,-65,84,1,55,23},編程找出數組中最大值、最小值元素及其下標。第6章函數
一個C語言的程序是由一個或多個C語言程序文件組成,一個C語言的程序文件是由一個或多個函數組成的,每個函數負責完成一個特定的操作或功能。一個C語言程序,必須有而且只能有一個名為main的函數,這是整個程序的入口,也就是整個程序的執行起點。利用函數,可以將一些功能上相對獨立、可能被重復執行的程序段包裝起來,使程序的結構更加模塊化。第6章函數在C語言程序設計中,無論多么復雜,規模多么大的程序,最終都落實到一個個簡單函數的編寫工作上,因此,C語言程序設計的根底工作就是函數的設計和編制。本章討論的是C語言函數的特點、自定義函數的定義和調用、函數之間傳遞數據的方法以及遞歸的概念,本章的最后還將介紹C語言常用的標準庫函數。C語言中的函數分為兩類,一類是系統提供的標準函數,又稱庫函數。標準函數由系統定義,在程序中可以直接使用。另一類是用戶自己定義的函數。第6章函數6.1函數的概念6.2函數的定義和說明6.3函數調用6.4函數傳遞機制6.5遞歸6.6變量的作用域及存儲類別6.7庫函數6.1函數的概念
函數是一個被命名的程序段,通過調用該函數可以屢次執行這個程序段。一個完整的程序是為了完成某個特定的任務而設計的一組指令〔語句〕。隨著程序規模的增大,將語句簡單地羅列起來,會使程序的復雜程度過高而難于閱讀和維護。如果將一些功能上相對獨立、可能被反復執行的程序段單獨提煉出來,用一個名稱來代表這段子程序,不僅可以減少總的程序量,而且可以使整個程序的結構更具模塊化,更易于閱讀和維護。在C語言中就是用函數來描述這樣的一段子程序。返回目錄頁例6.1voidmain(){increment(); /*調用函數increment*/increment(); /*調用函數increment*/increment(); /*調用函數increment*/}voidincrement(){intx=0;x+=1;printf("%d\n",x);}程序的運行結果是:111increment是用戶定義的函數名,在程序中要反復調用
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 考慮能效的自動駕駛路徑規劃與能量管理策略論文
- 中國醫藥銷售外包(CSO)行業市場前景預測及投資價值評估分析報告
- 節日前隊伍管理制度
- 苯加氫安全管理制度
- 茶藝師工作管理制度
- 課程推廣文案范文(26篇)
- 行業處理計劃微信銷售履行技能策劃計劃勝利案例
- 流川楓灌籃作文法-具體細節描寫法
- 環保小課題研究案例
- 自動化專業求職簡歷(15篇)
- 校長在2025暑假前期末教師大會上的講話:靜水深流腳踏實地
- (2025)全國“安全生產月活動”《安全知識》競賽試題庫(附含答案)
- 交房期間業主維權突發事件應急預案
- 貸款后管理與客戶滿意度提升
- 自動生成的文檔-202504081202-99
- 費用類報銷管理制度
- 杭州市上城區2025年下半年下半年招考50名專職社區工作者易考易錯模擬試題(共500題)試卷后附參考答案
- 2025年中國SUV帳篷行業市場前景預測及投資價值評估分析報告
- 福建省惠安縣2025屆七下數學期末學業質量監測試題含解析
- 2025年就業指導培訓課件
- 2025-2030石油管道行業市場深度調研及競爭格局與投資研究報告
評論
0/150
提交評論