了解陣列元素的位址 陣列 指標的應用 10-1 陣列與指標的關係 可以使用位址運算子 (&) 來查詢陣列中各個元素的位址 &test[0] 這行表示陣列最前面元素的位址 &test[1] 這行表示陣列第二個元素的位址
關於陣列名稱的機制 陣列名稱可以表示陣列最前面元素的位址 #include <stdio.h> int main(void) int test[5] = 80,60,55,22,75; printf("test[0] 的值為 %d \n", test[0]); printf("test[0] 的位址為 %p \n", &test[0]); printf("test 的值為 %p \n", test); return 0; 用陣列名稱來表示陣列最前面元素的位址
由陣列名稱來求出陣列最前面元素的值 陣列名稱和儲存了陣列最前面元素位址的指標擁有相同的功用 在陣列名稱加上 * 之後, 就可以表示陣列最前面元素的值 test &test[0] 陣列最前面元素的位址 *test test[0] 陣列最前面元素的值
理解指標運算的機制 運算子 指標運算的例子 ( 但是 p p1 p2 為指標 ) + p+1 取得 p 所指向元素的下一個元素位址 - p-1 取得 p 所指向元素的前一個元素位址 - p1-p2 取得 p1 和 p2 之間的元素數 ++ p++ 取得 p 所指向的下一個元素位址 -- p-- 取得 p 所指向的前一個元素位址 *test test[0] 陣列最前面元素的值 *(test+1) test[1] 陣列第二面元素的值 *(test+2) test[2] 陣列第三個元素的值
使用陣列名稱的注意事項 陣列名稱可以想成是儲存陣列最前面元素之位址的指標 但這裡的指標和一般的指標有些不同 表示陣列名稱的指標不可以指派其他變數的位址 #include <stdio.h> int main(void) int a = 5; int test[5] = 80,60,55,22,75; /* 錯誤 */ /* test = &a; */ return 0; 無法指派其他的位址
10-2 引數與陣列 把陣列當作引數使用 當使用陣列作為引數時, 必須傳遞陣列第一個元素的位址作為引數
將指標當作引數使用 當傳遞陣列第一個元素的位址作為引數時, 可以把指標寫成參數
對指標使用 [ ] 運算子 [ ] 也稱為註標運算子 (subscript operator) 對指標使用 [ ] 運算子的表示方式之意義為 從指標 pt 所指向的元素開始算起, 找出前二位的元素 當指標指向陣列時, 把指標加上 [ ], 就可以代表其所指向的元素 這正好與陣列的標示方法相同 只有在指標和陣列有密切的關係時, 才可以在指標加上 [ ] 運算子 double avg(int *pt) int i; double sum; sum = 0.0; for(i=0; i<5; i++) sum += pt[i]; 可以對指標使用 [ ] 運算子 return sum/5;
將字串視為指標處理 範例 1: char str[] = "Hello"; 利用陣列將字串初始化 範例 2: char *str = "Hello"; 操作指向字串所在位址的指標 範例 3: printf( 字串為 %s \n, str); 使用指標輸出字串
理解陣列和指標不同的地方 用陣列來操作字串時, 無法藉由指派陣列名稱來改變字串 而使用指標來操作字串時, 可以指派到指標來變更所指向的字串
字串陣列的陣列 #include <stdio.h> int main(void) 將一個字串限制在 19 個字元以內 char str[3][20] = "Hello", "GoodBye", "Thankyou"; int i; 準備好由三個字串所組成的陣列 for(i=0; i<3; i++) printf(" 字串為 %s \n", str[i]); 將字串逐一輸出 return 0;
字串指標的陣列 #include <stdio.h> int main(void) 準備好由三個字串所組成的陣列 char *str[3] = "Hello", "GoodBye", "Thankyou"; int i; for(i=0; i<3; i++) 將字串逐一輸出 printf(" 字串為 %s \n", str[i]); return 0;
10-4 字串的操作 使用標準程式庫函數 C 語言的開發環境中包含了標準程式庫函數 (standard library) 使用字串操作函數的時候, 要先引入 string.h 這個檔案 表 10-2: 操作字串的標準程式庫函數 (string.h) size_t strlen(const char *str); 除去字串 s 的 NULL 字元後, 傳回長度 char * strcpy(char *str1, const char *str2); 將字串 str2 複製到 str1 區域後, 傳回 str1 char * strcat(char *str1, const char *str2); 將字串 str2 追加到字串 str1 的最後面, 然後傳回 str1 int strcmp(const char *str1, const char *str2); 比較字串 str1 與字串 str2, 依照情況傳回以下的值 如果字串 str1 比字串 str2 小的時候 : 負值如果字串 str1 與字串 str2 相等的時候 :0 如果字串 str1 比字串 str2 大的時候 : 正值
查詢字串的長度 要查出字串的長度時, 可以使用 strlen() 函數 #include <stdio.h> #include <string.h> 先引入這個標頭檔 int main(void) char str[100]; printf(" 請輸入一個字串 ( 英數字 ) \n"); scanf("%s", str); printf(" 字串的長度為 %d \n", strlen(str)); 輸出字串的長度 return 0;
將字串複製到陣列當中 要把字串複製到陣列的時候, 可以使用 strcpy() 函數 #include <stdio.h> #include <string.h> int main(void) char str1[10]; char str2[10]; 把 Hello 複製到 str1 當中 strcpy(str1,"hello"); strcpy(str2,"goodbye"); 把 Goodbye 複製到 str2 當中 printf(" 陣列 str1 為 %s \n", str1); printf(" 陣列 str2 為 %s \n", str2); return 0;
將字串連結起來 要將字串連結起來, 可以使用 strcat() 函數 #include <stdio.h> #include <string.h> int main(void) char str0[20]; char str1[10]; char str2[10]; strcpy(str1,"hello"); strcpy(str2,"goodbye"); strcpy(str0,str1); strcat(str0,str2); 把 str1 複製到 str0 中 在 str0 的最後連結上 str2 printf( 陣列 str1 為 %s \n", str1); printf( 陣列 str2 為 %s \n", str2); printf( 二個陣列連結起來就變成 %s \n", str0); return 0; 輸出連結後的字串
注意陣列的大小 在把字串複製到陣列的情況下, 要注意不可以超出陣列的大小 int main(void) char str0[10]; 不可以使用大小不足的陣列 char str1[10]; char str2[10];
將字串進行比較 要比較字串的時候, 可以使用 strcmp() 函數 #include <stdio.h> #include <string.h> int main(void) char str1[100]; char str2[100]; printf(" 請輸入第 1 個字串 \n"); scanf("%s", str1); printf(" 請輸入第 2 個字串 \n"); scanf("%s", str2); if(strcmp(str1, str2) == 0) printf("2 個字串是相同的 \n"); else printf(" 這 2 個字串不一樣 \n"); return 0; 否則就輸出 不一樣 的意思 準備長度相同的陣列 如果比較字串之後的結果是 0 則輸出 相同 的意思
執行的時候才決定字串的長度 #include <stdio.h> #include <stdlib.h> 引入這個標頭檔 int main(void) char *str; int num, i; printf(" 要準備幾個 a?\n"); scanf("%d", &num); str = (char *) malloc (sizeof(char) * (num+1)); if(!str) printf(" 無法配置記憶體 \n"); return 1; for(i=0; i<num; i++) *(str+i) = 'a'; *(str+num) = '\0'; printf(" 準備了 %s \n", str); free(str); return 0; 得到表示被配置的記憶體位置之指標 指定的數量 +1 配置 char 型態大小的記憶體 使用指標儲存到陣列中 最後加上 \0 當成字串
10-5 函數指標 理解函數指標 函數擁有記憶體上的位址, 函數指標當中則儲存了函數的位址 儲存這種 函數位址 的指標就叫做函數指標 (function pointer)
宣告函數指標 宣告函數指標的語法 : 傳回值的型態 (* 指標 ) ( 引數列表 ) int (*pm)(int x, int y); 指定函數傳回值的型態 函數指標 pm 的宣告 指定函數的引數型態
將位址儲存於函數指標 指定指向函數指標的位址之語法 : 函數指標 = 函數名稱 ; pm = max; 呼叫利用函數指標的函數之語法 : (* 函數指標 ) ( 引數列表 ); res = pm(5, 10);
運用函數指標 可以使用函數指標來呼叫出函數 #include <stdio.h> /*max 函數的宣告 */ int max(int x, int y); int main(void) int num1, num2, ans; int (*pm)(int x, int y); pm = max; printf(" 請輸入第 1 個數值 \n"); scanf("%d",&num1); printf(" 請輸入第 2 個數值 \n"); scanf("%d",&num2); ans = (*pm)(num1, num2); printf(" 最大值為 %d \n", ans); return 0; /* max 函數的定義 */ int max(int x, int y) if (x > y) return x; else return y; 宣告函數指標 指定函數的位址 使用指標呼叫出函數
應用函數指標之範例 : #include <stdio.h> /* 函數的宣告 */ void show0(void); void show1(void); void show2(void); int main(void) void (*pm[3])(void); 宣告函數指標的陣列 int num; pm[0] = show0; pm[1] = show1; 將函數的指標指定給陣列元素 pm[2] = show2; printf(" 要呼叫哪一種交通工具?(0: 汽車 1: 賽車 2: 飛機 )\n"); scanf("%d",&num); if(0<= num && num <= 2) (*pm[num])(); return 0; /* 函數的定義 */ void show0(void) printf(" 汽車 \n"); void show1(void) 使用指標呼叫出函數 printf(" 賽車 \n"); void show2(void) printf(" 飛機 \n");