簡體   English   中英

到達文件結尾后,fgetc 是否在每次調用時都返回 EOF?

[英]Does fgetc return EOF on every call after end-of-file reached?

給定以下 C 代碼:

int eofCount = 0;
while (true) {
    int c = fgetc(stdin); 
    if (c == EOF) eofCount++;
}

eofCount 會大於 1 嗎?

我在 C 文檔中找不到任何描述在達到 EOF 后 fgetc 會發生什么的任何內容。 我知道我可以自己做這個簿記,但是如果 stdlib 為我做這件事就太好了。

我不是在尋找代碼片段,因為我已經用 glibc 嘗試過這個,實際上 eofCount 增加了超過 EOF。 我想要 stdlib 源代碼參考或規范,以確認這是定義的行為。 依賴未定義的行為可能會導致未來出現問題。

只要您不是從交互式 Linux 終端讀取(即您不從其他文件/進程打開文件或管道 stdin),一旦您讀取 EOF,所有未來的讀取也將讀取 EOF。

如果您從 Linux 終端讀取,按下 EOF 的按鍵序列(Linux 上的 CTRL-D)將讀取為 EOF,但您仍然可以輸入更多字符並讀取它們。

來自C 標准的第 7.21.7.1 節:

3如果設置了流的文件結尾指示符,或者如果流位於文件結尾,則設置流的文件結尾指示符並且fgetc函數返回EOF 否則, fgetc函數返回 stream 指向的輸入流中的下一個字符。 如果發生讀取錯誤,則設置流的錯誤指示符並且fgetc函數返回EOF

到達文件結尾后,fgetc 是否在每次調用時都返回 EOF?

它取決於 2 個指標和 I/O 函數調用。


雖然 OP 沒有提到,但fgetc(stdin);有兩個原因fgetc(stdin); 返回EOF以及它們如何影響后續fgetc()調用是不對稱的。 此外,使用各種 I/O 函數會影響 2 個指標,而這些指標又會影響后續的fgetc()調用

文件結束。
輸入錯誤。


C 規范在導致后續EOF文件結束指示符上是明確的。

如果 stream 指向的輸入流的文件結束指示符未設置並且存在下一個字符,則 fgetc 函數獲取該字符... C11 §7.21.7.1 2

當文件結束發生或已經發生時,會設置一個持久標志:文件結束指示符,因此對fgetc()后續調用將返回EOF

如果設置了流的文件尾指示符,或者如果流位於文件尾,則設置流的文件尾指示符並且fgetc函數返回EOF ... §7.21。 7.1 3


當發生罕見的輸入錯誤時, fgetc()返回EOF ,但該事件不會設置文件結束指示符,但會設置錯誤指示符 即使設置了錯誤指示符,后續調用也不一定返回EOF IMO,C 規范在這一點上不夠明確。

如果發生讀取錯誤,則設置流的錯誤指示符並且fgetc函數返回EOF §7.21.7.1 3


feof()ferror()的調用可用於區分導致EOF ,但也可以反映先前的 I/O 活動。 因此,好的代碼會在返回EOF后立即檢查這些函數,並在發生后續 I/O 時清除它們。


文件結束指示符錯誤指示符可以用void clearerr(FILE *stream);清除void clearerr(FILE *stream);

rewind()函數清除錯誤指示器

ungetc()將清除文件結束指示符

其他 I/O 功能也會影響這些指標。


如果導致第一個EOF的條件被移除並且相應的指示符被清除,則對fgetc()后續調用可能不會返回EOF

是的,計數將大於 1,因為您有一個無限的while循環。 您會發現http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdfhttp://pubs.opengroup.org/onlinepubs/9699919799/很有用。

嘗試這個:

#include <stdio.h>
#include <stdbool.h>

int main() {
    int eofCount = 0;
    /*while (true) {*/

    int c = fgetc(stdin); 
    if (c == EOF) eofCount++;
        c = fgetc(stdin); 
    if (c == EOF) eofCount++;
        c = fgetc(stdin); 
    if (c == EOF) eofCount++;

    /*}*/

printf("%d\n", eofCount);
return 0;

}

編譯運行。 在 Linux 上按 ctrl+D 兩次,然后輸入。 你會得到2。

這是用gcc -ansi -Wall -Werror -pedantic test.c編譯的,因此它滿足 ANSI 即 C89 標准。

暫無
暫無

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

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