2012-09-13 110 views
0

可能重複:
fgetc does not identify EOF
fgetc, checking EOFEOF缺少UNIX文件

我已經在Unix中創建的文件,並把它命名爲 「file.txt的」。我試圖從我的C程序中讀取文件內容。我無法收到EOF字符。 Unix不會在創建文件時存儲EOF字符?如果是的話是什麼讀取使用C.

這裏從一個Unix創建的文件的EOF的另一種方法是代碼示例

int main(){ 
File *fp; 
int nl,c; 
nl =0; 
fp = fopen("file.txt", "r"); 
while((c = fgetc(fp)) != EOF){ 
    if (c=='\n') 
    nl++; 
} 
return 0; 
} 

如果我明確給出即使檢測到EOF CTRL + d當我使用char c

+2

[fgetc無法識別EOF]的可能重複(http://stackoverflow.com/questions/3977223/fgetc-does-not-identify-eof),另請參閱http://stackoverflow.com/questions/11057259/fgetc-checking-eof以及其他很多 – Mat

+1

另請注意:EOF不是「存儲在文件中」,它只是I/O函數告訴你它們到達文件結尾的一種方式。末尾沒有存儲魔術字節。 – Mat

+2

請注意它應該是'FILE * fp;'而不是'File * fp;',並且您還應該在通過變量'fp'讀取任何內容之前檢查文件是否已成功打開。 –

回答

4

可能發生這種情況如果c類型是char而不是int(和char是在你的編譯器簽名,你可以通過檢查CHAR_MIN在值檢查)。

根據C標準,EOF的值爲負值。

因此,隱式鑄造EOFunsigned char將失去真實值EOF並且比較總是失敗。

UPDATE:有一個更大的問題必須先解決。在表達式c = fgetc(fp) != EOF中,首先評估fgetc(fp) != EOF(至0或1),然後將值分配給c。如果文件中至少有一個字符,則fgetc(fp) != EOF將評估爲0,並且while循環的主體將永遠不會執行。您需要添加括號,如下所示:(c = fgetc(fp)) != EOF

0

您不顯示如何聲明變量c它應該是int類型,而不是char

3

缺少括號。應該是:

while((c = fgetc(fp)) != EOF) 
+0

:)不幸的是,這不.. –

+0

這可以防止代碼編譯 - 但不解釋運行時錯誤。它還告訴我們,問題中的代碼不是編譯的代碼,這總是會使調試更加困難。 –

+0

這將如何防止代碼編譯?將不等式運算符的結果值賦給標量變量是完全有效的C. –

1

記住:fgetc()返回int,而不是char。它必須返回一個int,因爲它的一組返回值包含所有可能的有效字符和一個單獨的(負)EOF指示符。

有兩種可能的陷阱,如果你使用類型爲charc代替int

  1. 如果類型char與您簽訂的編譯器,你會發現一個有效的字符爲EOF。通常,在ISO 8859-1(又名拉丁語1代碼集)中,字符ÿ(y-umlaut,在Unicode中被正式稱爲LATIN LOWER CASE Y WITH DIAERESIS,U + 00FF,十六進制代碼0xFF)將被檢測爲等同於EOF,這是一個有效的角色。

  2. 如果類型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)。