2009-11-02 23 views
11

¿Fgets() siempre termina el búfer de caracteres con \ 0 incluso si ya se alcanzó EOF? Parece que sí (ciertamente lo hace en la implementación presentada en el libro ANSI K & R), pero pensé que podría preguntar para estar seguro.¿Fgets() siempre termina el búfer de caracteres con 0?

Supongo que esta pregunta se aplica a otras funciones similares, como gets().

EDIT: Sé que \ 0 se agrega durante circunstancias "normales", mi pregunta está dirigida a EOF o condiciones de error. Por ejemplo:

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

Compruebe siempre el valor de retorno de 'fgets()': 'Si (fgets (...) == NULL)/* variedad indeterminada * /;' – pmg

+0

Puede que tengas razón, sin embargo, Veo que hay otras respuestas que indican que '\ 0' siempre se adjunta, incluso si' fgets() 'devuelve' NULL'. – Ree

Respuesta

6

Never use gets !!

 
    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. 

Así, , cuando fgets() no devuelve NULL la matriz de destino siempre tiene un carácter nulo.

Si fgets() devuelve NULL, es posible que se haya cambiado la matriz de destino y que no tenga un carácter nulo. Nunca confíe en la matriz después de obtener NULL en fgets().


Edición ejemplo añadió

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

Ver?no NUL en buf :)

+0

Usted gana: D .... – Ree

+0

@pmg re "¡Nunca use se obtiene!", ¿Tiene alguna alternativa para la lectura de archivos? – atlex2

+1

@ atlex2: sí, la alternativa es 'fgets()'. – pmg

0

Sí lo hace. De CPlusPlus.com

lee los caracteres de la corriente y los almacena como una cadena C en str hasta personajes (num-1) han sido leídos o se alcance o bien un salto de línea o de un Archivo de fin de, lo que suceda primero.

Un carácter de nueva línea hace que los datos dejen de leer, pero se considera un carácter válido y, por lo tanto, se incluye en la cadena copiada en str.

Un carácter nulo se agrega automáticamente en str después de que los caracteres se leen para señalar el final de la cadena en C.

7

fgets qué siempre añadir un '\ 0' para el búfer de lectura, se lee en la mayoría size - 1 caracteres de la corriente (size siendo el segundo parámetro) debido a esto.

Nunca use gets ya que nunca puede garantizar que no se desbordará ningún búfer que le dé, por lo que, aunque técnicamente siempre termina la cadena de lectura, esto en realidad no ayuda.

2

hombre fgets:

fgets() lee como mucho uno menos de tam caracteres del flujo y los guarda en la memoria intermedia apuntada por s. La lectura se detiene después de un EOF o una nueva línea. Si se lee una nueva línea, se almacena en el búfer. A '\ 0' se almacena después del último carácter en el búfer.

0

Si abriste el archivo en modo binario "rb", y si quieres leer el texto línea por línea usando fgets puedes usar el siguiente código para proteger tu software de perder texto, si por error el texto contenía un byte '\ 0'. Pero finalmente como los otros mencionados, normalmente no debería usar fgets si la secuencia contiene '\ 0'.


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