2009-06-16 36 views
7

Comencé a leer "The C Programming Language" (K & R) y tengo una duda sobre la función getchar().¿Dónde `getchar()` almacena la entrada del usuario?

Por ejemplo este código:

#include <stdio.h> 

main() 
{ 
    int c; 

    c = getchar(); 
    putchar(c); 
    printf("\n"); 
} 

Typing toomanychars + CTRL + D (EOF) imprime solo t. Creo que se espera, ya que es el primer personaje presentado.

Pero entonces esta otra pieza de código:

#include <stdio.h> 

main() 
{ 
    int c; 

    while((c = getchar()) != EOF) 
    putchar(c); 
} 

Typing toomanychars + CTRL + D (EOF) imprime toomanychars.

Mi pregunta es, ¿por qué sucede esto si solo tengo una sola variable de caracteres? ¿Dónde están almacenados el resto de los personajes?

EDIT:

Gracias a todos por las respuestas, comienzo a ahora ... Sólo una pega:

Las primeras salidas del programa cuando se administra CTRL +D mientras el segundo imprime toda la cadena y luego espera a que el usuario ingrese más. ¿Por qué espera otra cadena y no sale como la primera?

+1

Su segundo enfoque simplemente se repite hasta EOF. CTRL + D (en sistemas típicos de Unix) no dará como resultado EOF a menos que lo golpee en una línea propia. Presionar CTRL + D después de haber escrito un carácter no resulta en EOF – nos

Respuesta

4

Está tratando el flujo de entrada como un archivo. Es como si hubiera abierto un archivo que contiene el texto "toomanychars" y lo haya leído o extraído un carácter a la vez.

En el primer ejemplo, en ausencia de un bucle while, es como si abriera un archivo y leyera el primer carácter, y luego lo imprimiera. Sin embargo, el segundo ejemplo continuará leyendo caracteres hasta que obtenga una señal de fin de archivo (ctrl+D en su caso) como si estuviera leyendo desde un archivo en el disco.


En respuesta a su pregunta actualizada, ¿qué sistema operativo está utilizando? Lo ejecuté en mi computadora portátil con Windows XP y funcionó bien. Si pulso enter, imprimirá lo que tenía hasta ahora, creará una nueva línea y luego continuará. (La función getchar() no regresa hasta que presione enter, que es cuando no hay nada en el búfer de entrada cuando se le llama). Cuando presiono CTRL+Z (EOF en Windows), el programa finaliza. Tenga en cuenta que en Windows, el EOF debe estar en una línea propia para contar como un EOF en el símbolo del sistema. No sé si este comportamiento se imita en Linux o en cualquier sistema que esté ejecutando.

+0

@ Carson, ¡exactamente! EOF debe estar en su propia línea. ¡MUCHAS GRACIAS! –

+0

de nada. Luché con esto también, pero lo resolví gracias a SO :) –

9

getchar obtiene un solo carácter de la entrada estándar, que en este caso es el búfer del teclado.

En el segundo ejemplo, la función getchar es en un bucle while que continúa hasta que encuentra un EOF, por lo que se seguirá sonando y recuperar un personaje (e imprimir el carácter a la pantalla) hasta que la entrada se vacía.

Las llamadas sucesivas al getchar obtendrán caracteres sucesivos que provienen de la entrada.

Ah, y no se sienta mal por hacer esta pregunta: me sorprendió la primera vez que me encontré con este problema.

+0

¿Comienza a repetirse inmediatamente después de que encuentra la instrucción 'while (c = getchar())', o espera que se presione enter y luego se repita? Por lo que puedo ver, ejecuta el cuerpo del bucle 'while()' solo después de presionar enter. Mi pregunta es: ¿el 'getchar()' hace que el bucle 'while()' espere hasta que 'enter' o 'CTRL + D' (en mi sistema) se presione y justo después que regrese al' while() 'loop y luego ejecutar el resto del cuerpo. – dud3

3

Su primer programa solo lee un carácter, lo imprime y sale. Tu segundo programa tiene un bucle. Sigue leyendo caracteres de uno en uno e imprimiéndolos hasta que lee un carácter EOF. Solo se almacena un caracter en un momento dado.

2

Solo está usando la variable c para contener cada carácter de uno en uno.

Una vez que hayas mostrado en pantalla el primer carácter (t) usando putchar(c), olvidar el valor de c asignando el siguiente carácter (o) a la variable c, reemplazando el valor anterior (t).

1

el código es funcionalmente equivalente a

main(){ 
    int c; 
    c = getchar(); 
    while(c != EOF) { 
    putchar(c); 
    c = getchar(); 
    } 
} 

es posible encontrar esta versión más fácil de entender. la única razón para poner la asignación en el condicional es evitar tener que escribir 'c = getchar()' dos veces.

4

Algo aquí está almacenado en el búfer. p.ej. el stdout FILE * en el que escribe putchar puede ser line.buffered. Cuando el programa finaliza (o se encuentra con una línea nueva) dicho archivo * se ejecutará (fflush) y verá la salida.

En algunos casos, el terminal actual que está visualizando puede almacenar en búfer la salida hasta una nueva línea, o hasta que el terminal reciba instrucciones para vaciar su memoria intermedia, lo que podría ocurrir cuando el programa en primer plano salga. un nuevo aviso.

Ahora, lo que probablemente sea el caso real aquí, es que es la entrada que se almacena en el búfer (además de la salida :-)) Al presionar las teclas, aparecerá en la ventana de su terminal. Sin embargo, el terminal no enviará esos caracteres a su aplicación, sino que almacenará el búfer hasta que le indique que sea el final de la entrada con Ctrl + D, y posiblemente también una línea nueva. Aquí es otra versión para jugar y reflexionar sobre: ​​

int main() { 
    int c; 
    while((c = getchar()) != EOF) { 
    if(c != '\n') 
     putchar(c); 
    } 
    return 0; 
} 

trate de alimentar a su programa una frase, y pulsa Enter. Y haga lo mismo si comenta if (c! = '\ N') Tal vez pueda determinar si su entrada, salida o ambas están almacenadas de alguna manera. Esto se vuelve más interesante si ejecuta lo anterior como: ./mytest | ./mytest

(Como comentario lateral, tenga en cuenta que CTRD + D no es un personaje, ni es EOF. Pero en algunos sistemas resultará en cerrar el flujo de entrada que de nuevo elevará EOF a cualquiera que intente leer desde la secuencia)

0

Para su pregunta actualizada, en el primer ejemplo, solo se lee un carácter. Nunca llega al EOF. El programa termina porque no hay nada que hacer después de completar la instrucción printf. Simplemente lee un personaje. Lo imprime Pone en una nueva línea. Y luego termina porque no tiene nada más que hacer. No lee más de un personaje.

Considerando que, en el segundo código, el getchar y el putchar están presentes dentro de un ciclo while.En esto, el programa sigue leyendo los caracteres uno por uno (como lo hace el ciclo) hasta que alcanza el carácter EOF (^ D). En ese punto, coincide con c! = EOF y dado que las condiciones no se cumplen, sale del ciclo. Ahora no hay más declaraciones para ejecutar. Entonces el programa termina en este punto.

Espero que esto ayude.

Cuestiones relacionadas