¿Cómo borrar el buffer de entrada en C?

Tengo el siguiente progtwig:

int main(int argc, char *argv[]) { char ch1, ch2; printf("Input the first character:"); // Line 1 scanf("%c", &ch1); printf("Input the second character:"); // Line 2 ch2 = getchar(); printf("ch1=%c, ASCII code = %d\n", ch1, ch1); printf("ch2=%c, ASCII code = %d\n", ch2, ch2); system("PAUSE"); return 0; } 

Como ha explicado el autor del código anterior: El progtwig no funcionará correctamente porque en la Línea 1, cuando el usuario presiona Enter, saldrá en el carácter del búfer de entrada 2: Enter key (ASCII code 13) y \n (ASCII code 10) . Por lo tanto, en la línea 2, leerá \n y no esperará a que el usuario ingrese un carácter.

OK, tengo esto. Pero mi primera pregunta es: ¿Por qué el segundo getchar() ( ch2 = getchar(); ) no lee la Enter key (13) , en lugar de \n character?

Luego, el autor propuso 2 formas de resolver tales probremas:

  1. usa fflush()

  2. escribe una función como esta:

     void clear (void) { while ( getchar() != '\n' ); } 

Este código funcionó en realidad. Pero no puedo explicar cómo funciona? Porque en la sentencia while, usamos getchar() != '\n' , eso significa leer cualquier caracter solo excepto '\n' ? si es así, ¿en el búfer de entrada sigue siendo el carácter '\n' ?

El progtwig no funcionará correctamente porque en la Línea 1, cuando el usuario presiona Intro, dejará en el carácter del búfer de entrada 2: tecla Intro (código ASCII 13) y \ n (código ASCII 10). Por lo tanto, en la línea 2, leerá \ n y no esperará a que el usuario ingrese un carácter.

El comportamiento que ves en la línea 2 es correcto, pero esa no es la explicación correcta. Con las transmisiones en modo texto, no importa qué terminaciones de línea utiliza su plataforma (ya sea retorno de carro (0x0D) + avance de línea (0x0A), un CR desnudo o un LF desnudo). La biblioteca C runtime se encargará de eso por usted: su progtwig verá solo '\n' para nuevas líneas.

Si escribió un carácter y presionó Intro, entonces ese carácter de entrada sería leído por la línea 1, y luego '\n' sería leído por la línea 2. Vea Estoy usando scanf %c para leer una respuesta Y / N, pero la entrada posterior se omite. de las preguntas frecuentes comp.lang.c.

En cuanto a las soluciones propuestas, consulte (nuevamente en las preguntas frecuentes de comp.lang.c):

  • ¿Cómo puedo eliminar la entrada pendiente para que el encabezado de escritura de un usuario no se lea en el siguiente mensaje? Will fflush(stdin) funciona?
  • Si fflush no funciona, ¿qué puedo usar para eliminar la entrada?

que básicamente dicen que el único enfoque portátil es hacer:

 while ((c = getchar()) != '\n' && c != EOF) { } 

Su getchar() != '\n' funciona porque una vez que llama a getchar() , el carácter devuelto ya se ha eliminado de la secuencia de entrada.

Además, me siento obligado a desalentarlo de usar scanf completo: ¿Por qué todos dicen no usar scanf ? ¿Qué debería usar en su lugar?

Puedes hacerlo (también) de esta manera:

 fseek(stdin,0,SEEK_END); 

Las líneas:

 int ch; while ((ch = getchar()) != '\n' && ch != EOF) ; 

no lee solo los caracteres antes del salto de línea ( '\n' ). Lee todos los caracteres en la secuencia (y los descarta) hasta e incluyendo el siguiente salto de línea (o se encuentra EOF). Para que la prueba sea verdadera, primero debe leer el salto de línea; así que cuando el ciclo se detiene, el salto de línea fue el último carácter leído, pero ha sido leído.

En cuanto a por qué se lee un salto de línea en lugar de un retorno de carro, eso se debe a que el sistema ha traducido el retorno a un salto de línea. Cuando se presiona enter, eso indica el final de la línea … pero la secuencia contiene un avance de línea, ya que ese es el marcador normal de final de línea para el sistema. Eso podría depender de la plataforma.

Además, usar fflush() en una secuencia de entrada no funciona en todas las plataformas; por ejemplo, generalmente no funciona en Linux.

Una forma portátil de borrar hasta el final de una línea que ya ha intentado leer parcialmente es:

 int c; while ( (c = getchar()) != '\n' && c != EOF ) { } 

Esto lee y descarta caracteres hasta que aparece \n que señala el final del archivo. También comprueba contra EOF en caso de que el flujo de entrada se cierre antes del final de la línea. El tipo de c debe ser int (o más grande) para poder mantener el valor EOF .

No hay una forma portátil de averiguar si hay más líneas después de la línea actual (si no hay, entonces getchar bloqueará la entrada).

Pero no puedo explicar cómo funciona? Porque en el enunciado while, usamos getchar() != '\n' , eso significa leer cualquier caracter solo excepto '\n' ?? si es así, ¿en el búfer de entrada aún permanece el carácter '\n' ? ¿Estoy malentendiendo algo?

Lo que quizás no se dé cuenta es que la comparación ocurre después de que getchar() elimine el carácter del buffer de entrada. Entonces cuando alcanzas el '\n' , se consume y luego sales del ciclo.

puedes probar

 scanf("%c%*c", &ch1); 

donde% * c acepta e ignora la nueva línea

un método más en lugar de fflush (stdin) que invoca un comportamiento indefinido que puede escribir

 while((getchar())!='\n'); 

no te olvides del punto y coma después de while loop

 unsigned char a=0; if(kbhit()){ a=getch(); while(kbhit()) getch(); } cout<(a) & 0xFF)< 

-o-

uso tal vez use _getch_nolock() .. ???

Me encuentro con un problema tratando de implementar la solución

 while ((c = getchar()) != '\n' && c != EOF) { } 

Publico un pequeño ajuste ‘Código B’ para cualquiera que tenga el mismo problema.

El problema fue que el progtwig me mantuvo atrapando el carácter ‘\ n’, independientemente del carácter enter, aquí está el código que me dio el problema.

Código A

 int y; printf("\nGive any alphabetic character in lowercase: "); while( (y = getchar()) != '\n' && y != EOF){ continue; } printf("\n%c\n", toupper(y)); 

y el ajuste fue para “atrapar” el carácter (n-1) justo antes de que se evalúe el condicional en el ciclo while, aquí está el código:

Código B

 int y, x; printf("\nGive any alphabetic character in lowercase: "); while( (y = getchar()) != '\n' && y != EOF){ x = y; } printf("\n%c\n", toupper(x)); 

La posible explicación es que, para que el bucle while se rompa, tiene que asignar el valor ‘\ n’ a la variable y, por lo que será el último valor asignado.

Si me perdí algo con la explicación, código A o código B, por favor dime, soy apenas nuevo en c.

Espero que ayude a alguien

Corto, portátil y declarado en stdio.h

 stdin = freopen(NULL,"r",stdin); 

No se cuelga en un bucle infinito cuando no hay nada en el stdin para descargar como la siguiente línea bien conocida:

 while ((c = getchar()) != '\n' && c != EOF) { } 

Un poco caro, así que no lo use en un progtwig que necesite borrar el buffer repetidamente.

Robó de un compañero de trabajo 🙂

 char choice; do{ printf("\n *"); printf("\n Do you want to continue? (y/n) "); choice = getchar(); if(getchar() != '\n'){ fflush(stdin); } }while( choice != 'n' ); 

Otra solución aún no mencionada es usar: rewind (stdin);