2009-11-02 24 views
11

即使EOF已經達到,fgets()是否總是用\ 0終止char緩衝區?它看起來像它(它確實在ANSI K & R書中提供的實現中),但我想我會要求確定。fgets()總是以 0結束char緩衝區嗎?

我想這個問題適用於其他類似的函數,如gets()。

編輯:我知道,\ 0是在「正常」的情況下追加,我的問題是針對EOF或錯誤的條件。例如:

FILE *fp; 
char b[128]; 
/* ... */ 
if (feof(fp)) { 
    /* is \0 appended after EACH of these calls? */ 
    fgets(b, 128, fp); 
    fgets(b, 128, fp); 
    fgets(b, 128, fp); 
} 
+1

經常檢查'與fgets的返回值()':'如果(與fgets(...)== NULL)/ *不確定的數組* /;' – pmg 2009-11-02 10:15:43

+0

你可能是正確的,但是,我發現還有其他答案指出總是附加'\ 0',即使'fgets()'返回NULL。 – Ree 2009-11-02 10:26:06

回答

6

永遠不要使用獲取!

 
    7.19.7.2 The fgets function 
    Synopsis 
1   #include <stdio.h> 
      char *fgets(char * restrict s, int n, 
       FILE * restrict stream); 
    Description 
2 The fgets function reads at most one less than the number of characters 
    specified by n from the stream pointed to by stream into the array pointed 
    to by s. No additional characters are read after a new-line character 
    (which is retained) or after end-of-file. A null character is written 
    immediately after the last character read into the array. 
    Returns 
3 The fgets function returns s if successful. If end-of-file is encountered 
    and no characters have been read into the array, the contents of the array 
    remain unchanged and a null pointer is returned. If a read error occurs 
    during the operation, the array contents are indeterminate and a null 
    pointer is returned. 

所以,,當fgets()不返回NULL目標數組總是有一個空字符。

如果fgets()返回NULL,則目標數組可能已被更改並且可能沒有空字符。在從fgets()獲得NULL之後,千萬不要依賴數組。


編輯例如添加

 
$ cat fgets_error.c 
#include <stdio.h> 

void print_buf(char *buf, size_t len) { 
    int k; 
    printf("%02X", buf[0]); 
    for (k=1; k<len; k++) printf(" %02X", buf[k]); 
} 

int main(void) { 
    char buf[3] = {1, 1, 1}; 
    char *r; 

    printf("Enter CTRL+D: "); 
    fflush(stdout); 
    r = fgets(buf, sizeof buf, stdin); 
    printf("\nfgets returned %p, buf has [", (void*)r); 
    print_buf(buf, sizeof buf); 
    printf("]\n"); 

    return 0; 
} 
$ ./a.out 
Enter CTRL+D: 
fgets returned (nil), buf has [01 01 01] 
$ 

看到了嗎?沒有NUL buf :)

+0

You win:D .... – Ree 2009-11-02 11:13:58

+0

@pmg re「永遠不要使用gets !!」,你有替代文件閱讀嗎? – atlex2 2015-10-19 17:07:11

+1

@ atlex2:是的,替代方法是'fgets()'。 – pmg 2015-10-19 17:42:51

0

是的。從CPlusPlus.com

從流中讀取字符和將它們存儲爲C字符串到STR直到已經讀取或達到任一換行或所述檔案結尾(NUM-1)的字符,以先到者爲準。

換行符使fgets停止讀取,但它被認爲是有效字符,因此它被包含在複製到str的字符串中。

在讀取字符以表示C字符串結束後,空字符會自動附加到str中。

7

fgets並不總是一個「\ 0」添加到讀緩衝器,它從流讀取最多size - 1字符(size是第二參數)因爲這個原因。

永遠不要使用gets,因爲你永遠不能保證它不會溢出你給它的任何緩衝區,所以雖然它在技術上總是終止讀取字符串,但實際上並沒有幫助。

2

人與fgets:

與fgets()至多一個小於從流大小的字符,並將它們存儲到緩衝器中讀出由s指向。讀取在EOF或換行符後停止。如果讀取新行,則將其存儲到緩衝區中。 '\ 0'存儲在緩衝區中的最後一個字符之後。

0

如果你打開了二進制模式「rb」的文件,並且如果你想通過使用fgets逐行讀取文本,你可以使用下面的代碼來保護你的軟件丟失文本,如果錯誤,文本包含'\ 0'字節。 但終於像其他人提到的那樣,如果流包含'\ 0',通常不應該使用fgets


size_t filepos=ftell(stream); 
fgets(buffer, buffersize, stream); 
len=strlen(buffer); 
/* now check for > len+1 since no problem if the 
    last byte is 0 */ 
if(ftell(stream)-filepos > len+1) 
{ 
    if(!len) filepos++; 
    if(!fseek(stream, filepos, SEEK_SET) && len) 
    { 
     fread(buffer, 1, len, stream); 
     buffer[len]='\0'; 
    } 
}