• Viernes 8 de Noviembre de 2024, 23:27

Autor Tema:  el poco Recomendable scanf !!  (Leído 2008 veces)

NICOLASBLUES

  • Nuevo Miembro
  • *
  • Mensajes: 10
    • Ver Perfil
el poco Recomendable scanf !!
« en: Sábado 15 de Mayo de 2010, 23:26 »
0
Hola Gente!!

SI NO OS INTERESA EL PORQUE DE NO USARLO PUDEN PASAR AL FINAL QUE SE EXPLICA COMO SUPLANTARLO

Hoy explico  porque el uso de scanf no es recomendable..
para empesar es un error decir que un programa lee del teclado en verdad lo que hace es leer de un area de memoria llamado "buffer de teclado"  y el buffer del teclado es "buffer de linea" esto quiere decir  que los datos que provienen del teclado se insertan linea por linea y no caracter a caracter . Es por eso que cuando leemos de ahí, por más que ingresemos muchos caracteres, hasta que no ingresamos el fin de línea (enter) el programa no lee nada y se queda trabado esperando que haya algo en el buffer.

si el buffer no está vacío, sí o sí hay al menos un fin de línea;
el buffer siempre tiene un carácter de fin de línea al final.

El gran problema con scanf es que no siempre leerá el fin de linea lo que nos lleva a que el buffer quede con basura, osea con caracteres no leídos los cuales la próxima vez que invoquemos a scanf los leerá de mas esta decir que esto podría causar algunos problemas al programador.
scanf solo lee hasta que encuentre el formato que le especificamos, esto conlleva a otro gran problema ya que si nosotros le decimos que lea un entero (%i") y nosotros ingresamos 2 enteros separados por un espacio scanf solo leerá hasta encontrar el formato especificado dejando al buffer sucio con ese entero de mas
Otro problema que tenemos es que no hace ningún tipo de chequeo a la hora de verificar los datos ingresados si se le indica que se ingresara un entero y el usuario ingresa una letra esté hace una conversión a entero lo cual genera un problema.


por estas razones no es recomendable usarlo siempre se puede suplantar con algo que no ensucie el buffer para eso utilsaremos sscanf y fgets :

Código: C
  1.  
  2. #include <stdio.h>
  3.  
  4. int main()
  5. {
  6.    char nombre[20]="", entrada[81]="";
  7.    unsigned int edad=0;
  8.  
  9.    printf( "Escriba su nombre y edad, separados por un espacio:n" );
  10.    fgets(entrada, 20, stdin ); //llenamos el buffer reservando 20 caracteres y stdin es la entrada standar
  11.    sscanf( entrada, "%s %u", nombre, &edad ); //con sscanf introducimos lo que tenemos en el buffer tanto en nombre como en edad    
  12.  
  13.    printf( "Has escrito: %sn", entrada ); //lo que tenemos en el buffer
  14.    printf( "Nombre: %s. Edad: %dn", nombre, edad ); //
  15.  
  16.  

El único inconveniente que tendremos con fgets es que como bien dice
Sorancio es que si nosotros ingresamos menos caracteres los que le indicamos en el segundo parámetro inserta un fin de linea en la cadena esto representa un pequeño inconveniente con el cual lidiar pero se podría de la siguiente manera:
 
Código: C
  1. if (letra2[strlen(letra2)-1]=='n')
  2.  letra2[strlen(letra2)-1]='';
  3.  


lo cual también representa una alternativa para gets la cual no tiene control interno y provoca muchas veces problemas inesperados.



bueno eso es todo...

Saludos Cordiales

rock_neurotiko

  • Nuevo Miembro
  • *
  • Mensajes: 14
    • Ver Perfil
Re: el poco Recomendable scanf !!
« Respuesta #1 en: Jueves 20 de Mayo de 2010, 22:58 »
0
Para liberar el buffer y que no ocurran estos errores (que suelen ocurrir con los char) es tan simple como lo siguiente:


Código: C
  1.  
  2. /*Código erróneo*/
  3. #include <stdio.h>
  4.  
  5. int main()
  6. {
  7.  
  8.   char c,d,e;
  9.  
  10. printf("Introduzca primer carácter:");
  11. scanf("%c", &c);
  12.  
  13. printf("Introduzca el segundo carácter:");
  14. scanf("%c", &d);
  15.  
  16. printf("Introduzca el tercer carácter:");
  17. scanf("%c", &e);
  18.  
  19. printf("Los carácteres son: %c, %c, %c.", c, d, e);
  20.  
  21. return 0;
  22. }
  23.  
  24.  


Dará un error, no al compilar, sino al trabajar con el, ya que al introducir el primer carácter hay que presionar Enter, y guarda el enter (n) en el buffer, y al hacer el otro scanf lo mete como si lo hubiese introducido el usuario.

Para solucionar esto, existe una función para liberar el buffer. La función es fflush(stdin); stdin es para limpiar el Standar Input que para este caso es el correcto.

El código sin error sería el siguiente:

Código: C
  1.  
  2. /*Código válido*/
  3. #include <stdio.h>
  4.  
  5. int main()
  6. {
  7.  
  8.   char c,d,e;
  9.  
  10. printf("Introduzca primer carácter:");
  11. scanf("%c", &c);
  12.  
  13. fflush(stdin); /*Liberamos el buffer*/
  14. printf("Introduzca el segundo carácter:");
  15. scanf("%c", &d);
  16.  
  17. fflush(stdin); */Volvemos a liberar el buffer*/
  18. printf("Introduzca el tercer carácter:");
  19. scanf("%c", &e);
  20.  
  21. printf("Los carácteres son: %c, %c, %c.", c, d, e);
  22.  
  23. return 0;
  24. }
  25.  
  26.  


Solo se necesita poner en los dos últimos ya que en el primero el buffer ya está liberado, pero si se quisiese meter en un bucle habría que ponerlo asi:


Código: C
  1.  
  2. for(;;){
  3. printf("Introduzca primer carácter:");
  4. scanf("%c", &c);
  5.  
  6. fflush(stdin); /*Liberamos el buffer*/
  7. printf("Introduzca el segundo carácter:");
  8. scanf("%c", &d);
  9.  
  10. fflush(stdin); */Volvemos a liberar el buffer*/
  11. printf("Introduzca el tercer carácter:");
  12. scanf("%c", &e);
  13.  
  14. printf("Los carácteres son: %c, %c, %c.", c, d, e);
  15.  
  16. fflush(stdin); /*Liberación antes de que empiece el bucle de nuevo*/
  17.  
  18. if (c='e') brake; /*Para poder salir del bucle de algun modo*/
  19. }
  20.  
  21.  


Si estoy equivocado en algo estaré encantado en que me corrijais =D

NICOLASBLUES

  • Nuevo Miembro
  • *
  • Mensajes: 10
    • Ver Perfil
Re: el poco Recomendable scanf !!
« Respuesta #2 en: Jueves 20 de Mayo de 2010, 23:18 »
0
Hola

STDIN, como su nombre lo indica, significa 'Standard input'. Es decir, el ingreso por teclado.

Acorde al Standard, fflush espera solamente un stream de salida (STDOUT: 'Standard Output) por lo que el comportamiento con streams de entrada como STDIN es indefinido. Por mas que en algunas plataformas funcione, o que en algunos compiladores funcione, no deberia ser utilizado.

Por el otro lado, para evitar esas pausas fastidiosas es necesario evitar las funciones que dejan basura por doquier (como scanf();) y utilizar funciones como la ya mencionada fgets();

gracias por comentar

Saludos Cordiales