截至目前為止,我們都只使用到「存放整數的陣列」,然而陣列是可以存放任何型別的資料集合
現在讓我們來討論使用「存放字元的陣列」來儲存「字串」
對於 C 而言,字串(例如 "Hello" ) 是一個存放各個字元的陣列,存放字串的陣列我們就稱為字元陣列
當我們宣告一個陣列為 char 型別,就指明該陣列為字元陣列,其可以使用字串(用雙引號包裹文字,如下方的 "Hello" 就是字串)來指定陣列的初始值。
註 : 將字母用單引號包裹起來就成了字元,用雙引號包裹起來成了字串
註 : 將字母用單引號包裹起來就成了字元,用雙引號包裹起來成了字串
char string[] = "Hello";
該程式語句會將陣列 string 的元素初始值設定為字串 "Hello" 的 "各個字元" ,且該陣列的大小將由編譯器根據字串的長度自動決定
字串 "Hello" 包含五個英文字母加上一個自動生成的空字元(null character)
空字元又稱空白字元或結束字元,因此陣列 string 實際上具有 6 個元素。空白字元為 '\0'
在C語言裡,字串都會「自動」以空白字元做為結束
註 : 只有宣告為 char 並加上雙引號的陣列才會自動生成空白字元,其他型態(type)的陣列並不會有。若將"一個字元"硬是用雙引號括起來,會使得該陣列具有兩個元素,其中一個為自動產生的空白字元 '\0'
字串 "Hello" 包含五個英文字母加上一個自動生成的空字元(null character)
空字元又稱空白字元或結束字元,因此陣列 string 實際上具有 6 個元素。空白字元為 '\0'
在C語言裡,字串都會「自動」以空白字元做為結束
註 : 只有宣告為 char 並加上雙引號的陣列才會自動生成空白字元,其他型態(type)的陣列並不會有。若將"一個字元"硬是用雙引號括起來,會使得該陣列具有兩個元素,其中一個為自動產生的空白字元 '\0'
字元陣列也可以用各別的字元來給予初始值,以下宣告與上方程式語句的宣告是等價的
char string[] = { 'H', 'e', 'l', 'l', 'o', '\0' };
因為字串實際上是字元所組成的陣列,所以我們可以直接使用索引(index)來直接存取字串中各別的字元,例如 string1[0] 是字元 'H'
我們可以用 scanf 配合轉換指定詞 %s 直接從鍵盤輸入"一個字串"到字元陣列中。例如
char string2[20];
產生了一個能存放 19 個字元加上 1 個空字元的字元陣列
scanf( "%s", string2 );
上述程式語句會從鍵盤讀入一個字串到 string2 當中
注意 : 當我們使用 scanf 將字串讀入時,並不需要像一般的變數一樣加上 "&" 符號。(原因在指標章節敘述)因為 & 符號實際上是用來告訴 scanf 讀進來的字元要放入哪個「地址」
注意 : 當我們使用 scanf 將字串讀入時,並不需要像一般的變數一樣加上 "&" 符號。(原因在指標章節敘述)
scanf 函式將會一直讀入字元,直到遇上了空白、tab、new line 或 end-of-file 指示器為止
注意我們在宣告 string2 時表明只能存放 19 個字元,假若使用者輸入的字串大於 19 個字元,則成是很有可能會因此當機。所以在使用 scanf 讀入字串時,以下的寫法是比較好的
注意我們在宣告 string2 時表明只能存放 19 個字元,假若使用者輸入的字串大於 19 個字元,則成是很有可能會因此當機。所以在使用 scanf 讀入字串時,以下的寫法是比較好的
scanf( "%19s", string2 );
在轉換指定詞內加入數字,可以限定能夠輸入的字串長度,超過 19 字元的話 scanf 就不會將超過的部分寫入記憶體地址內。
同樣的, printf 也可以配合 %s 來加以輸出,例如
printf( "%s\n", string2 );
如同 scanf , printf 也不會檢查字元陣列到底有多大,它會一直列印此陣列的各個字元,直到遇到空字元 ('\0\) 為止。
使用 pinrtf 在轉換指定詞%後方加上數字可以限制列印字串長度,同時顯示的結果會靠右對齊。
scanf 的缺陷(排除字元)
事實上前文講到的 "使用 scanf 來讀入字串" 具有一個致命的缺陷
之前的例子我們輸入的字串為「 WYJlearning 」並且它可以成功在螢幕上顯示。但如果我們換成輸入字串「 WYJ learning 」時會出現一個致命的錯誤,它只有印出「WYJ」 三個字(如下圖),空格後方的文字都不見了
其原因我們在前一篇有用幾個字帶過
「scanf 函式將會一直讀入字元,直到遇上了空白、tab、new line 或 end-of-file 指示器為止」
遇到空白就會停止? 這樣的限制可真是令人頭疼。但我們可以用一些技巧來破解這函式的限制
上方程式碼中的第 9 行 scanf( "%19[^\n]", string2 ); 我們用了 "%19[^\n]" 代替原本的 "%19s"
中括弧內代表的是掃描字符集合
我們在裡面使用了 ^ ,代表遇到字元 \n 後,結束 scanf 提取的意思
也就是說該語句會掃描使用者從鍵盤輸入的字元,並且不斷的掃描直到遇到 enter 鍵(即為\n) ,如此一來就可以避過 scanf 本身遇到空格會停止擷取的缺陷。
在上例中我們也測試了限制輸入字串長度為 19 是否起作用。由結果可以看出,我們輸入的字串大於 19 字元之後的字符(也就是ABC) 的確沒有被擷取以及列印顯示出來。
#include "stdio.h"
int main(void) {
setvbuf(stdout,NULL,_IONBF,0);
char string1[] = "Hello";
char string2[20];
int size = sizeof(string1)/sizeof(string1[0]);
printf( "string1[] size : %d\n\n", size );
printf( "Enter a string : " );
scanf( "%19s", string2 );
printf( "string1 is %s\n", string1 );
printf( "string2 is %s\n", string2 );
printf( "string2 is %19s\n\n", string2 );
printf( "Print string1 word by word \n" );
for( int i = 0; i < size ; i++){
printf( "%c\n", string1[i] );
}
printf( "Another way(smarter) \n" );
for( int i = 0; string1[i] != '\0' ; i++){
printf( "%c\n", string1[i] );
}
}
使用 pinrtf 在轉換指定詞%後方加上數字可以限制列印字串長度,同時顯示的結果會靠右對齊。
scanf 的缺陷(排除字元)
事實上前文講到的 "使用 scanf 來讀入字串" 具有一個致命的缺陷
#include "stdio.h"
int main(void) {
setvbuf(stdout,NULL,_IONBF,0);
char string1[] = "Hello";
char string2[20];
int size = sizeof(string1)/sizeof(string1[0]);
printf( "string1[] size : %d\n\n", size );
printf( "Enter a string : " );
scanf( "%19s", string2 );
printf( "string1 is %s\n", string1 );
printf( "string2 is %s\n", string2 );
printf( "string2 is %19s\n\n", string2 );
printf( "Print string1 word by word \n" );
for( int i = 0; i < size ; i++){
printf( "%c\n", string1[i] );
}
printf( "Another way(smarter) \n" );
for( int i = 0; string1[i] != '\0' ; i++){
printf( "%c\n", string1[i] );
}
}
之前的例子我們輸入的字串為「 WYJlearning 」並且它可以成功在螢幕上顯示。但如果我們換成輸入字串「 WYJ learning 」時會出現一個致命的錯誤,它只有印出「WYJ」 三個字(如下圖),空格後方的文字都不見了
其原因我們在前一篇有用幾個字帶過
「scanf 函式將會一直讀入字元,直到遇上了空白、tab、new line 或 end-of-file 指示器為止」
遇到空白就會停止? 這樣的限制可真是令人頭疼。但我們可以用一些技巧來破解這函式的限制
#include "stdio.h"
int main(void) {
setvbuf(stdout,NULL,_IONBF,0);
char string2[20];
printf( "Enter a string : " );
scanf( "%19[^\n]", string2 );
printf( "\nstring2 is %19s\n", string2 );
return 0;
}
上方程式碼中的第 9 行 scanf( "%19[^\n]", string2 ); 我們用了 "%19[^\n]" 代替原本的 "%19s"
中括弧內代表的是掃描字符集合
我們在裡面使用了 ^ ,代表遇到字元 \n 後,結束 scanf 提取的意思
也就是說該語句會掃描使用者從鍵盤輸入的字元,並且不斷的掃描直到遇到 enter 鍵(即為\n) ,如此一來就可以避過 scanf 本身遇到空格會停止擷取的缺陷。
在上例中我們也測試了限制輸入字串長度為 19 是否起作用。由結果可以看出,我們輸入的字串大於 19 字元之後的字符(也就是ABC) 的確沒有被擷取以及列印顯示出來。