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

換行符大揭密:Windows (\r\n) vs Linux (\n) 相容性完全指南

     編輯:關於C語言

前言:看不見的字元,看得見的災難

跨平台開發最讓人頭痛的細節之一,就是換行符不一致。Windows 用 \r\n (CRLF),Linux/Unix/macOS 用 \n (LF),舊版 Mac OS 9 用 \r (CR)。這導致 Git diff 雜訊、編譯警告、腳本執行失敗、協議解析錯誤等無數問題。本文徹底釐清來龍去脈與解決之道。

ASCII 碼對照表

歷史淵源:打字機機械結構

  • CR (\r):捲筒歸位到行首
  • LF (\n):捲筒向上捲一行
  • 早期電傳打字機需要兩個動作才能換新行
  • Windows (DOS 繼承 CP/M) 保留雙字元 \r\n
  • Unix 簡化為單一 \n 同時代表「歸位+換行」

平台行為差異對照

符號名稱ASCII (Hex)十進位功能
\nLine Feed (LF)0x0A10換行
\rCarriage Return (CR)0x0D13歸位 (游標移至行首)
平台鍵盤 Enter 產生文字檔儲存C 語言 \n 行為Notepad 顯示
Windows\r\n\r\n (0x0D 0x0A)輸出 \n → 實際寫入 \r\n需 \r\n 才換行
Linux/Unix\n\n (0x0A)輸出 \n → 寫入 \nN/A
macOS (現代)\n\n (0x0A)輸出 \n → 寫入 \nN/A

經典陷阱:\r 覆蓋輸出

#include <stdio.h>
int main() {
    char a[10] = "abc\r";
    printf(a);  // 無任何輸出!
    return 0;
}

原因:\r 將游標移回行首,後續輸出覆蓋 "abc"。若接著 printf("def"),螢幕顯示 "def"。

C 語言標準庫的自動轉換機制

  • 文字模式 (text mode):fopen("file.txt", "r") / "w"
    • Windows:讀取時 \r\n → \n;寫入時 \n → \r\n
    • Linux:無轉換
  • 二進位模式 (binary mode):fopen("file.bin", "rb") / "wb"
    • 所有平台:零轉換,位元組原樣讀寫

建議:處理文字檔用文字模式,處理二進位檔 (圖片、壓縮檔、協議封包) 必須用二進位模式。

跨平台開發最佳實踐

1. Git 設定:統一倉庫內為 LF

# .gitattributes (專案根目錄)
* text=auto eol=lf

# 或全域設定
git config --global core.autocrlf input  # 提交時轉 LF,簽出不轉

2. 編輯器設定

  • VS Code:右下角 CRLF/LF 切換,設定 "files.eol": "\n"
  • Vim::set fileformat=unix
  • Notepad++:編輯 → 文件格式轉換 → Unix (LF)

3. 程式碼層面處理

// 讀取整行並移除尾部換行符 (跨平台安全)
void read_line(FILE *fp, char *buf, size_t size) {
    if (fgets(buf, size, fp)) {
        size_t len = strlen(buf);
        while (len > 0 && (buf[len-1] == '\n' || buf[len-1] == '\r')) {
            buf[--len] = '\0';
        }
    }
}

// 通用字串分割:支援 \n, \r\n, \r
char **split_lines(const char *text, int *count) {
    // 以 \r 或 \n 為分隔符,忽略空行...
}

4. 網路協議 (HTTP, SMTP, IRC 等)

RFC 規定必須使用 \r\n (CRLF) 作為行終結符,無論平台。發送時請硬編碼 "\r\n" 或使用常數 CRLF。

常見工具轉換指令

工具CRLF → LFLF → CRLF
dos2unix / unix2dosdos2unix file.txtunix2dos file.txt
sedsed -i 's/\r$//' filesed -i 's/$/\r/' file
trtr -d '\r' < in > outawk '{print $0 "\r"}' < in > out
Pythonopen('in', newline='').read()open('out', 'w', newline='\r\n')

結語

換行符雖小,折騰不少。核心原則三點:**倉庫統一 LF、編輯器配合、二進位檔案禁用文字模式**。理解歷史背景與平台差異,才能在跨平台協作中從容應對,不再為「多一個 \r」或「少一個 \n」煩惱。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved