陣列與字串
-
陣列與指標
-
陣列變數設定初始值的語法:
int x[5] = { 2, 3, 5, 7, 11 }; 或簡寫成: int x[] = { 2, 3, 5, 7, 11 };
- 陣列的名字單獨寫時, 相當於最前面那個元素的位址. 例: 若有
int dm[13];
則dm
與& dm[0]
有相同的意義.
Q: 有沒有那一個盒子的名字叫做 dm? - 指標變數或陣列名稱與整數相加的意義:
dm+5
相當於& dm[5]
, 也就是說dm[5]
相當於* (dm+5)
同樣地, 若有 int *p; 則p[k]
與*(p+k)
意義完全相同. - 注意: 因為在 C/C++ 當中, 所有的變數都必須宣告型別, 所以 C compiler 可以自動推算指標變數加一時, 真正的樓層數應該移動多少. 上例中若 dm 在第 0x2f4c 層, 則 dm+1 為第 0x2f50 層; 但若當初宣告為 char dm[13]; 則 dm+1 為第 0x2f4d 層.
- Q: 在 a[b] 一式中, a 與 b 各扮演 ?-value 的角色?
- 作業: 請做 address.c 當中的作業 3
-
作業: 假設有下列宣告及程式片段
int tab[10], *p, *q, *r, x; p = tab; q = &x; r = &tab[2];
則我們總共要來了幾個盒子可以用? 並解釋以下各程式片段的作用 (圖示?)++x ++&x ++*(tab+3) ++(tab+3) ++p[1] ++*p ++(q+2) ++*(q+2) ++r ++r[3]
-
作業:
- 把 randwalk.c 當中四處走動的遊標改成四處走動的蠶寶寶. 第一個版本先不考慮身體打結的狀況. 再加入測試條件避免身體打結 (但是既不可以打結, 又不可以走回頭路, 還要避免撞牆, 有沒有甚麼情況會卡住呢?)
- 修改蠶寶寶程式, 讓螢幕上同時出現 n 隻. 不要管彼此穿越了.
- 寫一個簡單的 game of life
-
高維陣列: 採 row major 儲存方式. 例如:
int x[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
則x[0] == &x[0][0] x[0]+1 == &x[0][1] x[0]+2 == &x[0][2] x[0]+3 == &x[1][0] x[0]+4 == &x[1][1] x[0]+5 == &x[1][2]
-
陣列變數設定初始值的語法:
-
字串
-
字串不過是字元的陣列而已. 約定俗成:
每個字串的最後一個字元必須是 '\0' (ASCII 碼為零的那個字元)
例:
char s[8]; s[0] = 'h'; s[1] = 'e'; s[2] = 'l'; s[3] = 'l'; s[4] = 'o'; s[5] = '\0';
Q: 如果當初宣告 s 為 char *s; 會有什麼問題? -
初始值的設定: 上例可簡寫為:
char s[8] = { 'h', 'e', 'l', 'l', 'o', '\0' }; 又可簡寫為: char s[8] = "hello";
-
Q: 仔細研究主程式的 prototype: int main(int argc, char
*argv[]); 如果使用者在命令列上輸入: a.out hello world good
morning 請問下列各式的型別各是什麼, 值各是多少? (畫圖表示)
(argv+1)[2] argv[1]+2 argv[1][2] *argv+1+2 *(argv+1)+2 *(argv+1+2) *(argv+1)[2] *(argv[1]+2) (*argv+1)[2]
-
特殊語法: 字元指標的初始值設定:
char * p = "hello";
系統會安排一塊可讀不可寫的空間存放 "hello", 並將那塊空間的起始位址存放到 p 裡面. 建議寫成:char const * p = "hello";
- 一般規則: string literal 單獨寫時, 系統會安排一塊可讀不可寫的空間存放該字串, 並傳回那塊空間的起始位址. (例外: 字元陣列的初始值設定)
- C 不允許將一個陣列以 "=" 直接拷貝到另一個陣列.
如果要拷貝字串, 必須呼叫系統函數:
strcpy(s, "hello");
-
傳遞參數時, 副程式期待它的實際參數扮演 r-value 的角色: 假設有
char s[8], t[8]; char * p, * q; p = s; q = t;
則strcpy(p, "hello");
與strcpy(s, "hello");
的效果相同. Q:strcpy(p+1, q+2)
有何效果? -
作業: 學習使用 string.h 中宣告的 strcpy, strcat, strlen,
strcmp, strchr, strrchr, strstr 等函數. 例:
strcmp("save earth", "save earth ") == ?
又, 若char s[20] = "hello, "; char t[20] = "world!";
則 strcpy(s, t) 之後, printf("%s\n%s\n", s, t) 印出?
而 strcat(s, t) 之後, printf("%s\n%s\n", s, t) 印出? -
空字元/空指標/空字串的分別:
- 空字元: '\0' 這個 ASCII 碼為零的字元. 例: char c = '\0';
- 空指標: 0x0000 這個位址. 例: char * p = NULL; 注意: NULL 的定義可在 stdio.h 或 stdlib.h 中找到, 其實只是 0, 但是應該把 NULL 當做指標看, 而不要把 NULL 當做數字來看.
- 空字串: 程式可以使用的字元陣列, 但是只包含一個字元 -- 空字元. 例: char s[8] = "";
-
Q: 假設有上面的宣告, 則以下各式的運算結果各為 True 或是
False? 還是會有 Compile time error 或是 Run time error?
p==NULL p=='\0' p=="" s==NULL s=='\0' s=="" *p==NULL *p=='\0' *p=="" *s==NULL *s=='\0' *s==""
- 作業: 寫一個函數 my_strcmp 模擬 strcmp, 並且寫主程式從命令列接受兩個字串參數, 印出 strcmp 的比較結果與 my_strcmp 的比較結果. 注意邊界狀況 (boundary conditions), 例如輸入的字串如果是空指標/空字串等等.
-
字串不過是字元的陣列而已. 約定俗成:
每個字串的最後一個字元必須是 '\0' (ASCII 碼為零的那個字元)
例:
- 本頁最新版網址: https://frdm.cyut.edu.tw/~ckhung/b/c/string.php; 您所看到的版本: February 14 2012 10:32:25.
- 作者: 朝陽科技大學 資訊管理系 洪朝貴
- 寶貝你我的地球, 請 減少列印, 多用背面, 丟棄時做垃圾分類。
- 本文件以 Creative Commons Attribution-ShareAlike License 或以 Free Document License 方式公開授權大眾自由複製/修改/散佈。