7.4 字串及應用

7。4 字串及應用

上一節介紹了二維陣列的定義、初賦值、記憶體映象及陣列元素的使用。本節主要講字串、字串的的儲存和使用。

文字處理是計算機應用的重要工作。近年來,計算機更多地被用來文字處理而非數值處理,如文字的輸入、編輯、排版、查詢、替換和輸出等。為了能進行簡單文字處理,C語言可以透過定義字元型資料來完成一些的工作。如:

char ch;ch=getchar( );putchar(ch);

以上程式碼定義了一個字型變數,並且可以透過getchar函式輸入一個字元存放到字元變數ch中,再透過putchar(ch)把字元輸出來。字元常量用單引號定界,可以是普通字元,如‘A’、‘#’、‘9’等,也可以是跳脫字元,如‘\n’、‘\t’、‘\x41’、‘\101等。如果兩個單引號之間什麼也沒有,如’‘,則稱為空字元,這與空白’ ‘字元不同,空白字元中有一個稱為空格的符號。

很多時候,我們要處理更多的字元,因此我們可以把這些字元按順序排列,並用一對雙引號(“”)定界,稱為

字串常量

。回顧一下,我們在學習scanf與printf函式時,函式的第一個引數——

格式控制字串

就是字串。如:

“Hello,world!\n”“a=%d,b=%d\n”

如果要讓螢幕上顯示的Hello,world兩端帶有雙引號(“),則字串要寫成這樣的形式:

”\“Hello,world!\”\n“

此時字串用轉義符號

'\"'

表示雙引號,目的是要與用來定界的雙引號區別開。

字串常量可以用printf輸出,此時要用%s格式符表示。如;

printf(”Hello,%s“,”world!\n“);

printf函式執行時,會把字串”world!\n“去代替格式控制字串中的%s,因此螢幕上顯示:

Hello,world!

字串常量被儲存在連續的儲存空間中,最後用一個特殊的字元

'\0'

表示字串的結束,如“Hello,world!”在記憶體中是這樣儲存的:

地址

內空空間

編號

xxx0D

12

xxx0C

'\0'

11

xxx0B

’d‘

10

xxx0A

’l‘

9

xxx09

’r‘

8

xxx08

’o‘

7

xxx07

’w‘

6

xxx06

’,‘

5

xxx05

’o‘

4

xxx04

’l‘

3

xxx03

’l‘

2

xxx02

’e‘

1

xxx01

’H‘

0

字串常量”Hello,world!“佔用的儲存空間中的內容是不可被改變的。我們看到的是一串符號,但在計算機中

字串常量是其第一個字元的首地址

,如上圖,”Hello,world!“的值是一個地址數值xxx01,即字元’H‘的首地址。我們可以透過以下輸出來驗證字串是一個地址的事實:

printf(”%d“,”Hello,world!\n“);

注意這裡用的格式符是

%d

,而不是

%s

。因此語句執行後顯示的結果是一個整數,而不是字串本身。

很遺憾C語言沒有提供字串變數,這使操作字串時稍稍麻煩些。由於字串佔用連續儲存空間,所以可以透過定義

字元陣列

來儲存字串。如:

char str[80];

字元陣列str可以存放79個字元的字串,因為要留一個字元來儲存字串結束標誌’\0‘。字串在定義的同時是可以被賦初值的,有以下幾種賦初值的辦法:

char str[80]={’H‘,’e‘,’l‘,’l‘,’o‘,’!‘,’\0‘};char str[80]=”Hello!“;char str[80]={”Hello!“};

三種賦初值的結果都一樣,但是第一種很顯然要麻煩得多,因為一個字元一個字元賦值,並且在最後不能忘記字串結束標

'\0'

。而後兩種賦初值,會依次把每個字元複製到字元陣列str的每個元素中,含最後的字串結束符號

'\0'

字串的輸出可以用printf或puts函式實現。用printf函式時,要在格式控制字串中用格式符%s指定,用puts不需要指它格式符,如:

printf(”%s“,str);puts(str);

我們前面講過,陣列名字是地址常量,因此str是一個地址。那麼怎麼輸出字串呢?執行以上語句時,printf函式從str地址對應的字元開始逐個字元輸出,直到碰到字串結束標誌’\0‘為止。我們可以用前面學習的陣列元素的輸出方法(逐個元素)來輸出字串,即:

for(i=0;str[i]!=’\0‘;i++) putchar(str[i]);

與一維陣列輸出不同是

迴圈控制條件

。前面用i小於陣列長度來表示。字串的長度可以用strlen函式來確定,但如果先求字串長度再輸出顯示多消耗了一些時間。因為知道字串以’\0‘結束。因此,迴圈條件可設為為str[i]!=’\0‘,即當第i個字元為’\0‘時,表示字串結束,退出迴圈。

知道了字串的輸出方法後,我們來看一如何輸入字串儲存到陣列中。我們可以用getchar函式一個字元一個字元地輸入,輸入一個就儲存到陣列對應的元素中,此時需要一個計數器記錄當前輸入的字元個數,只要不碰到回車我們繼續輸入。給字元陣列輸入字串的程式碼段為:

cnt=0; //計數器為零,表示初始沒有字元while( (ch=getchar( ))!=’\0‘){ str[cnt]=ch; cnt++;}str[cnt]=’\0‘;

以上程式碼能完成了字串的輸入並儲存到字元陣列str中,但是這裡假定了str陣列是無限長的,在實際應用時,還要限定輸入字串的長度,如cnt

cnt=0;while( (ch=getchar( ))!=’\n‘ && cnt

當然我們可以用scanf函式來實現字串的輸入,此時格式控制字串中要使用%s格式符,如:

scanf(”%d“,str);

由於陣列名str本身是一個地址常量,所以不能在str的前面用取地址運算子&。但是scanf只能實現沒有空格的字串輸入,如果輸入的字串含有空格,只取空格前的字串放到陣列中。

也可以用使用gets函式來實現字串的輸入,與scanf相比,可以輸入帶有空格的字串,輸入方式為:

gets(str);

上面,我們已經學習字串的概念、儲存與字串的輸入與輸出,以下通過幾個例項深入掌握字串的應用。

例1

:輸入一個以回車符為結束標誌的字串(少於80個字元),判斷該字串是否為迴文。迴文指的是字串中心對稱或正向讀與反向讀都是一樣的,如“abcba” “abccba”是迴文,“abcdba”不是迴文。

字串的輸入與輸出,我們可以直接使用前面的方法實現,所以本例的關鍵是判斷字串str是否迴文。為此,可設兩個變數i、j,i儲存字串前面的字元的下標,j儲存字串後面字元的下標,初始時i為0,j為字串最後一個字元下標(字串長度-1)。比較str[i]與str[j],如果兩個字元相等,則分別讓i加1、j減1。如果不等或者i比j大,則程式結束。

7.4 字串及應用

初始狀態

7.4 字串及應用

比較完第一次後i,j下標的位置

完整的程式如下:

#include int main( ){char str[80],ch;int cnt=0,i,j;while( cnt<80 && ( ch=getchar( ))!=’\0‘) str[cnt++]=ch;str[cnt]=’\0‘;i=0;j=cnt-1;while(i= j) printf(”It is a plalindrome\n“);else printf(”It is not a plalindrome\n“);return 0;}

程式使用i>=j判斷是否迴文,原因是如果不是迴文,一定是因為條件str[i]!=str[j]退出的,此時i小於j。只有從條件i>=j退出,此時說明是迴文。

例2:

輸入一個以回車符為結束標誌的字串(少於80個字元),統計其中數字字元’0‘……’9‘的個數。

本例我們用gets輸入字串str,然後依次檢驗每個字元str[i]是否是數字,如果是則讓記數器cnt加1。檢驗字元str[i]的程式碼為:

if(str[i]>=’0‘ && str[i]<=’9‘) cnt++;

由於’\0‘之前的每個字元都要被檢驗到,因此可以使用for迴圈或while迴圈實現,用for迴圈如下:

for(i=0;str[i]!=’\0‘;i++) //str[i]!=’\0‘可簡寫為str[i] if(str[i]>=’0‘ && str[i]<=’9‘) cnt++;

完整的程式如下:

#includeint main( ){char str[80];int cnt=0;gets(str);for(i=0;str[i]!=’\0‘;i++) //str[i]!=’\0‘可簡寫為str[i] if(str[i]>=’0‘ && str[i]<=’9‘) cnt++;printf(”count=%d\n“,cnt);return 0;}

例3:

輸入一個以回車符為結束標誌的字串(少於20個字元),提取其中所有的數字字元( ’0‘……’9‘ ),將其轉換為一個十進位制整數輸出。

分析:

如有字串“abc1xyz2uvw3#yuv”,提取的數字字元應該是’1‘、’2‘、’3‘,因此構成的十進位制整數是123。如何才能把’1‘、’2‘、’3‘變成十進位制整數呢?

假設該十進位制數為x,則x的初值為0。然後碰到’1‘後,要把1放在x的之後(0

1

),可讓x乘以10再加上’1‘對應的數1,即:x=x*10+’1‘-’0‘=1;當碰到’2‘時,要把2放在x之後(1

2

),可讓x乘以10再加上’2‘對應的數2,即:x=x*10+’2‘-’0‘=10+2=12。最後,要把’3‘放在x之後(12

3

),即讓x=x*10+’3‘-’0‘=12*10+3=123。因此當str[i]是數字時要作如下處理:

if(str[i]>=’0‘ && str[i]<=’9‘) x=x*10+str[i]-’0‘; //讓str[i]作為x的個位

用for迴圈對字串每個字元進行處理,程式碼如下:

for(i=0;str[i];i++) if(str[i]>=’0‘ && str[i]<=’9‘) x=x*10+str[i]-’0‘;

完整的程式如下:

#include int main( ){char str[20],ch;long long x=0;short int cnt=0,i;while( cnt<20 && ( ch=getchar( ) )!=’\0‘) str[cnt++]=ch;str[cnt]=’\0‘;for(i=0;str[i];i++) if(str[i]>=’0‘ && str[i]<=’9‘) x=x*10+str[i]-’0‘;printf(”%Ld\n“,x);return 0;}

最後講一下

字串的長度

,字串的長度指的是字串中包含字元的個數。空字串”“指的是不包括任何字元的串,只有一個字元結束符’\0‘,因此字串長度為0。字串”Hello world!“的字元個數為12。但是如果字串中含有轉義符,則多個符號表示的轉義符只算作一個字元,如:字串”\\\x41\\“長度為3而不是8,因為’\\‘是一個字元,’\x41‘是一個字元’A‘,如果用printf輸出,顯示為:\A\。

本節主要介紹了字串常量及用字串陣列儲存、輸入與輸出字串的方法。字串的應用很頻繁,初學者只有不斷加強字串程式設計訓練才能更好掌握字串應用。本節就講到這裡,下次再見!