|Lo que no hay que hacer en C/C++. Nivel basico|

Iniciado por Littlehorse, 12 Diciembre 2009, 18:15 PM

0 Miembros y 1 Visitante están viendo este tema.

leogtz

Cita de: [Zero] en 27 Marzo 2011, 20:37 PM
Pero es lo que dije antes, fgets deja basura en el buffer si el usuario escribe un número de caracteres mayor que el del segundo parámetro. Le puedo poner 1000 en el segundo parámetro, pero si el usuario mete 1001 caracteres fgets deja 1 en el buffer  :P.

Saludos

¿Y para qué crees que es el sscanf()?
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

[Zero]

Cita de: Leo Gutiérrez. en 27 Marzo 2011, 20:45 PM
¿Y para qué crees que es el sscanf()?

sscanf opera sobre el buffer del primer parámetro de fgets, no limpia stdin, que es el problema  :-\.

Saludos

"El Hombre, en su orgullo, creó a Dios a su imagen y semejanza.”
Nietzsche

leogtz

#include <stdio.h>
int main()
{
    unsigned int n;
    char buffer[100];
    do
    {
        printf("n : ");
        fgets(buffer, 99, stdin);
    } while(sscanf(buffer, "%u", &n) != 1);
    printf("n : %u\n", n);
    return 0;
}
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

[Zero]


#include <stdio.h>

int main()
{
    unsigned int n;
    char buffer[10];
    do
    {
        printf("n : ");
        fgets(buffer,9, stdin);
    } while(sscanf(buffer, "%u", &n) != 1);
    printf("n : %u\n", n);
    getchar();
    return 0;
}


Si meto un número de caracteres menor que el buffer, el getchar() funciona porque stdin está limpio, pero si meto 15 caracteres, getchar() obtiene lo que quedó en stdin sobrante y no hace lo que quería que hiciera.

Saludos

"El Hombre, en su orgullo, creó a Dios a su imagen y semejanza.”
Nietzsche

Eternal Idol

¿Alguna razon para no usar un buffer de entrada de por ejemplo 120 caracteres? fgets no deja basura, a lo sumo no lee mas de lo permitido pero no es lo mismo.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

[Zero]

Cita de: Eternal Idol en 28 Marzo 2011, 10:20 AM
¿Alguna razon para no usar un buffer de entrada de por ejemplo 120 caracteres? fgets no deja basura, a lo sumo no lee mas de lo permitido pero no es lo mismo.

Bueno, pues preferiría evitar que haga eso. Si meto un buffer de 300 bytes pues al usuario no se le va a ocurrir introducir más, y si lo hace es normal que el programa no funcione correctamente, pero si se puede evitar mejor.

Saludos

"El Hombre, en su orgullo, creó a Dios a su imagen y semejanza.”
Nietzsche

Littlehorse

Mas allá de la seguridad de fgets, también es mas estable dado que su comportamiento es predecible. Para lograr lo mismo con scanf hay que jugar bastante con los parámetros, y a la larga queda poco agradable a la vista y un tanto confuso.

No hay nada en C para descartar caracteres (como si lo hay en C++) por lo que si se trata de mantener el estándar la mejor alternativa es hacer una función con el primer código que pusiste y llamarla cuando corresponda -pero cuidado, chequear \n pero también EOF-

Si realmente necesitas mas flexibilidad entonces no te queda alternativa mas que utilizar funciones especificas del sistema ya sea para limpiar el buffer o para modificar el modo de I/O.

Saludos!

An expert is a man who has made all the mistakes which can be made, in a very narrow field.

[Zero]

Gracias, era lo que quería saber, ya no hay duda  ;D.

Saludos

"El Hombre, en su orgullo, creó a Dios a su imagen y semejanza.”
Nietzsche

Maurice_Lupin

#48
Soy nuevo en el foro, asi que si me equivoco me lo hacen saber =) . No sabia si crear un nuevo tema, en fin. Aqui comparto unas funciones que hace tiempito hice para leer en consola, intente limitar los caracteres, si tienen sugerencias se los agradeceria. Por cierto hay alguna función estandar que haga lo mismo que getch(); para no usar la libreria conio.h, este código lo compile con Dev C++ 4.9

libreria.h
Código (cpp) [Seleccionar]

#include<conio.h>
// esta función lee caracteres limitando la cantidad de estos
void ygets(char *c, register int n)
 {register char car;
  register int t;  
  for(t=0; t<n ;) //lee hasta el maximo de caracteres
     {car=getch(); // caracter por caracter
      switch(car)
        {// si presionaste enter, ingresa caracter nulo
         // y termina el bucle
         case '\r': c[t]='\0' ;return;
         // si presionaste delete, retrocede, imprime espacio
         // y vuelve a retroceder, da la impresión que no
         // presionaste nada =)
         case '\b': if(t>0) {t-- ;printf("\b \b");};
         break;
         // muestra lo demas y almacena en nuestra variable
         default: putchar(car); c[t]=car; t++;
        }  
     }
  c[n]='\0';  
 }

// casi lo mismo quet ygets(), pero sólo
// admite numeros en el switch
void LeerN(char *c, int n)
 {register char car;
  register int t;
  for(t=0;t<n;)
     {car=getch();
      switch(car)
        {case '\r': c[t]='\0' ;return;
         case '\b': if(t>0) {t-- ;printf("\b \b");}; break;
         case '0':case '1':case '2':case '3':case '4':case '5':
         case '6':case '7':case '8':case '9':
              c[t]=car;putchar(car);t++;break;            
         default: break;
        }  
     }
  c[n]='\0';  
 }

// para leer los passwords hace lo mismo que ygets()
// pero muestra "*" en lugar de caracteres o.0!
void leerPass(char *c, int n)
 {register char car;
  register int t;
  for(t=0;t<n;)
     {car=getch();
      switch(car)
        {case '\r': c[t]='\0' ;return;
         case '\b': if(t>0) {t-- ;printf("\b \b");}; break;
         default: {putchar('*');
                  c[t]=car; t++;}
        }
     }
  c[n]='\0';  
 }



Código (cpp) [Seleccionar]

#include <stdio.h>
#include <iostream>
#include "libreria.h"


int main(int argc, char *argv[])
{   char t[15];  
   
   printf("Max 9 digitos \n");
   printf("Solo numeros: "); LeerN(t,9);    
   printf("\nnum: "); printf("%s \n",t);
   //-----------------------
   printf("\nMax 9 caracteres");    
   printf("\nCualquier caracter: "); ygets(t,9);
   printf("\nCadena: "); printf("%s \n",t);    
   //------------------------
   printf("\nMax 5 caracteres");
   printf("\nLee Pass: "); leerPass(t,5);
   printf("\nIngreso: "); printf("%s",t);    
   getch();
   return EXIT_SUCCESS;
}
Un error se comete al equivocarse.

gowend

Gowend132 El conocimiento es LIBRE!!!