Test Foro de elhacker.net SMF 2.1

Programación => Programación C/C++ => Mensaje iniciado por: m@o_614 en 12 Octubre 2013, 04:29 AM

Título: sustituir scanf
Publicado por: m@o_614 en 12 Octubre 2013, 04:29 AM
Saludos

Tengo el siguiente codigo en el que le ingresas datos a una estructura x, el programa compila correctamente pero tengo una duda, tengo entendido que cuando alternas una funcion como fgets() y scanf() te da problemas, y para esto le puse un ciclo while con un getchar(). Pero queria saber si podia sustituir el scanf por otra funcion que no me provoque basura en el buffer, para asi no tener que ponerle el while(getchar()!= '\n')

#include <stdio.h>
#include <stdlib.h>
#define TAM 20
#define MAX 10
typedef struct datos
{
   char nombre[TAM];
   int edad;
   char ciudad_residencia[TAM];
}Persona;

void entrada(Persona *p);

int main()
{
   Persona p;
   int i;
   for(i = 0;i < 10;i++)
      entrada(&p);
   return 0;
}

void entrada(Persona *p)
{
   printf("Dame nombre:\n");
   fgets(p->nombre,TAM,stdin);
   printf("Dame edad:\n");
   while(getchar()!='\n')
   scanf("%d",&p->edad);
   printf("Dame ciudad de residencia:\n");
   fgets(p->ciudad_residencia,TAM,stdin);
}


gracias
Título: Re: sustituir scanf
Publicado por: Eternal Idol en 12 Octubre 2013, 11:46 AM
fgets
+
sscanf

http://foro.elhacker.net/programacion_cc/zanjar_de_una_vez_fflushstdin-t265125.0.html;msg1294511
Título: Re: sustituir scanf
Publicado por: m@o_614 en 14 Octubre 2013, 19:19 PM
Saludos Eternal Idol, por lo que he entendido la funcion sscanf obtiene la entrada de un arreglo y no de un stream, entonces si yo quisiera ponerle un stdin para indicarle que va a tomar la entrada de lo que le ingrese por el teclado me va a dar error, que puedo hacer en este caso?

de antemano gracias
Título: Re: sustituir scanf
Publicado por: Eternal Idol en 14 Octubre 2013, 19:42 PM
Para eso se llama primero a fgets con stdin, fijate en el enlace que deje antes.
Título: Re: sustituir scanf
Publicado por: m@o_614 en 15 Octubre 2013, 22:28 PM
muchas gracias Eternal Idol ya cheque el enlace que dejaste, y ya pude hacer el codigo que me tiene que ingresar datos de una estructura en un archivo, cerrarlo y despues que me imprima en pantalla los datos que se habian guardado, pero tengo otra duda, cada vez que utilizas fgets() es necesario quitarle el salto de linea '\n', se recomienda hacer eso?? y tambien en el sscanf si quiero que lo que me ingrese sea un entero no se desperdicia espacio en el array que le puse asi:

void entrada(Persona *p)
{
    char cad[10];
    printf("Dame nombre:\n");
    fgets(p->nombre,MAX,stdin);
    printf("Dame edad:\n");
    fgets(cad,10,stdin);// aqui tiene una array de 10 elementos pero solo ocupo un int
    sscanf(cad,"%d",&p->edad);
}


aqui esta el codigo completo

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20
/*
   Crear un "struct" que almacene los siguientes datos de una persona: nombre, edad, ciudad de residencia.
   Pedir al usuario esos datos de una persona y guardarlos en un fichero llamado "gente.dat", cerrar el fichero,
   volverlo a abrir para lectura y mostrar los datos que se habían guardado.
*/
typedef struct datos
{
    char nombre[MAX];
    int edad;
    char ciudad_residencia[MAX];
}Persona;

void entrada(Persona *p);
void mostrar(FILE *ap);

int main()
{
    FILE *fd,*ap;
    Persona p;
    if((fd = fopen("F:\\gente.txt","w"))!= NULL)
    {
        entrada(&p);
        fprintf(fd,"%s\n",p.nombre);
        fprintf(fd,"%d\n",p.edad);
        fprintf(fd,"%s\n",p.ciudad_residencia);
        fclose(fd);
        if((ap = fopen("F:\\gente.txt","r"))!= NULL);
           mostrar(ap);
    }
    else
       printf("No se pudo crear archivo");
    return 0;
}

void entrada(Persona *p)
{
    char cad[10];
    printf("Dame nombre:\n");
    fgets(p->nombre,MAX,stdin);
    printf("Dame edad:\n");
    fgets(cad,10,stdin);
    sscanf(cad,"%d",&p->edad);
    printf("Dame ciudad de residencia:\n");
    fgets(p->ciudad_residencia,MAX,stdin);
    system("cls");
}

void mostrar(FILE *ap)
{
    int car;
    while((car = fgetc(ap))!= EOF)
       printf("%c",car);
}
Título: Re: sustituir scanf
Publicado por: Eternal Idol en 15 Octubre 2013, 23:28 PM
Cita de: m@o_614 en 15 Octubre 2013, 22:28 PMmuchas gracias Eternal Idol ya cheque el enlace que dejaste, y ya pude hacer el codigo que me tiene que ingresar datos de una estructura en un archivo, cerrarlo y despues que me imprima en pantalla los datos que se habian guardado, pero tengo otra duda, cada vez que utilizas fgets() es necesario quitarle el salto de linea '\n', se recomienda hacer eso?? y tambien en el sscanf si quiero que lo que me ingrese sea un entero no se desperdicia espacio en el array que le puse asi:

De nadas. Partiendo de la base de que esta el salto de linea (dependera del tamaño que le pases a fgets y lo que escriba el usuario) si lo que queres guardar no es una linea en si misma entonces tiene sentido sacarlo. cad solo tiene como ambito entrada, cuando la funcion retorna esos caracteres en la pila vuelven a estar disponibles.
Título: Re: sustituir scanf
Publicado por: m@o_614 en 16 Octubre 2013, 05:10 AM
una ultima pregunta, si le quiero hacer una modificacion al codigo y en vez de que me guarde los datos de la estructura en el archivo con fprintf quiero que lo haga con fwrite, ya no funciona como lo hacia con fprintf ahora me imprime basura, por que sucede esto??

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20
/*
   Crear un "struct" que almacene los siguientes datos de una persona: nombre, edad, ciudad de residencia.
   Pedir al usuario esos datos de una persona y guardarlos en un fichero llamado "gente.dat", cerrar el fichero,
   volverlo a abrir para lectura y mostrar los datos que se habían guardado.
*/
typedef struct datos
{
    char nombre[MAX];
    int edad;
    char ciudad_residencia[MAX];
}Persona;

void entrada(Persona *p);
void mostrar(FILE *ap);

int main()
{
    FILE *fd,*ap;
    Persona p;
    if((fd = fopen("F:\\gente.txt","w"))!= NULL)
    {
        entrada(&p);
        fwrite(&p,sizeof(Persona),1,fd);
        fclose(fd);
        if((ap = fopen("F:\\gente.txt","r"))!= NULL);
           mostrar(ap);
    }
    else
       printf("No se pudo crear archivo");
    return 0;
}

void entrada(Persona *p)
{
    char cad[10];
    printf("Dame nombre:\n");
    fgets(p->nombre,MAX,stdin);
    printf("Dame edad:\n");
    fgets(cad,10,stdin);
    sscanf(cad,"%d",&p->edad);
    printf("Dame ciudad de residencia:\n");
    fgets(p->ciudad_residencia,MAX,stdin);
    system("cls");
}

void mostrar(FILE *ap)
{
    int car;
    while((car = fgetc(ap))!= EOF)
       printf("%c",car);
}

Título: Re: sustituir scanf
Publicado por: Eternal Idol en 16 Octubre 2013, 09:32 AM
fwrite hace exactamente lo que vos le decis, ahi estas pasandole sizeof(Persona) como tamaño y eso incluye TODOS los bytes de las cadenas, aunque estas esten terminadas antes ...
Título: Re: sustituir scanf
Publicado por: m@o_614 en 17 Octubre 2013, 00:36 AM
ya entendi en donde estaba el error, sizeof(Persona) es igual a 44 porque toma las elementos de la struct completos, otra duda, estaba leyendo en una pagina de internet y me decia que cuando estoy guardando estructuras en un archivo de texto tengo que hacerlo campo por campo, o sea que tendria que usar 3 fwrites() y cuando estoy abriendo el archivo en binario puedo hacerlo todo en un solo paso, si es asi o no?

gracias de nuevo
Título: Re: sustituir scanf
Publicado por: Eternal Idol en 17 Octubre 2013, 00:44 AM
Si inicializas todo a 0 (asi por ejemplo se sabe donde termina la cadena) y no te importa escribir mas bytes de los necesarios podes escribir la estructura entera.
Título: Re: sustituir scanf
Publicado por: m@o_614 en 17 Octubre 2013, 17:10 PM
Saludos

ya le puse que me escribiera con los fwrite, uno para cada campo porque no queria escribir bytes de mas, pero en el segundo fwrite() no me imprime el numero correcto, no se si es porque fwrite el primer argumento tiene que ser una cadena o arreglo

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20
/*
   Crear un "struct" que almacene los siguientes datos de una persona: nombre, edad, ciudad de residencia.
   Pedir al usuario esos datos de una persona y guardarlos en un fichero llamado "gente.dat", cerrar el fichero,
   volverlo a abrir para lectura y mostrar los datos que se habían guardado.
*/
typedef struct datos
{
    char nombre[MAX];
    int edad;
    char ciudad_residencia[MAX];
}Persona;

void entrada(Persona *p);
void mostrar(FILE *ap);

int main()
{
    FILE *fd,*ap;
    Persona p;
    if((fd = fopen("F:\\gente.txt","w"))!= NULL)
    {
        entrada(&p);
        fwrite(p.nombre,sizeof(char),strlen(p.nombre),fd);
        fwrite(&p.edad,sizeof(int),1,fd);
        fwrite(p.ciudad_residencia,sizeof(char),strlen(p.ciudad_residencia),fd);
        fclose(fd);
        if((ap = fopen("F:\\gente.txt","r"))!= NULL);
           mostrar(ap);
    }
    else
       printf("No se pudo crear archivo");
    return 0;
}

void entrada(Persona *p)
{
    char cad[10];
    printf("Dame nombre:\n");
    fgets(p->nombre,MAX,stdin);
    printf("Dame edad:\n");
    fgets(cad,10,stdin);
    sscanf(cad,"%d",&p->edad);
    printf("Dame ciudad de residencia:\n");
    fgets(p->ciudad_residencia,MAX,stdin);
    system("cls");
}

void mostrar(FILE *ap)
{
    int car;
    while((car = fgetc(ap))!= EOF)
       printf("%c",car);
}


disculpa que haga tantas preguntas, pero es que apenas estoy empezando a familiarizarme con archivos, gracias
Título: Re: sustituir scanf
Publicado por: Eternal Idol en 17 Octubre 2013, 17:59 PM
Revisa la documentacion de todas las funciones que usas, especilamente fopen. No podes esperar que printf("%c",car); funcione, escribiste un int con la dead, no un caracter.