簡體   English   中英

fgets 回車

[英]carriage return by fgets

我正在運行以下代碼:

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

int main(){
    FILE *fp;
    if((fp=fopen("test.txt","r"))==NULL){
        printf("File can't be read\n");
        exit(1);
    }
    char str[50];
    fgets(str,50,fp);
    printf("%s",str);
    return 0;
}

text.txt 包含: I am a boy\\r\\n

由於我在 Windows 上,它需要 \\r\\n 作為換行符,所以如果我從文件中讀取它應該在str存儲"I am a boy\\n\\0" ,但我得到"I am a boy\\r\\n" 我正在使用 mingw 編譯器。

該行為取決於 c 庫實現以及您傳遞給fopen模式。 請參閱有關fopen的 MSDN 文檔中的引用(MSDN 上的fopen

b - 以二進制(未翻譯)模式打開; 禁止涉及回車和換行符的翻譯。

意思是,如果您使用 Microsoft c 庫,並打開省略 'b' 的文件,則回車字符將從流中刪除。

由於您使用的是 mingw,您的編譯器可能會鏈接到遵循 POSIX 標准的 GNU c 庫。 這是 GNU 文檔關於fopen (gnu.org 上的 fopen)的說明

opentype 中的字符 'b' 具有標准含義; 它請求二進制流而不是文本流。 但這在 POSIX 系統(包括 GNU 系統)中沒有區別。

結論:您省略了 'b' 模式字符,它以文本模式打開您的流。 您在 Windows 上,但使用 GNU c 庫,它在文本和二進制模式之間沒有區別。 這就是fgets讀取回車和換行的原因。

由於我在 Windows 上,它需要 \\r\\n 作為換行符......

這個假設是錯誤的。 C 標准將回車和換行視為兩種不同的事物,如 C99 §5.2.1/3(字符集)所示:

[...] 在基本執行字符集中,應該有代表警告、退格、回車和換行的控制字符。 [...]

fgets函數描述如下,在 C99 §7.19.7.2/2 中:

fgets 函數從 stream 指向的流中讀取至多比 n 指定的字符數少 1 到 s 指向的數組中。 在換行符(保留)后或文件結束不會讀取其他字符 在讀入數組的最后一個字符后立即寫入空字符。

因此,當遇到字符串I am a boy\\r\\n ,符合要求的實現應該讀到\\n字符。 實現應該基於平台丟棄\\r沒有可能合理的理由。

c 標准對以下內容中的文本流進行了說明(除其他外):

可能必須在輸入和輸出中添加、更改或刪除字符,以符合在宿主環境中表示文本的不同約定。 因此,流中的字符與外部表示中的字符之間不需要一一對應。 僅在以下情況下,從文本流中讀取的數據將必然與之前寫入該流的數據相等: 數據僅由打印字符和控制字符水平制表符和換行符組成; 沒有新行字符緊跟在空格字符之前; 最后一個字符是換行符。

換句話說,如果文件以文本模式打開,則實現可以自由地添加、刪除和修改控制字符,如果它在往返磁盤時需要/需要。 這顯然是微軟實現對回車所做的,但 gnu 實現沒有。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM