Re: [問題] 二維陣列給值的問題
每次看到 char arry, string 似乎都會讓人有所誤解..
放下 string 問題, 先看一段比較正常的程式碼
#include <stdio.h>
int main()
{
int i, arr[3] = {0,1,2};
for(i=0; i!=3; ++i) printf("%d ", arr[i]);
return 0;
}
這裡沒問題,重點是 3 如果改成 5,會有什麼結果?
很讓人意外的,「通常」只是會輸出一堆莫名奇妙的數字,
並不會馬上當掉,但後面的數字也變得沒有意義;
改成 10 的話,運氣好程式只是輸出錯誤,並不會停掉;
改成 100 的話,大概就一定會停掉了。
若到時 release 出去,這種錯誤並不好抓,
因不是每次執行結果都一定會失敗,有時失敗,有時成功;
最難抓的 bug, 我認為是 -
程式從頭到尾都很順的執行完了,但結果就是不對,上述是原因之一。
-----
回到正文,若以單純的「字元陣列」而言,
char CharArr[5] = {'1','2','3','4','5'};
實際上,那些 '1', '2', '3', '4', '5' ,在記憶體裡面,是存成
ASCII 數值,也就是存成 0x31 , 0x32, 0x33, 0x34, 0x35,是一堆二進位數值,
只是用 %c 或 %d 或 %u 時,會再翻譯成適當的 字元,整數。
上面 CharArr 是合法的「字元陣列」,陣列大小五個,元素也是五個,
沒問題,在輸出時我多加了一點東西進去。
for(int i=0; i!=5; ++i) {
printf("%c(%hhu)\n",
CharArr[i],CharArr[i]); /* 輸出字元與對應之 ascii */
}
這也沒問題。有問題的是 %s 的部份。
%s 會有一個特性,就是從第一個元素,輸出到「非 '\0' 元素」為止,
且注意到, '\0' 在 ASCII code 代表數值即為 0。
承上 CharArr,在我設定的陣列裡面,並沒有給它任何 '\0' 的元素,
在記憶體裡面,我合理假設它可能是長這樣
0x31 0x32 0x33 0x34 0x35 ???? ???? ???? ???? ???? 0x00
如果此時進行以下指令時
printf("%s", CharArr);
問題從這裡才開始產生,0x31 輸出 '1', 0x32 輸出 '2', ...
一直到那五個問號都還不是 '\0' (也就是 0),也會跟著一起輸出,
一直到最後遇到莫名的 0,才停止輸出,這也是為何你程式會有亂碼的原因。
-----
為了避免上述這種 %s 莫名奇妙不知道輸出到哪裡,於是在習慣上,
會把字元陣列的最尾巴,加上 '\0',也就是 ASCII(0) 這字元,作為結束字元。
所以若要用 %s 的時候,記得尾巴要加上 '\0',如
char CharArry[6] = { '1', '2', '3', '4', '5', '\0' };
注意到了,用 %s 時,最後那個 '\0' 是不會顯示出來的。
因為前面已經有 1~5 五個元素,還要再加上 1 個「結束字元」,所以才會有種說法
字元陣列的大小,至少要大於等於字串長度 + 1 才行。
當然下面三種宣告並給初值的方式都一樣的。
char CharArr[6] = { '1' , '2', '3', '4', '5', '\0'}; /* 字元設定 */
char CharArr[6] = { 0x31 , 0x32, 0x33, 0x34, 0x35, 0x00}; /* ASCII Hex */
char CharArr[6] = { 49 , 50, 51, 52, 53, 0 }; /* ASCII Dec */
至於還會有一些常見的字串常量 (字面常量),會直接寫成
char CharArr[6] = "12345" ;
事實上,這種寫法已經有偷偷在最後補上 0 了,
表面上只有用到五個元素,實際上包含了結束字元後,它一共是六個元素。
所以下面三種 %s 寫法,在 printf - %s 時都沒問題
char Str1[100] = {'1','2','3','4','5','\0'}; /* 沒設到元素全 0 */
char Str2[100] = "12345"; /* 注意到,最後有偷補 0 進去 */
printf("%s %s %s\n", Str1, Str2, "12345");
----
最後整理重點出來
1. 字元陣列 與 字串,差別在於 「有沒有結束字元」
2. %s 只能輸出字串,不能輸出字元陣列;意指,一定要有結束字元。
3. 字串常量 "abcd",事實上都有偷補結束字元 '\0' 進去,所以用 %s 不會有問題。
4. 使用 strlen、strcat ... 等相關字串函式,也會以結束字元 '\0' 做參考。
看完說明後,我想你下次問題的答案,已在 13 戒之 4,有空先去逛逛。
--
YouLoveMe() ? LetItBe() : LetMeFree();
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 180.177.78.41
→
08/25 02:30, , 1F
08/25 02:30, 1F
推
08/25 02:34, , 2F
08/25 02:34, 2F
推
08/25 03:48, , 3F
08/25 03:48, 3F
→
08/25 04:04, , 4F
08/25 04:04, 4F
→
08/25 04:06, , 5F
08/25 04:06, 5F
推
08/25 04:35, , 6F
08/25 04:35, 6F
討論串 (同標題文章)
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章