記住:fgetc()
返回int
,而不是char
。它必須返回一個int
,因爲它的一組返回值包含所有可能的有效字符和一個單獨的(負)EOF指示符。
有兩種可能的陷阱,如果你使用類型爲char
的c
代替int
:
如果類型char
與您簽訂的編譯器,你會發現一個有效的字符爲EOF。通常,在ISO 8859-1(又名拉丁語1代碼集)中,字符ÿ(y-umlaut,在Unicode中被正式稱爲LATIN LOWER CASE Y WITH DIAERESIS,U + 00FF,十六進制代碼0xFF)將被檢測爲等同於EOF,這是一個有效的角色。
如果類型char
是無符號的,那麼比較永遠不會是真的。
這兩個問題是嚴重的,無一不是通過使用正確的類型迴避:
FILE *fp = fopen("file.txt", "r");
if (fp != 0)
{
int c;
int nl = 0;
while ((c = fgetc(fp)) != EOF)
if (c == '\n')
nl++;
printf("Number of lines: %d\n", nl);
}
注意該類型是FILE
而不是File
。請注意,在嘗試通過fp
閱讀之前,您應該檢查文件是否已打開。
如果我明確給予CTRL + d,當我使用char c
即使檢測到EOF。
這意味着您的編譯器爲您提供了char
作爲簽名類型。這也意味着您將無法在包含ÿ的文件中準確地計算行數。
與CP/M和DOS不同,Unix不使用任何字符來表示EOF;當沒有更多字符可讀時,您到達EOF。令許多人感到困惑的是,如果您在終端鍵入某個組合鍵,程序會檢測到EOF。實際發生的事情是,終端驅動程序識別該字符並將任何未讀字符發送到該程序。如果沒有未讀字符,程序會返回0字節,這與您到達文件結尾時的結果相同。因此,字符組合(通常,但並非總是,Ctrl-D)似乎將'EOF'發送給程序。但是,如果您使用的是cat >file
,則不會將該字符存儲在文件中;此外,如果您讀取包含control-D的文件,則該文件是字符值爲0x04的完美字符。如果一個程序生成一個control-D並將它發送給一個程序,那麼這並不表示程序的EOF。它完全是Unix終端的一種屬性(tty和pty - teletype和pseudo-teletype - devices)。
[fgetc無法識別EOF]的可能重複(http://stackoverflow.com/questions/3977223/fgetc-does-not-identify-eof),另請參閱http://stackoverflow.com/questions/11057259/fgetc-checking-eof以及其他很多 – Mat
另請注意:EOF不是「存儲在文件中」,它只是I/O函數告訴你它們到達文件結尾的一種方式。末尾沒有存儲魔術字節。 – Mat
請注意它應該是'FILE * fp;'而不是'File * fp;',並且您還應該在通過變量'fp'讀取任何內容之前檢查文件是否已成功打開。 –