首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言字串反轉:多行文字逐行逆序輸出實作詳解

     編輯:關於C語言

字串反轉是陣列操作基礎訓練,本文實作讀取多行文字並逐行反轉輸出的 C 程式,深入解析輸入緩衝區處理、字串長度計算、原地反轉與輸出反轉兩種策略差異。

完整程式碼實作

#include <stdio.h>
#include <string.h>

#define MAX_LINE 1000

int main() {
    int n;
    char line[MAX_LINE];
    
    scanf("%d", &n);
    getchar();  // 吸收換行符
    
    while (n--) {
        if (fgets(line, sizeof(line), stdin) == NULL) break;
        
        // 移除 fgets 保留的換行符
        size_t len = strlen(line);
        if (len > 0 && line[len-1] == '\n') {
            line[len-1] = '\0';
            len--;
        }
        
        // 反序輸出
        for (size_t i = len; i-- > 0; ) {
            putchar(line[i]);
        }
        
        if (n > 0) putchar('\n');
    }
    return 0;
}

關鍵技術細節

輸入緩衝區處理

  • scanf("%d", &n) 留下換行符在緩衝區
  • getchar() 單獨吸收該換行符
  • fgets() 讀取整行含換行符,需手動移除

迴圈邊界寫法比較

// 寫法 1:size_t 無號型別陷阱
for (size_t i = len; i > 0; i--)  // 錯誤:i=0 時 i-- 變巨大值

// 寫法 2:正確遞減 (C99)
for (size_t i = len; i-- > 0; )

// 寫法 3:使用有號整數
for (int i = (int)len - 1; i >= 0; i--)

// 寫法 4:指標算術
for (char *p = line + len - 1; p >= line; p--)

原地反轉 vs 輸出反轉

原地反轉實作


void reverse_inplace(char *str) {
    char *left = str;
    char *right = str + strlen(str) - 1;
    while (left < right) {
        char tmp = *left;
        *left++ = *right;
        *right-- = tmp;
    }
}

進階功能擴充

單字反轉 (保持單字順序)


void reverse_words(char *str) {
    char *start = str;
    while (*str) {
        if (*str == ' ') {
            reverse_range(start, str - 1);
            start = str + 1;
        }
        str++;
    }
    reverse_range(start, str - 1);  // 最後一個單字
    reverse_range(str - strlen(str), str - 1);  // 整行反轉
}

Unicode/多位元組字元支援

ASCII 字串反轉直接對位元組操作即可。UTF-8 需解碼為 code point 陣列再反轉,否則會破壞多位元組字元結構。

大檔案行反轉


// 記憶體映射大檔案反轉
#include <sys/mman.h>
#include <fcntl.h>

void reverse_file_lines(const char *filename) {
    int fd = open(filename, O_RDWR);
    struct stat st; fstat(fd, &st);
    char *data = mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    // 找出所有行邊界,兩兩交換...
}
字串反轉程式執行示意多行輸入反轉結果

常見錯誤與最佳實踐

  1. 緩衝區溢位:固定 MAX_LINE 可能不足,動態分配或 getline() (POSIX) 更安全
  2. 空行處理:len=0 時迴圈不執行,直接輸出空行正確
  3. 換行符殘留:fgets 保留 \n,必須移除否則反轉會跑到行首
  4. Windows CRLF:讀取 \r\n 需同時移除 \r

標準庫替代方案


// C++ 標準庫一行解決
#include <algorithm>
#include <string>
std::reverse(str.begin(), str.end());

// C strrev (非標準,MSVC 提供)
char *strrev(char *str);  // 原地反轉並回傳指標

效能分析

  • 時間複雜度:O(n) 每行長度
  • 空間複雜度:O(1) 輸出反轉 / O(n) 原地反轉
  • 快取友好:循序存取,分支預測簡單
  • 向量化潛力:編譯器可自動 SIMD 化原地交換迴圈

字串反轉雖屬基礎操作,但涵蓋緩衝區管理、指標算術、無號整數陷阱、編碼認知等關鍵 C 語言核心概念。掌握多種實作策略與邊界處理,是建立紮實系統程式設計功力的重要一環。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
策略程式碼優點缺點
輸出反轉直接逆序 putchar無額外記憶體、保留原字串無法後續處理反轉結果
原地反轉雙指標交換結果可重複使用修改原資料、需可寫緩衝區