2010-09-21 19 views
26

Tengo esto pero una vez que alcanza el supuesto EOF simplemente repite el ciclo y el scanf de nuevo.¿Cómo se lee scanf hasta EOF en C?

int main(void) 
{ 
     char words[16]; 

     while(scanf("%15s", words) == 1) 
      printf("%s\n", words); 

     return 0; 
} 
+0

¿Qué entrada estás utilizando? ¿Está redirigiendo un archivo a 'stdin', o escribiendo en la consola? Si es este último, ¿qué sistema operativo está usando y cómo está escribiendo en el EOF? –

Respuesta

0

Es necesario comprobar el valor de retorno contra EOF, no contra 1.

Tenga en cuenta que en su ejemplo, también se utilizan dos nombres de variables diferentes, words y word, sólo se declaró words, y no declaró su longitud, que debe ser 16 para adaptarse a las 15 caracteres leídos en más un carácter NUL.

14

Probar:

while(scanf("%15s", words) != EOF) 

Es necesario comparar scanf salida con EOF

Puesto que usted está especificando un ancho de 15 en la cadena de formato, usted leerá a lo sumo 15 Char. Por lo tanto, las palabras char array deben ser del tamaño 16 (15 +1 para null char). Así que declararlo como:

char words[16]; 
+3

Esto NO es correcto. scanf devuelve el número de campos de entrada escaneados con éxito, NUNCA EOF (-1). Por lo tanto, su ciclo while es redundante, se romperá en la primera vez. – user411313

+2

@ user411313 no, scanf puede devolver EOF, ya que está comparando el uso de! = No se romperá la primera vez. Sin embargo, en el caso general, también desearía la cantidad de elementos asignados para que pueda realizar una validación. – nos

+1

@ user411313: Tanto [man scanf] (http://www.google.com/search?q=man+scanf) como C99 §7.19.6.2/16 dicen que puede devolver EOF. –

3

Scanf es mucho más problemático de lo que vale. Aquí hay dos formas mejores de hacer lo que estás tratando de hacer. Esta primera es una traducción más o menos directa de su código. Es más largo, pero puedes mirarlo y ver claramente lo que hace, a diferencia de scanf.

#include <stdio.h> 
#include <ctype.h> 
int main(void) 
{ 
    char buf[1024], *p, *q; 
    while (fgets(buf, 1024, stdin)) 
    { 
     p = buf; 
     while (*p) 
     { 
      while (*p && isspace(*p)) p++; 
      q = p; 
      while (*q && !isspace(*q)) q++; 
      *q = '\0'; 
      if (p != q) 
       puts(p); 
      p = q; 
     } 
    } 
    return 0; 
} 

Y esta es otra versión. Es un poco más difícil ver lo que hace por inspección, pero no se rompe si una línea tiene más de 1024 caracteres, por lo que es el código que utilizaría en la producción. (Bueno, realmente lo que iba a utilizar en la producción es tr -s '[:space:]' '\n', pero esta es la forma de poner en práctica algo por el estilo.) Bucles

#include <stdio.h> 
#include <ctype.h> 
int main(void) 
{ 
    int ch, lastch = '\0'; 
    while ((ch = getchar()) != EOF) 
    { 
     if (!isspace(ch)) 
      putchar(ch); 
     if (!isspace(lastch)) 
      putchar('\n'); 
     lastch = ch; 
    } 
    if (lastch != '\0' && !isspace(lastch)) 
     putchar('\n'); 
    return 0; 
} 
+0

Sí, eso es * mucho * más simple que 'para (char buf [1024]; scanf ("% 1023s ", buf) == 1;) printf ("% s \ n ", buf);', excepto que cambió el comportamiento en ciertos casos de espacios en blanco iniciales, finales y adyacentes. –

+0

En la vida real escribiría un ciclo sobre caracteres individuales con exactamente el comportamiento de espacio en blanco que quería (que podría o no ser lo que OP quería, no lo dijeron), pero sería demasiado tedioso como ejemplo. Si está utilizando scanf, no debe preocuparse por el comportamiento de la caja de borde o la recuperación de errores, de todos modos. – zwol

+0

... ya sabes, es * no * demasiado tedioso. Reescribió el ejemplo. – zwol

3

Su código hasta que lea una sola palabra, luego se cierra. Entonces, si le das varias palabras, leerá la primera y saldrá, mientras que si le das una entrada vacía, se repetirá para siempre. En cualquier caso, solo imprimirá basura al azar de la memoria no inicializada. Esto aparentemente no es lo que quieres, pero ¿qué quieres? Si lo que desea es leer e imprimir la primera palabra (si existe), utilice si:

if (scanf("%15s", word) == 1) 
    printf("%s\n", word); 

Si desea bucle mientras se puede leer una palabra, utilice mientras:

while (scanf("%15s", word) == 1) 
    printf("%s\n", word); 

Además, como han dicho otros, es necesario dar la palabra conjunto un tamaño que es lo suficientemente grande para su scanf:

char word[16]; 

otros han sugerido pruebas para EOF en lugar de comprobar cuántos elementos scanf emparejados. Eso está bien para este caso, donde scanf no puede fallar a menos que exista un EOF, pero no es tan bueno en otros casos (como tratar de leer números enteros), donde scanf podría no coincidir sin alcanzar EOF (si la entrada no es t un número) y devuelve 0.

edición

Parece que ha cambiado su pregunta para que coincida con el código que funciona muy bien cuando lo ejecuto - bucles de la lectura de palabras hasta que se alcanza EOF y luego se cierra. Así que algo más está sucediendo con su código, tal vez relacionada con la forma en que lo está alimentando de entrada según lo sugerido por David

+0

Oye, gracias por la respuesta, pero ¿has intentado esto? Me di cuenta de que puse "! =" En mi publicación original, pero quise decir ==, y esto me da lo que quiero donde escribo una oración cuando se llama al scanf, luego se repite e imprime las palabras como se supone que también , luego vuelve a llamar al scanf que no quiero. Lo llama dejándome sin forma de salir del círculo. Tal vez mi compilador? pero el único problema es después de que imprime todas las palabras que no se rompe. – JJRhythm

+2

@ user315903: Es por eso que la mejor idea es publicar el código que no funciona, en lugar de intentar escribir algo similar. Si tu código no funciona, por razones que no entiendes, entonces no entiendes lo que está mal y no puedes confiar en ti mismo para preservar la esencia del problema. –

-3

Para usuarios de C, esto también funcionará

while (gets(str) != NULL) 
+9

-1 Para usar 'gets'. –

+2

Para ser claros, el problema con 'gets' es que puede escribir más allá del final del búfer asignado. –

-2

supongo que mejor manera de hacerlo es ...

int main() 
{ 
    char str[100]; 
    scanf("[^EOF]",str); 
    printf("%s",str); 
    return 0;  
} 
Cuestiones relacionadas