2011-02-07 10 views
8

Dependiendo de los argumentos de la línea de comandos, estoy configurando un puntero de archivo para apuntar hacia un archivo o stdin especificado (para el propósito de la canalización). Luego paso este puntero a una serie de funciones diferentes para leer del archivo. Esta es la función para obtener el puntero del archivo:Usando fseek con un puntero de archivo que apunta a stdin

FILE *getFile(int argc, char *argv[]) { 
    FILE *myFile = NULL; 
    if (argc == 2) { 
     myFile = fopen(argv[1], "r"); 
     if (myFile == NULL) 
      fprintf(stderr, "File \"%s\" not found\n", argv[1]); 
    } 
    else 
     myFile = stdin; 
    return myFile; 
} 

Cuando se está apuntando a la entrada estándar, no parece trabajar fseek. Con eso, quiero decir que lo uso y luego uso fgetc y obtengo resultados inesperados. ¿Este es el comportamiento esperado? De ser así, ¿cómo me muevo a diferentes ubicaciones en la transmisión?

Por ejemplo:

int main(int argc, char *argv[]) { 
    FILE *myFile = getFile(argc, argv); // assume pointer is set to stdin 
    int x = fgetc(myFile); // expected result 
    int y = fgetc(myFile); // expected result 
    int z = fgetc(myFile); // expected result 

    int foo = bar(myFile); // unexpected result 

    return 0; 
} 

int bar(FILE *myFile) { 
    fseek(myFile, 4, 0); 
    return fgetc(myFile); 
} 
+0

su código de ejemplo se ve bien para mí. (excepto cuando el archivo no existe, pero esto no está relacionado con su problema) –

+0

me parece correcto. ¿Qué compilador es? puede tratar de imprimir, dentro de la barra() funcionan ambos punteros (stdin y myFile) para comprobar que son los mismos. – leonbloy

+0

@leonbloy: He descubierto que el problema es en realidad con 'fseek()'. Aparentemente, ¿no funciona cuando el puntero apunta a stdin? Tiene alguna idea sobre esto? (Actualizado la pregunta) –

Respuesta

12

Sí, es perfectamente normal que fseek no funcionará en stdin - que va normalmente sólo funciona en un archivo de disco, o algo razonablemente similares.

Aunque en realidad es algo de POSIX, normalmente puede usar if (isatty(fileno(myFile))) para obtener al menos una muy buena idea de si la búsqueda funcionará en un archivo en particular. En algunos casos, isatty y/o fileno tendrán un subrayado inicial (por ejemplo, IIRC las versiones proporcionadas con los compiladores de Microsoft sí).

+0

Entonces, supongo que mi pregunta es, y esto podría ser estúpido, ¿cómo voy a pasar a un índice diferente en la transmisión? Creo que habría una solución más elegante que llamar 'fgetc (myFile)' en un bucle n veces. –

+4

@Tyler Treat: No existe esta es la diferencia fundamental entre las secuencias y los archivos. Conceptualmente, la entrada de una secuencia no se almacena en ninguna parte; una secuencia es efímera, se genera cuando la consumes. Si necesita buscar datos en una secuencia, debe leerlos en la memoria y buscarlos por allí (o, si es particularmente grande, leerlos en un archivo temporal). – caf

+1

No encuentro soporte en la especificación C11 con respecto a "es perfectamente normal que fseek no funcione en stdin". ¿Tiene la especificación C para admitir eso cuando 'stdin' es una secuencia de texto? – chux

1

FSEEK() se basa en lseek(), y la página del manual lseek analiza los posibles errores, incluyendo:

[ESPIPE]   Fildes is associated with a pipe, socket, or FIFO. 

Si la entrada estándar está conectado a una pseudo tty, yo creo que va a tener un comportamiento zócalo.

+1

¿ANSI C dice algo al respecto? –

+0

Lo mejor que pude encontrar fue N1256 7.19.3 Archivos 1 "Si un archivo puede admitir solicitudes de posicionamiento (como un archivo de disco, a diferencia de un terminal)", pero no pude encontrar algo que vincule 'stdin' con él. –

Cuestiones relacionadas