2009-11-02 13 views
11

Beendet fgets() den Zeichenpuffer immer mit \ 0, auch wenn EOF bereits erreicht ist? Es sieht so aus als ob es (tut es sicherlich in der im ANSI K & R Buch präsentierten Implementierung), aber ich dachte, ich würde fragen, um sicher zu sein.Beendet fgets() den Zeichenpuffer immer mit 0?

Ich denke, diese Frage gilt für andere ähnliche Funktionen wie gets().

EDIT: Ich weiß, dass \ 0 ist bei "normalen" Umständen angefügt, meine Frage zielt auf EOF oder Fehlerbedingungen. Zum Beispiel:

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

immer den Rückgabewert von 'fgets überprüfen()': 'if (fgets (...) == NULL)/* unbestimmtem Array * /;' – pmg

+0

können Sie richtig sein, aber, Ich sehe, dass es andere Antworten gibt, die angeben, dass "\ 0" immer angehängt wird, selbst wenn 'fgets()' 'NULL' zurückgibt. – Ree

Antwort

6

Niemals benutzen wird !!

 
    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. 

So ja, wenn fgets() nicht NULL das Ziel-Array zurückgibt hat immer ein Null-Zeichen.

Wenn fgets() NULL zurückgibt, wurde das Zielarray möglicherweise geändert und darf kein Nullzeichen enthalten. Verlassen Sie sich niemals auf das Array, nachdem Sie NULL von fgets() erhalten haben.


bearbeiten Beispiel hinzugefügt

 
$ 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] 
$ 

sehen?nein NUL in buf :)

+0

Sie gewinnen: D .... – Ree

+0

@pmg re "Nie benutzt wird, !!", haben Sie eine Alternative zum Lesen von Dateien? – atlex2

+1

@ atlex2: Ja, die Alternative ist 'fgets()'. – pmg

0

Ja, tut es. Von CPlusPlus.com

Lesen Zeichen aus dem Stream und speichert sie als C-String in str bis (num-1) Zeichen gelesen wurden oder entweder eine Neue-Zeile oder eine der End-of-Datei erreicht ist, je nachdem, was zuerst eintritt.

Ein Newline-Zeichen bewirkt, dass Fgets den Lesevorgang beenden, aber es wird als gültiges Zeichen betrachtet und daher in der in str kopierten Zeichenfolge enthalten.

Ein Nullzeichen wird automatisch in str angehängt, nachdem die Zeichen gelesen wurden, um das Ende der C-Zeichenfolge zu signalisieren.

7

fgets fügt immer ein ‚\ 0‘ an den Lesepuffer, liest höchstens size - 1 Zeichen aus dem Strom aus diesem (size der zweite Parameter ist).

Verwenden Sie nie gets, da Sie nie garantieren können, dass es keinen Puffer überläuft, den Sie es geben, so, während es technisch immer die gelesene Zeichenkette beendet, hilft das eigentlich nicht wirklich.

2

Mann fgets:

fgets() liest höchstens eine Größe von weniger als Zeichen aus dem Strom und speichert sie in den Pufferspeicher, auf die durch s in. Das Lesen stoppt nach einem EOF oder einem Zeilenumbruch. Wenn eine neue Zeile gelesen wird, wird sie im Puffer gespeichert. A '\ 0' wird nach dem letzten Zeichen im Puffer gespeichert.

0

Wenn Sie die Datei im binären Modus "rb" geöffnet haben, und wenn Sie Text zeilenweise mit fgets lesen möchten, können Sie den folgenden Code verwenden, um Ihre Software vor Textverlust zu schützen. wenn der Text versehentlich ein '\ 0' Byte enthielt. Aber schließlich wie die anderen erwähnt, normalerweise sollten Sie fgets nicht verwenden, wenn der Stream '\ 0' enthält.


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'; 
    } 
}