字符串就地逆序的指針算法詳解
題目要求
將輸入字符串按逆序重新排列,要求使用字符指針實現,即就地(in-place)反轉,空間複雜度 O(1)。
核心算法:雙指針交換法
#include <stdio.h>
#include <string.h>
void reverse_string(char *str) {
if (!str) return;
char *left = str;
char *right = str + strlen(str) - 1; // 指向最後一個有效字符
while (left < right) {
char temp = *left;
*left = *right;
*right = temp;
left++;
right--;
}
}
int main() {
char str[100];
printf("請輸入字符串: ");
fgets(str, sizeof(str), stdin);
// 移除 fgets 讀入的換行符
str[strcspn(str, "\n")] = '\0';
printf("原字符串: %s\n", str);
reverse_string(str);
printf("逆序後: %s\n", str);
return 0;
}
執行過程圖解
輸入: "hello"
索引: 0 1 2 3 4
字符: h e l l o
↑ ↑
left right
第1輪: 交換 h↔o → "oellh" left→e right→l
第2輪: 交換 e↔l → "olleh" left→l right→l (相遇停止)
結果: "olleh"
關鍵技術點
| 技術點 | 說明 | 注意事項 |
| strlen(str) | 獲取字符串長度(不含 \0) | 每次調用 O(n),循環外緩存更優 |
| str + len - 1 | 指針算術,定位末尾字符 | 空字符串需特判,避免指向 -1 |
| left < right | 指針比較,中間相遇停止 | 奇數長度中間字符無需交換 |
| 就地修改 | 無額外內存分配 | 原數組必須可寫,不能是字符串常量 |
進階版本:支持 Unicode/多字節字符
// 簡易 UTF-8 逆序(僅演示思路,生產環境用 ICU 庫)
void reverse_utf8(char *str) {
// 實際需解碼 Unicode 碼點數組,逆序後重新編碼
// 此處略過,強調:字節級逆序會破壞多字節字符
}
常見錯誤與修正
| 錯誤代碼 | 問題 | 修正 |
| for(i=0; i<len/2; i++) swap(str[i], str[len-i]) | 索引越界:str[len] 是 \0 | str[len-1-i] |
| char *s = "hello"; reverse(s); | 字符串常量不可修改 | 用 char s[] = "hello"; |
| while(*left++ = *right--) | 賦值而非交換,邏輯錯誤 | 用 temp 變量三步交換 |
標準庫替代方案
// C++ 風格(若編譯器支持)
#include <algorithm>
#include <string>
std::reverse(str, str + strlen(str));
// 手寫通用版(可用於任意類型數組)
void reverse_generic(void *base, size_t nmemb, size_t size) {
char *left = (char*)base;
char *right = left + (nmemb - 1) * size;
char *temp = malloc(size);
while (left < right) {
memcpy(temp, left, size);
memcpy(left, right, size);
memcpy(right, temp, size);
left += size;
right -= size;
}
free(temp);
}
- 上一篇文章: C語言學習極簡法則:多看、多寫、多做、多編程
- 下一篇文章: C語言與 C++ 關係深度解析:從學習順序到經典教材推薦
Copyright ©
程式碼之家 All Rights Reserved