將字串倒序輸出,比較「複製到新陣列」與「原地交換」兩種演算法。
// 錯誤程式碼
char a[50], a1[50];
gets(a); // ❌ 不安全,已移除 C11
int len = strlen(a);
for (int i = 0; i < len; i++) {
a1[i] = a[len - i - 1];
}
for (int i = 0; i < len; i++) {
printf("%s", a1[i]); // ❌ %s 期望 char*,傳入 char 導致崩潰/亂碼
}
gets() 無緩衝區長度限制,**極度危險**,C11 標準已移除,編譯器會警告。printf("%s", a1[i]) 將單一字元 a1[i] (整數提升為 int) 當作字串指標傳遞,導致存取無效記憶體。a1[len] = '\0';,非字串格式。char a[50], a1[50];
fgets(a, sizeof(a), stdin);
a[strcspn(a, "\n")] = '\0'; // 移除換行
int len = strlen(a);
for (int i = 0; i < len; i++) {
a1[i] = a[len - 1 - i];
}
a1[len] = '\0'; // 關鍵:加上結尾符
printf("反轉結果: %s\n", a1); // 整串輸出用 %s
// 原始碼邏輯正確
for (int i = 0; i < len / 2; i++) {
char temp = a[i];
a[i] = a[len - 1 - i];
a[len - 1 - i] = temp;
}
for (int i = 0; i < len; i++) {
printf("%c", a[i]); // 逐字元輸出用 %c 正確
}
strrev (非標準,MSVC 專有)// Windows MSVC 可用
#include <string.h>
char str[] = "Hello";
strrev(str);
printf("%s\n", str); // "olleH"
跨平台請自行實作或用標準函數組合。
#include <string.h>
void reverse_string(char* str) {
if (!str) return;
int len = strlen(str);
for (int i = 0, j = len - 1; i < j; i++, j--) {
char tmp = str[i];
str[i] = str[j];
str[j] = tmp;
}
}
int main() {
char line[100];
printf("輸入字串: ");
fgets(line, sizeof(line), stdin);
line[strcspn(line, "\n")] = '\0';
reverse_string(line);
printf("反轉: %s\n", line);
return 0;
}
| 方法 | 時間複雜度 | 空間複雜度 | 優點 | 缺點 |
|---|---|---|---|---|
| 複製新陣列 | O(n) | O(n) | 原字串保留 | 額外記憶體 |
| 原地交換 | O(n) | O(1) | 空間最省 | 破壞原字串 |
| 遞迴 | O(n) | O(n) 堆疊 | 教學展示 | 棧溢位風險 |
fgets 替代 gets'\0'printf("%s", str) 輸出整串,printf("%c", ch) 輸出單字元len-1-i 而非 len-i