C語言-陣列與字串
陣列
如果是需要使用到多個變數的場合,例如統計全班成績,宣告這麼多的變數儲存成績是不實際的
所以C語言提供陣列,方便你宣告一個以索引為識別的資料結構
一維陣列
陣列的宣告方式如下:
1 | 資料型態 變數名稱[陣列長度]; |
例如:
1 | int score[10]; // 宣告10個元素的整數陣列 |
陣列的長度必須事先決定,原因是因為編譯器在編譯過程中,陣列所需的空間必須是靜態的
如果長度不確定,編譯器就無法保留空間給陣列
下一個章節會提到如果陣列空間不確定時,如何宣告一個動態長度的陣列
而之前在資料型態與變數運算有提過,變數宣告後
變數的內容是不確定的,所以你可以這樣初始化陣列
1 | int score[10] = {0}; // 這樣裡面10個元素都會初始化為0 |
你也可以在宣告陣列的時候指定初始值
1 | int score[10] = {1,2,3,4,5,6,7,8,9,10}; |
當你需要存取某個元素的時候,只要
1 | int first = score[0]; |
這樣就可以取得第一個元素的值了,這邊要注意的是
陣列的索引值是從0開始,從0到9總共10個元素
而為什麼索引值從0開始,是因為陣列名稱是指向陣列第一個元素的
索引值就是往後偏移量,因為開頭已經指向第一個元素,所以偏移量是零
陣列的每個元素可以直接當作變數使用,也可以直接做輸入輸出
下面是一個簡單的範例程式
1 |
|
執行結果
請輸入第1個元素:10
請輸入第2個元素:9
請輸入第3個元素:8
請輸入第4個元素:7
請輸入第5個元素:6
請輸入第6個元素:5
請輸入第7個元素:4
請輸入第8個元素:3
請輸入第9個元素:2
請輸入第10個元素:1
你輸入了:10 9 8 7 6 5 4 3 2 1
使用陣列時有以下幾點要注意
如果你在初始化的時候未定義陣列大小,編譯器將會幫你決定陣列大小
1
2
3
4
5
6
7
8
9
10
11
int main(void) {
int array[] = {1,2,3,4,5};
printf("陣列長度:%d\n", sizeof(array) / sizeof(array[0]));
return 0;
}執行結果
陣列長度:5
不能存取超過陣列長度的元素,這會造成無法預期的錯誤
小則取得無法預期的值,大則程式爆炸
1
2
3
4
5
6
7
8
9
10
11
int main(void) {
int array[] = {1,2,3,4,5};
printf("第八個元素:%d\n",array[7]);
return 0;
}
執行結果
第八個元素:0
陣列是不能直接指定的,必須一個元素一個元素指定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int main(void) {
int array1[] = {1,2,3,4,5};
int array2[5] = {0};
int i;
for(i = 0; i < 5; i++)
array2[i] = array1[i];
for(i = 0; i < 5; i++)
printf("%d ",array2[i]);
puts("");
return 0;
}執行結果
1 2 3 4 5
想要比較陣列是否相同,也必須一個元素一個元素比較
如果傳陣列到函數裡面,在函數裡面的改變會保留回到主函數,原因會在下一章說明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
void modify_array(int[],int);
int main(void) {
int array[] = {1,2,3,4,5};
int i;
printf("改變前:");
for(i = 0; i < 5; i++)
printf("%d ",array[i]);
printf("\n");
modify_array(array,5);
printf("改變後:");
for(i = 0; i < 5; i++)
printf("%d ",array[i]);
printf("\n");
return 0;
}
void modify_array(int array[],int length){
int i;
for(i = 0; i < length; i++)
array[i] *= 2;
}執行結果
改變前:1 2 3 4 5 改變後:2 4 6 8 10
二維陣列
如果你想統計全校成績,就需要使用二維陣列,宣告語法如下
1 | 變數型態 變數名稱[ROW][COLUMN]; |
例如:
1 | int score[5][40]; // 5個班級,每班40個人 |
二維陣列在宣告的時候指定初始值如下:
1 | int array[2][3] = { |
以下是二維陣列的範例程式,宣告了5列9行的二維陣列,num[i-1][j-1]表示取出第i-1列j-1行的元素
1 |
|
執行結果
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
二維陣列實際上是一維陣列的變形,以下二維陣列的宣告實際上跟一維陣列的宣告是一樣的
1 | int num[2][3] = { |
而行與列是我們為了理解陣列元素的存取想像而來的,在記憶體中,二維陣列仍然是線性配置的
兩個索引值代表的意義都是跟陣列開頭偏移的量,只是第一個偏移量是以一維陣列計算
例如num[1][0]表示往後偏移一個長度為3的一維陣列
而num[1][2]則代表往後偏移一個長度為3的一維陣列,再往後偏移2個元素
如果想傳二維陣列到函數,不像一維陣列這麼簡單,以下是範例程式
1 |
|
執行結果
1 2 3
4 5 6
字串
宣告與使用
在C語言裡面,字元陣列又稱為字串,由’\0’做結尾,宣告語法如下
1 | char str[20]; // 宣告可以輸入20字以內的字串 |
你也可以像初始化陣列一樣初始化字串
1 | char str[] = "Hello World!" |
這邊要注意的是字串結尾’\0’也算是字元,所以上面這個字串的長度為13,而不是12
1 |
|
執行結果
Hello World!的長度為:13
H e l l o W o r l d ! \0
也就是說,你宣告50個字元,實際上只有49個字元可以使用,如果超過上限會導致不可預期的爆炸XD
字串跟陣列一樣,除了初始化可以指定以外,其他時機是不能指定的,必須一個元素一個元素指定
1 |
|
這邊要注意,上面只會顯示What,因為str[4]就會被認為是字串結尾,之後不管有什麼都不管
執行結果
What
字串其實就是一維陣列,所以傳參數到函數的方式跟陣列一樣,以下是示範程式
1 |
|
執行結果
反轉前:Hello World!
反轉後:!dlroW olleH
常用函數
C語言提供了很多函數來操作字串,以下舉幾個常用例子
函數名稱 | 標頭檔 | 說明 |
---|---|---|
strlen | string.h | 取得字串長度(不含’\0’) |
strcpy | string.h | 複製字串 |
strcat | string.h | 連接字串 |
strcmp | string.h | 比對字串 |
strstr | string.h | 找出符合的子字串 |
atoi | stdlib.h | 將字串轉為int |
atol | stdlib.h | 將字串轉為long |
atof | stdlib.h | 將字串轉為double |
isalnum | ctype.h | 是否為字母或數字 |
isalpha | ctype.h | 是否為字母 |
isdigit | ctype.h | 是否為數字 |
islower | ctype.h | 是否為小寫字母 |
isupper | ctype.h | 是否為大寫字母 |
以下是幾個範例程式
strlen範例程式
size_t是string.h所定義的資料型態,大部分為unsigned int
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main() {
char input[] = "Hello World!";
size_t length;
length = strlen(input);
printf("字串長度:%u\n", length);
return 0;
}執行結果
字串長度:12
strcpy範例程式
第一個參數是目標變數,第二個參數是你要複製的變數
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main() {
char input[50];
char tmp[50];
puts("請輸入字串:");
gets(input);
strcpy(tmp, input);
printf("複製後:%s\n", tmp);
return 0;
}執行結果
請輸入字串: Hello 複製後:Hello
strcat範例程式
第一個參數是要被連接的變數,第二個參數是要連接上去的變數
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main() {
char str1[50] = "Hello";
char str2[] = "World";
printf("串接前:%s\n", str1);
strcat(str1, str2);
printf("串接後:%s\n", str1);
return 0;
}執行結果
串接前:Hello 串接後:HelloWorld
strcmp範例程式
參數是兩個要比較的字串str1,str2,傳回-1代表str1<str2,傳回0表示相等,傳回1表示str1>str2
比較方法是字典順序,字典順序就像字典在編排單字一樣,例如b大於a,ab大於aa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main() {
char str1[] = "a";
char str2[] = "ab";
printf("str1 < str2 %d\n",strcmp(str1, str2));
printf("str1 == str2 %d\n",strcmp(str1, str1));
printf("str1 > str2 %d\n",strcmp(str2, str1));
}執行結果
a < ab -1 a == a 0 ab > a 1