2010-09-09 19 views
38

Estoy confundido por un programa mencionado en K & R que usa getchar(). Da el mismo resultado que la cadena de entrada:¿Cómo funciona getchar()?

#include <stdio.h> 

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

¿Por qué imprime toda la cadena? Esperaría que leyera un personaje y preguntara nuevamente por la entrada.

Y, ¿son todas las cadenas que ingresamos terminadas por un EOF?

+0

¿No es EOF un valor de char y no un int? –

+3

Creo que es un int cuyo valor es -1. – Shubham

+2

Las cadenas terminan en \ 0.Los archivos son finalizados por EOF que es -1 –

Respuesta

34

En la configuración simple que probablemente esté usando, getchar funciona con la entrada con buffer, por lo que debe presionar enter antes de que getchar obtenga algo para leer. Las cadenas no están terminadas por EOF; de hecho, EOF no es realmente un personaje, sino un valor mágico que indica el final del archivo. Pero EOF no es parte de la cadena de lectura. Es lo que getchar devuelve cuando no queda nada por leer.

+0

Cuando probé el programa de conteo de caracteres en K & R, encontré que 'get char()' obtiene mi entrada como "abc", cuando contando, sería '4' en lugar de' 3', entonces usé 'gdb' para depurarlo, resultó que el 'carácter' adicional es (nl), cuyo código ascii es 0x0a. Entonces, ¿mi entrada fue una cadena? ¿No terminó esa cadena con '\ 0'? ¿Por qué hubo un (nl)? – ray6080

+0

Esto se debe a que el carácter de avance de línea que termina la línea es parte de la entrada. C es así, lidiar con eso. –

3

getchar() lee un solo carácter de entrada y devuelve ese carácter como el valor de la función. Si hay un error al leer el carácter, o si se llega al final de la entrada, getchar() devuelve un valor especial, representado por "EOF".

26

Hay un búfer/flujo subyacente que getchar() y amigos leen. Cuando ingresa texto, el texto se almacena en un búfer en algún lugar. getchar() puede transmitirlo un carácter a la vez. Cada lectura devuelve el siguiente carácter hasta que alcanza el final del búfer. La razón por la que no le pide caracteres posteriores es que puede obtener la siguiente del búfer.

Si ejecuta su secuencia de comandos y escribe directamente en él, continuará solicitando la entrada hasta que presione CTRL + D (fin del archivo). Si lo llamas como ./program < myInput donde myInput es un archivo de texto con algunos datos, obtendrá el EOF cuando llegue al final de la entrada. EOF no es un personaje que existe en la secuencia, sino un valor centinela para indicar cuándo se ha alcanzado el final de la entrada.

Como advertencia adicional, creo que getchar() también devolverá EOF si encuentra un error, por lo que querrá comprobar ferror(). Ejemplo a continuación (no probado, pero entiendes la idea).

main() { 
    int c; 
    do { 
     c = getchar(); 
     if (c == EOF && ferror()) { 
      perror("getchar"); 
     } 
     else { 
      putchar(c); 
     } 
    } 
    while(c != EOF); 
} 
+1

Gracias por la información CTRL + D. – estrar

+0

¿'bash' crea el buffer o lo hace Linux? Parece extraño que K & R no mencionara este problema, especialmente porque estaban basados ​​en Unix. Gracias. – Ron

9

Cuerdas, por C definición, están terminadas en '\0'. No tiene "C strings" en su programa.

Su programa lee los caracteres (almacenados en el búfer hasta ENTER) desde la entrada estándar (el teclado) y los vuelve a escribir en la salida estándar (la pantalla). Hace esto sin importar cuántos caracteres escriba o por cuánto tiempo lo hace. Para detener el programa, debe indicar que la entrada estándar no tiene más datos (¿cómo puede un teclado no tener más datos?).

Simplemente escriba Ctrl+D (Unix) o Ctrl+Z (Windows) para simular que el archivo ha llegado a su fin.
Ctrl+D (o Ctrl+Z) no son realmente caracteres en el sentido de la palabra C.

Si ejecuta su programa con la redirección de entrada, el EOF es el fin real del archivo, no una creencia hacer uno
./a.out < source.c

2

De acuerdo con la definición de getchar() que lee un carácter desde la entrada estándar. Desafortunadamente stdin se confunde con el teclado, que podría no ser el caso de getchar. getchar usa un buffer como stdin y lee un solo caracter a la vez. En su caso, dado que no hay EOF, el getchar y el putchar se ejecutan varias veces y le parece que la secuencia completa se imprime a la vez. hacer un pequeño cambio y comprenderá:

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

Ahora mira en la salida en comparación con el código original.

Otro ejemplo que le explique el concepto de getchar y la entrada estándar tamponada:

void main(){ 
int c; 
printf("Enter character"); 
c = getchar(); 
putchar(); 
c = getchar(); 
putchar(); 
} 

introducir dos caracteres en el primer caso. La segunda vez que se ejecuta getchar, ¿está ingresando un personaje? NO, pero aún funciona putchar.

Esto en última instancia significa que hay un búfer y cada vez que esté escribiendo algo y haga clic en entrar, esto va y se instala en el búfer. getchar usa este buffer como stdin.

Cuestiones relacionadas