¿Cómo borrar el búfer de entrada en C?

4 minutos de lectura

avatar de usuario
ipkiss

tengo el siguiente programa:

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 programa no funcionará correctamente porque en la Línea 1, cuando el usuario presiona Enter, dejará en el búfer de entrada el carácter 2: Enter key (ASCII code 13) y \n (ASCII code 10). Por lo tanto, en la Línea 2, leerá el \n y no esperará a que el usuario ingrese un carácter.

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

A continuación, el autor propuso 2 formas de resolver tales problemas:

  1. usar fflush()

  2. escribir una función como esta:

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

Este código funcionó en realidad. ¿Pero no puedo explicarme cómo funciona? Porque en la declaración while, usamos getchar() != '\n'eso significa leer cualquier carácter individual excepto '\n'? si es así, en el búfer de entrada aún permanece el '\n' ¿personaje?

  • Ver también: No puedo vaciar stdin. ¿Cómo puedo vaciar stdin en C?

    – Gabriel grapas

    10 de abril a las 1:20

Puedes hacerlo (también) de esta manera:

fseek(stdin,0,SEEK_END);

  • Wow… por cierto, dice el estándar fseek está disponible para stdin?

    – ikh

    22 de mayo de 2014 a las 11:03

  • No sé, creo que no lo menciona, pero stdin es FILE* y fseek acepta un parámetro FILE*. Lo probé y funciona en Mac OS X pero no en Linux.

    – Ramy Al Zuhouri

    22 de mayo de 2014 a las 11:07

  • Por favor explique. Sería una gran respuesta si el autor escribiera las implicaciones de este método. ¿Hay algún problema?

    – Eva Alex

    28 de octubre de 2015 a las 7:35

  • @EvAlex: hay muchos problemas con esto. Si funciona en su sistema, genial; si no, entonces no es sorprendente ya que nada garantiza que funcionará cuando la entrada estándar es un dispositivo interactivo (o un dispositivo no buscable como una tubería, un enchufe o un FIFO, por nombrar solo algunas otras formas en las que puede fallar).

    –Jonathan Leffler

    15 de septiembre de 2016 a las 5:08

  • ¿Por qué debería ser SEEK_END? ¿Podemos usar SEEK_SET en su lugar? ¿Cómo se comporta el stdin de FP?

    – Rajesh

    3 de marzo de 2017 a las 11:33

  • @AndreasWenzel Sí. Reparado. Gracias.

    – Steve cumbre

    14 de marzo a las 22:29

Me sorprende que nadie haya mencionado esto:

scanf("%*[^\n]");

avatar de usuario
inquisiciones

Prueba esto:

stdin->_IO_read_ptr = stdin->_IO_read_end;

avatar de usuario
milímetro

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 obtiene \n que señala el final del archivo. También verifica 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 mayor) para poder mantener el valor EOF.

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

  • por qué while((c=getchar())!=EOF); ¿No funciona? Es un bucle sin fin. No se puede entender la ubicación de EOF en stdin.

    – Rajesh

    3 de marzo de 2017 a las 15:57

  • @Rajesh Eso se borraría hasta que se cierre el flujo de entrada, lo que no ocurrirá si hay más entradas más adelante

    –MM

    03/03/2017 a las 21:45


  • @Rajesh Sí, tienes razón. Si no hay nada en stdin para vaciar cuando se llama esto, se bloqueará (colgará) debido a que está atrapado en un bucle infinito.

    – Jason Enocs

    13/07/2017 a las 21:31

  • @AbhishekMane Pero un byte tiene 8 bits y 256 toma 9 bits. No puede manejar ningún valor de 8 bits, más un valor de indicador adicional, si asigna el resultado de getchar() a un char. También, stdio.h posee #define EOF (-1). C tiene carácter, carácter firmado, carácter sin firmar y el carácter puede estar en 0..255 o -128..127 dependiendo de la arquitectura. man getchar es muy explícito: “fgetc() lee el siguiente carácter de la secuencia y lo devuelve como una conversión de caracteres sin firmar a un int, o EOF al final del archivo o error”. Entonces (int) -1 o (int) 0..255. Rellenarlo en una variable char descarta información esencial.

    – Paul_pedante

    19 de marzo a las 10:07

  • @Paul_Pedant lo entendió. Gracias. EOF no es personaje. getchar() devoluciones char(0,1,2,...255) + EOF para manejar esto EOF solo tipo de retorno de getchar(_) es int . Asi que C debe ser int derecho ?

    – Abhishek Mané

    22 de marzo a las 8:26

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad