自行實現字串複製 `strcpy` 與字串比較 `strcmp` 的原型,掌握指標/陣列操作與空字元處理。
'\0'` 結尾,複製時必須連同結束符一起複製。char *my_strcpy(char *dest, const char *src);
char *my_strcpy(char *dest, const char *src) {
char *ret = dest; // 保存起始位址以便返回
while ((*dest++ = *src++) != '\0') // 複製字元並檢查結束符
; // 空循環體
return ret;
}
'\0'`),較短者視為「較小」。int my_strcmp(const char *s1, const char *s2);
int my_strcmp(const char *s1, const char *s2) {
while (*s1 && (*s1 == *s2)) { // 同時未結束且相等
s1++; s2++;
}
return (unsigned char)*s1 - (unsigned char)*s2; // 處理 signed char 溢位
}
#include <stdio.h>
#include <string.h> // 對比標準庫
char *my_strcpy(char *dest, const char *src);
int my_strcmp(const char *s1, const char *s2);
int main() {
char src[] = "I am src string";
char dest1[256] = "";
char dest2[256] = "";
// 測試 strcpy
my_strcpy(dest1, src);
strcpy(dest2, src); // 標準庫
printf("my_strcpy: %s\n", dest1);
printf("strcpy : %s\n", dest2);
printf("strcmp my vs std: %d\n", my_strcmp(dest1, dest2)); // 應為 0
// 測試 strcmp
printf("my_strcmp(\"abc\", \"abd\"): %d\n", my_strcmp("abc", "abd")); // 負
printf("strcmp (\"abc\", \"abd\"): %d\n", strcmp("abc", "abd")); // 負
printf("my_strcmp(\"abc\", \"abc\"): %d\n", my_strcmp("abc", "abc")); // 0
return 0;
}
| 錯誤 | 後果 | 修正 |
|---|---|---|
未複製 `'\0'` | 目標字串無結束符,後續操作讀越界 | 循環條件包含賦值檢查 `(*d++ = *s++) != '\0'` |
| 目標緩衝區未初始化/過小 | 覆蓋相鄰記憶體,未定義行為 | 呼叫者分配足夠空間,或改用 `strncpy` 限制長度 |
| 比較時用 `char` 直接相減 | 若 `char` 為有號,`127 - (-128)` 溢位導致錯誤符號 | 轉為 `unsigned char` 再相減 |
| 未處理空指標 | 段錯誤 | 實務中可加斷言 `assert(src && dest);` |
手寫 `strcpy`/`strcmp` 是理解 C 指標、陣列、字串結束約定、ASCII 比較語義的經典練習。掌握「以 `'\0'` 為邊界」的思維,並養成「返回目標指標支援鏈式」、「用 `unsigned char` 比較避免溢位」等良好習慣,對後續系統級開發大有裨益。