¿Feof() comprueba eof para la posición actual de filepointer o comprueba la posición junto al actual filepointer?¿Cómo funciona feof() en C
Gracias por su ayuda!
¿Feof() comprueba eof para la posición actual de filepointer o comprueba la posición junto al actual filepointer?¿Cómo funciona feof() en C
Gracias por su ayuda!
Cada secuencia FILE
tiene una marca interna que indica si la persona que llama ha intentado leer más allá del final del archivo. feof
devuelve esa bandera. El indicador no indica si la posición actual del archivo es como el final del archivo, solo si una lectura previa ha intentado leer más allá del final del archivo.
Como ejemplo, veamos lo que sucede cuando leemos un archivo que contiene dos bytes.
f = fopen(filename, "r"); // file is opened
assert(!feof(f)); // eof flag is not set
c1 = getc(f); // read first byte, one byte remaining
assert(!feof(f)); // eof flag is not set
c2 = getc(f); // read second byte, no bytes remaining
assert(!feof(f)); // eof flag is not set
c3 = getc(f); // try to read past end of the file
assert(feof(f)); // now, eof flag is set
Esta es la razón por la que sigue es la mal manera de utilizar EF cuando se lee a través de un archivo:
f = fopen(filename, "r");
while (!feof(f)) {
c = getc(f);
putchar(c);
}
debido a la forma feof
obras, el indicador de fin de archivo es de sólo establecer una vez getc
intenta leer más allá del final del archivo. getc
devolverá EOF
, que es , no un carácter, y la construcción del bucle hace que putchar
intente escribirlo , lo que da como resultado un error o una salida de basura.
método de entrada de la biblioteca estándar C Cada devuelve una indicación de éxito o fracaso : getc
devuelve el valor especial EOF
si se trató de leer más allá del final del archivo , o si hubo un error durante la lectura. El valor especial es , el mismo para fin de archivo y error, y aquí es donde entra la forma correcta de usar feof
: puede usarlo para distinguir entre situaciones de fin de archivo y error .
f = fopen(filename, "r");
c = getc(f);
if (c == EOF) {
if (feof(f))
printf("it was end-of-file\n");
else
printf("it was error\n");
}
Hay otro indicador interno para FILE
objetos para situaciones de error: ferror
. A menudo es más claro probar los errores en lugar de "no al final del archivo". Una forma idiomática para leer un archivo en C es la siguiente:
f = fopen(filename, "r");
while ((c = getc(f)) != EOF) {
putchar(c);
}
if (ferror(f)) {
perror(filename):
exit(EXIT_FAILURE);
}
fclose(f);
(comprobación de errores se ha eludido a partir de ejemplos aquí, por razones de brevedad.)
La función feof
es bastante rara vez son útiles.
Puede obtener una mejor comprensión de cómo funciona feof
, al saber cómo se implementa. Aquí hay una versión simplificada de cómo la biblioteca de 7th Edition Unix stdio implementa feof
. Las bibliotecas modernas son muy similares, agregando código que ofrece seguridad de subprocesos, mayor eficacia y una implementación más limpia.
extern struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
char _flag;
char _file;
} _iob[_NFILE];
#define _IOEOF 020
#define feof(p) (((p)->_flag&_IOEOF)!=0)
#define getc(p) (--(p)->_cnt>=0? *(p)->_ptr++&0377:_filbuf(p))
int
_filbuf(FILE *iop)
{
iop->_ptr = iop->_base;
iop->_cnt = read(fileno(iop), iop->_ptr, BUFSIZ);
if (iop->_cnt == 0) {
iop->_flag |= _IOEOF;
return(EOF);
}
return(*iop->_ptr++ & 0377);
}
La biblioteca stdio mantiene con cada archivo de una estructura que contiene un buffer interno señalado por _base
.El carácter actual en el búfer está apuntado por _ptr
y la cantidad de caracteres disponibles está en _cnt
. La macro getc
, que es la base de una gran cantidad de funcionalidades de nivel superior, como scanf
, intenta devolver un carácter desde el búfer. Si el buffer está vacío, llamará al _filbuf
para llenarlo. _filbuf
a su vez llamará al read
. Si read
devuelve 0, lo que significa que no hay más datos disponibles, _filbuf
configurará el indicador _IOEOF
, que feof
comprueba cada vez que lo llame para devolver verdadero.
Como usted puede entender de lo anterior, feof
devolverá verdadero la primera vez que intente leer un carácter más allá del final del archivo (o una función de la biblioteca intenta en su nombre). Esto tiene implicaciones sutiles en el comportamiento de varias funciones. Considere un archivo que contiene un solo carácter: el dígito 1
. Después de leer ese carácter con getc
, feof
devolverá falso, porque el indicador _IOEOF
está desactivado; nadie ha intentado leer más allá del final del archivo. Llamar de nuevo al getc
dará como resultado una llamada al read
, la configuración del indicador _IOEOF
, y esto hará que feof
devuelva verdadero. Sin embargo, después de leer el número del mismo archivo usando fscanf("%d", &n)
, feof
devolverá inmediatamente verdadero, porque fscanf
habrá intentado leer dígitos adicionales del entero.
Simple y correcto :-) – cnicutar
Lo siento, me emocioné y lo amplié un poco. –
Es aún mejor – cnicutar