que - ¿Se define getc() después de haber devuelto EOF?
gets c (3)
Yo uso getc();
en un ejercicio de C, y después de mirar hacia atrás en el programa noté algo raro. Supuse que el archivo dado en los argumentos de la línea de comando contiene al menos un byte. (Llama a getc();
dos veces seguidas sin buscar EOF
. Después de probarlo en un archivo vacío, funcionó sin problemas. Mi pregunta es: ¿el comportamiento de getc();
en un puntero de archivo que se ha agotado (EOF tiene ha sido alcanzado y no rebobinado) indefinido o ¿continuará siempre devolviendo EOF?
Creo que podría ampliar esta pregunta a todas las funciones de E / S en C STL, aclare esto también en su respuesta.
Aquí está el código para el programa. Se supone que el programa elimina un archivo fuente C / C ++ de todos los comentarios (y funciona perfectamente).
#include <stdio.h>
int main(int argc, char *argv[]) {
int state = 0; // state: 0 = normal, 1 = in string, 2 = in comment, 3 = in block comment
int ignchar = 0; // number of characters to ignore
int cur, next; // current character and next one
FILE *fp; // input file
if (argc == 1) {
fprintf(stderr, "Usage: %s file.c/n", argv[0]);
return 1;
}
if ((fp = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "Error opening file./n");
return 2;
}
cur = getc(fp); // initialise cur, assumes that the file contains at least one byte
while ((next = getc(fp)) != EOF) {
switch (next) {
case ''/'':
if (!state && cur == ''/'') {
state = 2; // start of comment
ignchar = 2; // don''t print this nor next char (//)
} else if (state == 3 && cur == ''*'') {
state = 0; // end of block comment
ignchar = 2; // don''t print this nor next char (*/)
}
break;
case ''*'':
if (!state && cur == ''/'') {
state = 3; // start of block comment
ignchar = 2; // don''t print this nor next char (/*)
}
break;
case ''/n'':
if (state == 2) {
state = 0;
ignchar = 1; // don''t print the current char (cur is still in comment)
}
break;
case ''"'':
if (state == 0) {
state = 1;
} else if (state == 1) {
state = 0;
}
}
if (state <= 1 && !ignchar) putchar(cur);
if (ignchar) ignchar--;
cur = next;
}
return 0;
}
Lógicamente, creo que debería devolver EOF
para siempre.
getc se define en términos de fgetc .
La función getc () será equivalente a fgetc (), excepto que si se implementa como una macro, puede evaluar la transmisión más de una vez, por lo que el argumento nunca debe ser una expresión con efectos secundarios.
La documentación para fgetc
dice:
Si se establece el indicador de fin de archivo para el flujo, o si el flujo se encuentra al final del archivo, el indicador de fin de archivo para el flujo se establecerá y fgetc () devolverá EOF.
Y "está al final del archivo" se puede determinar llamando a feof .
La documentación para feof
dice:
La función feof () devolverá un valor distinto de cero si y solo si el indicador de fin de archivo está configurado para la transmisión.
Entonces, a menos que algo pase para borrar el indicador de fin de archivo, debería continuar devolviendo EOF
para siempre.
Los archivos Stdio mantienen un indicador "eof" que se establece la primera vez que se llega al final del archivo y solo se puede restablecer llamando a clearerr
o realizando un fseek
o rewind
éxito. Por lo tanto, una vez que getc
devuelve EOF
una vez, seguirá devolviendo EOF
, incluso si hay nuevos datos disponibles, a menos que use uno de los métodos antes mencionados para borrar el indicador de eof.
Algunas implementaciones no conformes pueden hacer que nuevos datos estén disponibles de inmediato. Este comportamiento es dañino y puede romper aplicaciones conformes.
Si se establece el indicador de EOF
en la transmisión, getc
debe devolver EOF
(y si continúa llamando a getc
, debe seguir devolviendo EOF
).