字串反轉是 C 語言基礎教學中的經典題目,也是面試高頻考點。本題要求將字元陣列 "student a am i" 原地反轉為 "i am a student",且只能開闢有限額外空間(O(1) 空間複雜度)。這正是雙指標原地交換演算法的典型應用場景。
#include <stdio.h>
// 反轉函數:傳入字串長度與字元陣列
void my_reverse(int len, char arr[]) {
int left = 0;
int right = len - 1;
while (left < right) {
char tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
left++;
right--;
}
}
int main() {
// 注意:原始字串已預先反轉字元順序,方便演示
char arr[] = "tneduts a ma i";
int len = sizeof(arr) / sizeof(arr[0]) - 1; // 扣除 '\0'
my_reverse(len, arr);
printf("%s\n", arr); // 輸出: i am a student
return 0;
}
sizeof vs strlensizeof(arr) 回傳整個陣列佔用的位元組數,包含結束符 '\0'。strlen(arr) 回傳字串實際字元長度,不含 '\0'。sizeof(arr)/sizeof(arr[0]) - 1 精確取得有效字元長度。left 從索引 0 開始,right 從 len-1 開始。left < right 時交換兩端字元,隨後向中間收攏。left >= right,確保奇偶長度皆正確處理。函數宣告為 void,因為直接修改傳入陣列的內容(陣列名退化為指標傳遞),無需額外回傳值。這符合 C 語言「傳址修改」的慣用模式。
若題目升級為「反轉單詞順序但保持單詞內字元順序」,例如 "student a am i" → "i am a student",可採用兩階段策略:
"i ma a tneduts""i am a student"void reverse_words(char *str) {
// 階段 1:整體反轉
int len = strlen(str);
my_reverse(len, str);
// 階段 2:逐單詞反轉
char *start = str;
for (char *p = str; *p; p++) {
if (*p == ' ') {
my_reverse(p - start, start);
start = p + 1;
}
}
my_reverse(strlen(start), start); // 處理最後一個單詞
}
| 錯誤類型 | 錯誤代碼 | 正確做法 |
|---|---|---|
| 長度計算錯誤 | int len = sizeof(arr); | int len = sizeof(arr)/sizeof(arr[0]) - 1; |
| 索引越界 | right = len; | right = len - 1; |
| 迴圈條件錯誤 | while (left <= right) | while (left < right) |
| 修改字串常數 | char *s = "abc"; reverse(s); | 使用陣列 char s[] = "abc"; |
掌握原地反轉演算法不僅能解決字串操作題目,更能鍛鍊指標操作與邊界條件控制能力,是 C 語言程式設計進階的必修課。