¿Queda algo en el Buffer de Entrada stdin?

Muy buen dia aun que la pregunta en el titulo de este post parece una pregunta totalmente N00b. No lo es.

El objetivo de post Deja de utilizar fflush

Código
  1. fflush(stdin);

Yo no lo utilizo, o por lo menos trato de nunca recomendarlo, solo que ayer se lo recomendé a alguien y no me convence su implementación.  :silbar:

La verdad es que quiero dar por terminado el tema de la función fflush para el Buffer de entrada.

Todo esto en Lenguaje C  ;-)

La idea de este post viene de preguntas hechas en el foro similares a ¿Como filtrar todo tipo de datos de entrada en un programa?

Revisando algunas links en internet me encuentro con:
https://es.stackoverflow.com/questions/82431/saber-si-el-b%C3%BAfer-de-entrada-stdin-est%C3%A1-vac%C3%ADo-en-c-est%C3%A1ndar
http://man7.org/linux/man-pages/man3/fflush.3.html
http://www.cplusplus.com/reference/cstdio/fflush/

Sin embargo en todos ellos hablan de que el comportamiento de fflush para el stdin es Inesperado, por lo cual repetidamente dicen que no se debe de usar.

¿Cual es la solución para limpiar el buffer de entrada, si es que realmente queda algo en el?

Intente con feof, sin embargo al parecer NUNCA llega el fin del archivo para STDIN

Código

#include<stdio.h>
#include<string.h>

int main()    {
    char temporal[10];
    printf("Ingrese menos de 10 o mas de 10 caracteres\npara ver el comportamiento de feof(stdin): ");
    fgets(temporal,10,stdin);
    temporal[strcspn(temporal,"\n\r")] = '\0';
    printf("Valor leido %s\n");
    if(feof(stdin))    {
        printf("stdin llego al final del archivo\n");
    }
    else    {
        printf("stdin NO llego al final del archivo\n");
    }   
}

 

El problema de todo esto radica que cuando estamos leyendo múltiples valores desde el teclado, aun que lo delimitemos con fgets para la cantidad de datos que se guardaran en cada variable, el fgets , al igual que otras funciones de entrada deja los caracteres restantes en el buffer de entrada y son tomados automáticamente por cualquier función de entrada de texto.




Como ven en la imagen, en la segunda entrada de las AAAAAAAAAAAAA, se salto el segundo "Ingrese una cadena."

Código:
#include<stdio.h>
#include<string.h>

int main() {
 char temporal_1[10];
 char temporal_2[10];
 printf("Ingrese una cadena: ");
 fgets(temporal_1,10,stdin);
 temporal_1[strcspn(temporal_1,"\n\r")] = '\0';
 printf("Ingrese una cadena: ");
 fgets(temporal_2,10,stdin);
 temporal_2[strcspn(temporal_2,"\n\r")] = '\0';
 printf("Valor leido %s\n",temporal_1);
 printf("Valor leido %s\n",temporal_2);
}

Este problema tambien se presenta en C++ con funciones de entrada tipo cin>>

Ejemplo:



Codigo:


#include<iostream>

using namespace std;
int main()    {
    int numero_1,numero_2;
    cout<<"Ingrese un numero: ";
    cin>>numero_1;
    cout<<"Ingrese un numero: ";
    cin>>numero_2;
    cout<<"Valor leido "<<numero_1<<endl;
    cout<<"Valor leido "<<numero_2<<endl;
}



Entonces pregunto:

¿Cual es la solución para limpiar el buffer de entrada, si es que realmente queda algo en el?
¿Como se si es que realmente queda algo en el buffer de entrada, sin consumirlo?


Soluciones:

fseek(stdin, 0, SEEK_END);


Esa linea de codigo nos "vacia" el  buffer de entrada.

Otra forma de realizar esta operacion es realizando algunas validaciones en el texto leido con fgets.

 Si bien han usado en su momento fgets, recordaran que este guarda en la misma cadena que acaba de leer el "Enter" esto es un byte de valor 0xA (10 en decimal)

Esto siempre y cuando la longitud del texto leído no supere el tamaño del arreglo donde vamos a guardar nuestra cadena leida.

Vemos un ejemplo con Codigo:


#include<stdio.h>
#include<string.h>

int main()    {
    int len,i = 0;
    char temporal[10];
    printf("Ingrese una cadena: ");
    fgets(temporal,10,stdin);
    len = strlen(temporal);
    printf("Cadena Leida: %s",temporal);
    printf("La longitud de la cadena leida es de %i\n",len);
    while(i<10) printf("%.2X",temporal[i++]);
    printf("\n");
}


Aqui unas cuantas salidas.



1er caso de la imagen: ingresar mas de 9 letras "A", obvio hay datos en el buffer de stdin esperando ser leeidos,
2do caso de la imagen: Al ingresar exactamente 9 letras A, el ultimo byte del buffer el byte 10 es el valor nulo '\0' En este caso queda un Enter en el buffer de datos de stdin
3er caso de la imagen: Al ingresar exactamente 8 letras A, strlen sigue considerando 9 espacios usados ya que el Enter (0xA) esta el la posición temporal[8] y en temporal[9] esta el byte nulo '\0'
4to caso de la imagen: Al ingresar exactamente 7 letras A, strlen marca una longitud de 8 espacios mismo caso que el anterior sigue considerando el "Enter" como un valor valido de la cadena.

En conclusión, si al usar fgets correctamente, el valor de nuestro arreglo en su posición strlen(temporal) - 1 es igual 0xA entonces no queda nada en nuestro buffer de STDIN, en caso contrario si queda Algo, ya sea solo el Enter o Texto restante + Enter.

En cualquier caso después de realizar esta evaluación si detectamos el caso de que aun quede buffer pendiente por leer, podemos leerlo asi



while ((c = getchar()) != 0xA);

 



Comentarios

Entradas populares de este blog

Clave WPA2 por Defecto de equipos TotalPlay (Huawei HG8245H)

Cable modem Ubee - WPA2 y WPS por defecto