字元陣列
用來存放字元量的陣列稱為字元陣列。
形式與前面介紹的數值陣列相同。
例如:
char c[10];
由於字元型和整型通用,也可以定義為int c[10]但這時每個陣列元素占2個位元組的記憶體單元。
字元陣列也可以是二維或多維陣列。
例如:
char c[5][10];
即為二維字元陣列。
字元陣列也允許在定義時作初始化賦值。
例如:
char c[10]={‘c’, ‘ ’, ‘p’, ‘r’, ‘o’, ‘g’, ‘r’, ‘a’,’m’};
賦值後各元素的值為:
陣列C c[0]的值為‘c’
c[1]的值為‘ ’
c[2]的值為‘p’
c[3]的值為‘r’
c[4]的值為‘0’
c[5]的值為‘g’
c[6]的值為‘r’
c[7]的值為‘a’
c[8]的值為‘m’
其中c[9]未賦值,由的值為‘p’系統自動賦予0值。
當對全體元素賦初值時也可以省去長度說明。
例如:
char c[]={`c`,` `,`p`,`r`,`o`,`g`,`r`,`a`,`m`};
這時C陣列的長度自動定為9。
【例1】
#include<stdio.h> main() { int i,j; char a[][5]={{'B','A','S','I','C',},{'d','B','A','S','E'}}; for(i=0;i<=1;i++) { for(j=0;j<=4;j++) printf("%c",a[i][j]); printf("\n"); } } |
本例的二維字元陣列由於在初始化時全部元素都賦以初值,因此一維下標的長度可以不加以說明。
在C語言中沒有專門的字串變數,通常用一個字元陣列來存放一個字串。前面介紹字串常量時,已說明字串總是以'\0'作為串的結束符。因此當把一個字串存入一個陣列時,也把結束符'\0'存入陣列,並以此作為該字串是否結束的標誌。有了'\0'標誌後,就不必再用字元陣列的長度來判斷字串的長度了。
C語言允許用字串的方式對陣列作初始化賦值。
例如:
char c[]={'c', ' ','p','r','o','g','r','a','m'};
可寫為:
char c[]={"C program"};
或去掉{}寫為:
char c[]="C program";
用字串方式賦值比用字元逐個賦值要多占一個位元組, 用於存放字串結束標誌'\0'。上面的陣列c在記憶體中的實際存放情況為:
C |
' ' |
p |
r |
o |
g |
r |
a |
m |
\0 |
‘\0'是由C編譯系統自動加上的。由於採用了‘\0'標誌,所以在用字串賦初值時一般無須指定陣列的長度, 而由系統自行處理。
在採用字串方式後,字元陣列的輸入輸出將變得簡單方便。
除了上述用字串賦初值的辦法外,還可用printf函數和scanf函數一次性輸出輸入一個字元陣列中的字串,而不必使用迴圈語句逐個地輸入輸出每個字元。
【例 2】
#include<stdio.h> main() { char c[]="BASIC\ndBASE"; printf("%s\n",c); } |
注意在本例的printf函數中,使用的格式字串為“%s”,表示輸出的是一個字串。而在輸出表列中給出陣列名稱則可。不能寫為:printf("%s",c[]);
【例 3】
#include<stdio.h> main() { char st[15]; printf("input string:\n"); scanf("%s",st); printf("%s\n",st); } |
本例中由於定義陣列長度為15,因此輸入的字串長度必須小於15,以留出一個位元組用於存放字串結束標誌`\0`。應該說明的是,對一個字元陣列,如果不作初始化賦值,則必須說明陣列長度。還應該特別注意的是,當用scanf函數輸入字串時,字串中不能含有空格,否則將以空格作為串的結束符。
例如當輸入的字串中含有空格時,運行情況為:
input string:
this is a book
輸出為:
this
從輸出結果可以看出空格以後的字元都未能輸出。為了避免這種情況,可多設幾個字元陣列分段存放含空格的串。
程式可改寫如下:
【例 4】
#include<stdio.h> main() { char st1[6],st2[6],st3[6],st4[6]; printf("input string:\n"); scanf("%s%s%s%s",st1,st2,st3,st4); printf("%s %s %s %s\n",st1,st2,st3,st4); } |
本程式分別設了四個陣列, 輸入的一行字元的空格分段分別裝入四個陣列。然後分別輸出這四個陣列中的字串。
在前面介紹過,scanf的各輸入項必須以位址方式出現,如 &a,&b等。但在前例中卻是以陣列名稱方式出現的,這是為什麼呢?
這是由於在C語言中規定,陣列名稱就代表了該陣列的首位址。整個陣列是以首位址開頭的一塊連續的記憶體單元。
如有字元陣列char c[10],在記憶體可表示如圖。
C[0] |
C[1] |
C[2] |
C[3] |
C[4] |
C[5] |
C[6] |
C[7] |
C[8] |
C[9] |
位址 2000 2001 ..... ....... 2010
設陣列c的首位址為2000,也就是說c[0]單元位址為2000。則陣列名稱c就代表這個首地址。因此在c前面不能再加位址運算符&。如寫作scanf("%s",&c);則是錯誤的。 在執行函數printf("%s",c) 時,按陣列名稱c找到首位址,然後逐個輸出陣列中各個字元直到遇到字串終止標誌'\0'為止。
C語言提供了豐富的字串處理函數, 大致可分為字串的輸入、輸出、合併、修改、比較、轉換、複製、搜索幾類。 使用這些函數可大大減輕程式的負擔。用於輸入輸出的字串函數,在使用前應包含頭檔<stdio.h>,使用其他字串函數則應包含頭檔<string.h>。
下面介紹幾個最常用的字串函數。
1. 字串輸出函數 puts
格式: puts (字元陣列名稱)
功能:把字元陣列中的字串輸出到顯示器。 即在螢幕上顯示該字串。
【例 5】
#include<stdio.h> main() { char c[]="BASIC\ndBASE"; puts(c); } |
從程式中可以看出puts函數中可以使用轉義字元,因此輸出結果成為兩行。puts函數完全可以由printf函數取代。當需要按一定格式輸出時,通常使用printf函數。
2. 字串輸入函數gets
格式: gets (字元陣列名稱)
功能:從標準輸入設備鍵盤上輸入一個字串。
本函數得到一個函數值,即為該字元陣列的首位址。
【例 5】
#include<stdio.h> main() { char st[15]; printf("input string:\n"); gets(st); puts(st); } |
可以看出當輸入的字串中含有空格時,輸出仍為全部字串。說明gets函數並不以空格作為字串輸入結束的標誌,而只以回車作為輸入結束。這是與scanf函數不同的。
3. 字元串連接函數strcat
格式: strcat (字元陣列名稱1,字元陣列名稱2)
功能:把字元陣列2中的字串連接到字元陣列1 中字串的後面,並刪去字串1後的串標誌“\0”。本函數返回值是字元陣列1的首位址。
【例 6】
#include<stdio.h> #include<string.h> main() { static char st1[30]="My name is "; int st2[10]; printf("input your name:\n"); gets(st2); strcat(st1,st2); puts(st1); } |
本程式把初始化賦值的字元陣列與動態賦值的字元串連接起來。要注意的是,字元陣列1應定義足夠的長度,否則不能全部裝入被連接的字串。
4.字串拷貝函數strcpy
格式: strcpy (字元陣列名稱1,字元陣列名稱2)
功能:把字元陣列2中的字串拷貝到字元陣列1中。串結束標誌“\0”也一同拷貝。字元數名2,也可以是一個字串常量。這時相當於把一個字串賦予一個字元陣列。
【例7.15】
#include<stdio.h> #include<string.h> main() { char st1[15],st2[]="C Language"; strcpy(st1,st2); puts(st1);printf("\n"); } |
本函數要求字元陣列1應有足夠的長度,否則不能全部裝入所拷貝的字串。
5. 字串比較函數strcmp
格式: strcmp(字元陣列名稱1,字元陣列名稱2)
功能:按照ASCII碼順序比較兩個陣列中的字串,並由函數返回值返回比較結果。
字串1=字串2,返回值=0;
字串2〉字串2,返回值〉0;
字串1〈字串2,返回值〈0。
本函數也可用於比較兩個字串常量,或比較陣列和字串常量。
【例 7】
#include<stdio.h> #include<string.h> main() { int k; static char st1[15],st2[]="C Language"; printf("input a string:\n"); gets(st1); k=strcmp(st1,st2); if(k==0) printf("st1=st2\n"); if(k>0) printf("st1>st2\n"); if(k<0) printf("st1<st2\n"); } |
本程式中把輸入的字串和陣列st2中的串比較,比較結果返回到k中,根據k值再輸出結果提示串。當輸入為dbase時,由ASCII 碼可知“dBASE”大於“C Language”故k〉0,輸出結果“st1>st2”。
6. 測字串長度函數strlen
格式: strlen(字元陣列名稱)
功能:測字串的實際長度(不含字串結束標誌‘\0’) 並作為函數返回值。
【例 8】
#include<stdio.h> #include<string.h> main() { int k; static char st[]="C language"; k=strlen(st); printf("The lenth of the string is %d\n",k); } |
【例 9】輸入五個國家的名稱按字母順序排列輸出。
本題程式思路如下:五個國家名應由一個二維字元陣列來處理。然而C語言規定可以把一個二維陣列當成多個一維陣列處理。 因此本題又可以按五個一維陣列處理, 而每一個一維陣列就是一個國家名字串。用字串比較函數比較各一維陣列的大小,並排序,輸出結果即可。
程式如下:
#include<stdio.h> #include<string.h> main() { char st[20],cs[5][20]; int i,j,p; printf("input country's name:\n"); for(i=0;i<5;i++) gets(cs[i]); printf("\n"); for(i=0;i<5;i++) { p=i;strcpy(st,cs[i]); for(j=i+1;j<5;j++) if(strcmp(cs[j],st)<0) {p=j;strcpy(st,cs[j]);} if(p!=i) { strcpy(st,cs[i]); strcpy(cs[i],cs[p]); strcpy(cs[p],st); } puts(cs[i]);}printf("\n"); } |
本程式的第一個for語句中,用gets函數輸入五個國家名字串。上面說過C語言允許把一個二維陣列按多個一維陣列處理,本程式說明cs[5][20]為二維字元陣列,可分為五個一維陣列cs[0],cs[1],cs[2],cs[3],cs[4]。因此在gets函數中使用cs[i]是合法的。 在第二個for語句中又嵌套了一個for語句組成雙重迴圈。這個雙重迴圈完成按字母順序排序的工作。在外層迴圈中把字元陣列cs[i]中的國名字串拷貝到陣列st中,並把下標i賦予P。進入內層迴圈後,把st與cs[i]以後的各字串作比較,若有比st小者則把該字串拷貝到st中,並把其下標賦予p。內迴圈完成後如p不等於i說明有比cs[i]更小的字串出現,因此交換cs[i]和st的內容。至此已確定了陣列cs的第i號元素的排序值。然後輸出該字串。在外迴圈全部完成之後即完成全部排序和輸出。