Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Problema creando agenda con ficheros

Estas en el tema de Problema creando agenda con ficheros en el foro de C/C++ en Foros del Web. Hola. He hecho este código: @import url("http://static.forosdelweb.com/clientscript/vbulletin_css/geshi.css"); Código C: Ver original /*Una agenda que maneje los siguientes datos: nombre, dirección, tlf móvil, email, y día, ...
  #1 (permalink)  
Antiguo 10/02/2012, 10:20
 
Fecha de Ingreso: enero-2012
Mensajes: 68
Antigüedad: 12 años, 11 meses
Puntos: 0
Problema creando agenda con ficheros

Hola.

He hecho este código:

Código C:
Ver original
  1. /*Una agenda que maneje los siguientes datos: nombre, dirección, tlf móvil, email, y día,
  2. mes y año de nacimiento (estos tres últimos datos deberán ser números enteros
  3. cortos). Deberá tener capacidad para 100 fichas. Se deberá poder añadir un dato
  4. nuevo, visualizar los nombres de las fichas existentes, o mostrar todos los datos de una
  5. persona (se preguntará al usuario cual es el nombre de esa persona que quiere
  6. visualizar). Al empezar el programa, leerá los datos de un fichero llamado “agenda.dat”
  7. (si existe). Al terminar, guardará todos los datos en ese fichero.*/
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12.  
  13. int main()
  14. {
  15.     struct
  16.     {
  17.       char nombre[10];
  18.       char direccion[15];
  19.       int movil;
  20.       char email[20];
  21.       short int dia, mes, ano;
  22.     }datos[100];
  23.     char lineas[500],comprobar[10];
  24.     FILE* fichero;
  25.     int opcion,posicion,tamano,i,j,aux;
  26.    
  27.     fichero = fopen("agenda.dat", "r+b");
  28.     if(fichero != NULL)
  29.     {
  30.    
  31.     while(! feof(fichero)) //Leemos los datos que contiene al principio
  32.     {
  33.       fgets(lineas,25,fichero);
  34.     }
  35.    
  36.     /*posicion actual*/
  37.     posicion = ftell(fichero);
  38.  
  39.     /* final del fichero */
  40.     fseek(fichero,0,SEEK_END);
  41.  
  42.     /* total de lineas */
  43.     tamano = ftell(fichero);
  44.  
  45.    
  46.     fseek(fichero,posicion,SEEK_SET);
  47.  
  48.     i = tamano / sizeof(datos);
  49.    
  50.     do
  51.     {
  52.     do
  53.     {
  54.     printf("Elija una opcion\n");
  55.     printf("1. Introducir datos\n");
  56.     printf("2. Visualizar nombres de las fichas existentes\n");
  57.     printf("3. Mostrar todos los datos de una persona\n");
  58.     printf("4. Salir");
  59.     scanf("%d",&opcion);
  60.    
  61.     switch(opcion)
  62.     {
  63.       case 1:
  64.            printf("Introduce un nombre: ");
  65.            fgets(datos[10].nombre, 10, stdin);
  66.            
  67.            printf("Introduce una direccion: ");
  68.            fgets(datos[i].direccion, 8, stdin);
  69.            printf("Introduce un movil: ");
  70.            scanf("%d",&datos[i].movil);
  71.            while(getchar() != '\n');
  72.            printf("Introduce correo electronico: ");
  73.            fgets(datos[i].email, 50, stdin);
  74.            printf("Introduce dia de nacimiento: ");
  75.            scanf("%d",&datos[i].dia);
  76.            while(getchar() != '\n');
  77.            printf("Introduce mes de nacimiento: ");
  78.            scanf("%d",&datos[i].mes);
  79.            while(getchar() != '\n');
  80.            printf("Introduce ano de nacimiento: ");
  81.            scanf("%d",&datos[i].ano);
  82.            i++;
  83.            break;
  84.       case 2:
  85.            for(j=0;j<=i;j++)
  86.            {
  87.              puts(datos[j].nombre);
  88.            }
  89.              
  90.              
  91.            break;
  92.       case 3:
  93.           printf("Introduce el nombre de la persona de la que desea visualizar los datos:");
  94.           fgets(comprobar, 10, stdin);
  95.          
  96.           for(j=0;j<=i;j++)
  97.           {
  98.             if(strcmp(datos[j].nombre,comprobar)==0)
  99.             {
  100.               printf("Nombre: %s\n",datos[j].nombre);
  101.               printf("Direccion: %s\n",datos[j].direccion);
  102.               printf("Movil: %d\n",datos[j].movil);
  103.               printf("Email: %s\n",datos[j].email);
  104.               printf("Dia de nacimiento: %d\n",datos[j].dia);
  105.               printf("Mes de nacimiento: %d\n",datos[j].mes);
  106.               printf("Ano de nacimiento: %d\n",datos[j].ano);
  107.             }
  108.           }
  109.            break;
  110.       case 4:
  111.            break;
  112.       default:
  113.               printf("Opcion no valida!\n");
  114.     }
  115.    
  116.     }while(opcion<1||opcion>4);
  117.     }while(opcion!=4);
  118.     }
  119.     aux=i;
  120.     for(i=0;i<=aux;i++)
  121.     {
  122.       fprintf(fichero, "%s\n", datos[i].nombre);
  123.       fprintf(fichero, "%s\n", datos[i].direccion);
  124.       fprintf(fichero, "%d\n", datos[i].movil);
  125.       fprintf(fichero, "%s\n", datos[i].email);
  126.       fprintf(fichero, "%d\n", datos[i].dia);
  127.       fprintf(fichero, "%d\n", datos[i].mes);
  128.       fprintf(fichero, "%d\n", datos[i].ano);
  129.       }
  130.    fclose(fichero);
  131.    
  132.     getchar();
  133.     printf("\n\nPulse una tecla para continuar");
  134.     getchar();
  135.     return 0;
  136. }

El problema es en el switch, en el case 1.

Ahí lo que quiero hacer es pedir los datos. Pues, al compilar, en la consola, elijo la opción 1. Directamente me sale "Introduce un nombre: Introduce una direccion: ". Y ahí se detiene para que introduzca la dirección.

¿Qué puedo hacer para que pare en "Introduzca un nombre"?

También me gustaría saber si os parece que el problema está bien planteado, y que si una vez solucionado el error que os acabo de exponer funcionará el programa adecuadamente, o falta algo por hacer.

Gracias.

Saludos.
  #2 (permalink)  
Antiguo 10/02/2012, 11:46
 
Fecha de Ingreso: diciembre-2011
Ubicación: Crespo - Entre Rios
Mensajes: 155
Antigüedad: 13 años
Puntos: 25
Respuesta: Problema creando agenda con ficheros

la funcion fgets es para leer desde un fichero, utiliza char* gets(char* cadena)


mas info fgets

mas info gets
  #3 (permalink)  
Antiguo 10/02/2012, 12:37
 
Fecha de Ingreso: diciembre-2011
Ubicación: CABA
Mensajes: 433
Antigüedad: 13 años
Puntos: 94
Respuesta: Problema creando agenda con ficheros

hola DickGumshoe! el problema esta en el scanf de la linea 59, al introducir la opcion se ingrese un numero seguido del enter, el cual queda almacenado en un bufer que luego es tomado por fgets. Pone getchar(); despues de la linea 59

Otra cosa: no entiendo xq haces
Código C:
Ver original
  1. while(! feof(fichero)) //Leemos los datos que contiene al principio
  2.     {
  3.       fgets(lineas,25,fichero);
  4.     }
segun el comentario lees los datos que tenes al principio hasta que sea EOF. Luego almacenas en posicion el valor devuelto por ftell, pero el valor devuelto de ftell va a ser el final del archivo.
Luego con:
Código C:
Ver original
  1. fseek(fichero,0,SEEK_END);
volves a posicionar el cursor en el final del archivo y volves a almacenar el valor devuelto por ftell en tamano el cual va a tener el mismo valor que posicion

Otra cosa que no entiendo es:
Código C:
Ver original
  1. i = tamano / sizeof(datos);
¿para que es esta division?
esta division va a dar 0(cero) siempre y cuando tamano no sea mas grande que sizeof(datos). Acordate que datos[100] es un arreglo de estructuras donde cada posicion del arreglo tiene un tamaño igual a la estructura

Saludos
  #4 (permalink)  
Antiguo 10/02/2012, 15:30
 
Fecha de Ingreso: enero-2012
Mensajes: 68
Antigüedad: 12 años, 11 meses
Puntos: 0
Respuesta: Problema creando agenda con ficheros

Muchas gracias por responder. Ya he puesto getchar(); debajo del scanf.

Lo que pretendía con lo primero es leer todos los datos que tiene el archivo inicialmente. Después con

Código C:
Ver original
  1. /*posicion actual*/
  2.     posicion = ftell(fichero);
  3.  
  4.     /* final del fichero */
  5.     fseek(fichero,0,SEEK_END);
  6.  
  7.     /* total de lineas */
  8.     tamano = ftell(fichero);
  9.  
  10.    
  11.     fseek(fichero,posicion,SEEK_SET);
  12.  
  13.     i = tamano / sizeof(datos);

Guardo la posición en la que estoy. Me voy al final del fichero, para ver cuántas líneas tiene. Vuelvo donde estaba al principio, y en la variable i guardo un valor. Con esto pretendo que al iniciar el programa sepa cuántas fichas he guardado, para que no me sobrescriba los datos, sino que, si he guardado 5 datos, me guarde el 6º, y no el 1º otra vez.

Gracias.

Saludos.
  #5 (permalink)  
Antiguo 10/02/2012, 16:40
 
Fecha de Ingreso: diciembre-2011
Ubicación: CABA
Mensajes: 433
Antigüedad: 13 años
Puntos: 94
Respuesta: Problema creando agenda con ficheros

Hola!! mmm t recomiendo algo, pone un printf debajo de posicion tamano e i imprimiendo el valor de cada uno. Vas a ver que posicion y tamano son iguales y que la variable i siempre es 0(cero) a menos que tamano sea>=6000.

Otra cosa ftell no devuelve la cantidad de lineas que tiene un archivo sino el desplazamiento a partir del origen, donde cada desplazamiento es un byte

Saludos
  #6 (permalink)  
Antiguo 10/02/2012, 16:42
 
Fecha de Ingreso: enero-2012
Mensajes: 68
Antigüedad: 12 años, 11 meses
Puntos: 0
Respuesta: Problema creando agenda con ficheros

Entonces... ¿Qué me recomiendas hacer para que la variable i guarde la ficha por la que voy?

Gracias.

Saludos
  #7 (permalink)  
Antiguo 10/02/2012, 17:42
 
Fecha de Ingreso: diciembre-2011
Ubicación: CABA
Mensajes: 433
Antigüedad: 13 años
Puntos: 94
Respuesta: Problema creando agenda con ficheros

Cuando decis ¿Qué me recomiendas hacer para que la variable i guarde la ficha por la que voy? te referis a que vos no queres sobreescribir la informacion que ya contiene el archivo ??? si es asi solo basta con posicionar el cursor del fichero al final
Código C:
Ver original
  1. fseek(fichero,0,SEEK_END);

De esta manera no pisas la info contenida en el archivo

Saludos
  #8 (permalink)  
Antiguo 11/02/2012, 08:23
 
Fecha de Ingreso: enero-2012
Mensajes: 68
Antigüedad: 12 años, 11 meses
Puntos: 0
Respuesta: Problema creando agenda con ficheros

Pensé en hacer eso, pero entonces no se me ocurre qué debo hacer para leer los datos de la agenda, ya que si i al empezar siempre vale 0, el algoritmo que he hecho para buscar las personas (case 2 y 3 del switch) no valen, y sin tener un valor i no se me ocurre ningún otro...

Bueno, quizá uno, pero no sé si vale, o si es fácil de implementar. Es este:

Leer los datos del fichero hasta que linea (variable creada donde guardo cada línea del fichero) sea igual a comprobar (la variable creada donde le pedía al usuario que metiera el nombre de una persona, y le daba todos sus datos). Entonces, a partir de ahí, leo las líneas 1, 2, 3, 4, 5 y 6, que son las correspondientes a la dirección, móvil, email y día, mes y año de nacimiento.

Bueno, ese sería el del case 3. Para el case 2 se me ocurre leer la primera línea, en la que debería estar el primer nombre, y, a partir de ahí, leer de 7 en 7 líneas del archivo.

No sé si lo que estoy diciendo es imposible, o difícil de hacer para alguien tan novato como yo... ¿Se puede así? ¿Hay otra forma de hacerlo más sencilla?

Gracias.

Saludos.
  #9 (permalink)  
Antiguo 11/02/2012, 13:50
 
Fecha de Ingreso: diciembre-2011
Ubicación: CABA
Mensajes: 433
Antigüedad: 13 años
Puntos: 94
Respuesta: Problema creando agenda con ficheros

Hola! ¿formas de hacer este programa? hay varias ¿cual es la forma mas sencilla? en lo particular a mi no me interesa mucho eso, con el tiempo vas a adquirir conocimientos que te va a facilitar hacer el programa.

Con respecto a lo que planteas para leer el archivo en cierta forma esta bien, al principio no le di importancia ya que no hacias nada con el pero lei el enunciado del programa y si tenes que leer el archivo.
En ves de almacenar lo leido del archivo en el arreglo lineas, la idea del programa es que lo hagas en el arreglo de estructuras(en datos[100]). Para eso te recomiendo que uses fscanf:
Código C:
Ver original
  1. while(!feof(fichero)) //Leemos los datos que contiene el archivo
  2.         {
  3.           c=fscanf(fichero,"%s",datos[i].nombre);
  4.           fscanf(fichero,"%s",datos[i].direccion);
  5.           fscanf(fichero,"%d",&datos[i].movil);
  6.           fscanf(fichero,"%s",datos[i].email);
  7.           fscanf(fichero,"%d",&datos[i].dia);
  8.           fscanf(fichero,"%d",&datos[i].mes);
  9.           fscanf(fichero,"%d",&datos[i].ano);
  10.           [B]if(c!=-1) i++;[/B]// evita que i incremente erroneamente
  11.        }
De esta manera vas a guardar todos los datos del archivo en el arreglo. Fijate en el if, lo puse xq, a pesar de que el archivo no tenga nada, va a entrar igual en el while por lo que la variable i va a incrementar(lo cual estaria mal). Con el if, i solo va a incrementar cada vez que se lea correctamente del archivo (fscanf retorna -1 cuando hay un error)


Pasando en limpio el codigo quedaria asi:

Código C:
Ver original
  1. /*Una agenda que maneje los siguientes datos: nombre, dirección, tlf móvil, email, y día,
  2.     mes y año de nacimiento (estos tres últimos datos deberán ser números enteros
  3.     cortos). Deberá tener capacidad para 100 fichas. Se deberá poder añadir un dato
  4.     nuevo, visualizar los nombres de las fichas existentes, o mostrar todos los datos de una
  5.     persona (se preguntará al usuario cual es el nombre de esa persona que quiere
  6.     visualizar). Al empezar el programa, leerá los datos de un fichero llamado “agenda.dat”
  7.     (si existe). Al terminar, guardará todos los datos en ese fichero.*/
  8.      
  9.     #include <stdio.h>
  10.     #include <stdlib.h>
  11.     #include <string.h>
  12.      
  13.     int main()
  14.     {
  15.         struct
  16.         {
  17.           char nombre[10];
  18.           char direccion[15];
  19.           int movil;
  20.           char email[20];
  21.            int dia, mes, ano;
  22.         }datos[100];
  23.         char lineas[500],comprobar[10];
  24.         FILE* fichero;
  25.         int opcion,posicion,tamano,i=0,j,aux;
  26.        int c;
  27.         fichero = fopen("agenda.dat", "r+b");
  28.         if(fichero != NULL)
  29.         {
  30.        
  31.         while(!feof(fichero)) //Leemos los datos que contiene el archivo y los almacenamos en el arreglo datos[100]
  32.         {
  33.           c=fscanf(fichero,"%s",datos[i].nombre);
  34.           fscanf(fichero,"%s",datos[i].direccion);
  35.           fscanf(fichero,"%d",&datos[i].movil);
  36.           fscanf(fichero,"%s",datos[i].email);
  37.           fscanf(fichero,"%d",&datos[i].dia);
  38.           fscanf(fichero,"%d",&datos[i].mes);
  39.           fscanf(fichero,"%d",&datos[i].ano);
  40.           printf("ENTRO WHILE %d\n",c);
  41.           if(c!=-1)i++; // evita incrementar erroneamente
  42.         }
  43.  
  44.         /*posicion actual*/
  45.         //posicion = ftell(fichero);
  46.         //printf("pos: %d\n",posicion);
  47.      
  48.      /* este rewind es necesario ya que al leer los datos con fscanf el cursor se va desplazando, y si no ponemos
  49.      el rewind luego cuando guardemos (con fprintf) se va a guardar datos repetidos */
  50.        rewind(fichero); //posiciona el cursor al inicio. Igual a fseek(fichero,0,SEEK_SET);
  51.      
  52.         do
  53.         {
  54.         do
  55.         {
  56.         printf("iii: %i\n",i);
  57.         printf("Elija una opcion\n");
  58.         printf("1. Introducir datos\n");
  59.         printf("2. Visualizar nombres de las fichas existentes\n");
  60.         printf("3. Mostrar todos los datos de una persona\n");
  61.         printf("4. Salir\n");
  62.         scanf("%d",&opcion);
  63.         getchar();
  64.        
  65.         switch(opcion)
  66.         {
  67.           case 1:
  68.                printf("Introduce un nombre: ");
  69.                //fgets(datos[i].nombre, 10, stdin);
  70.                scanf("%s",datos[i].nombre);
  71.                //getchar
  72.                printf("Introduce una direccion: ");
  73.                //fgets(datos[i].direccion, 8, stdin);
  74.                scanf("%s",datos[i].direccion);
  75.                printf("Introduce un movil: ");
  76.                scanf("%d",&datos[i].movil);
  77.                while(getchar() != '\n');
  78.                printf("Introduce correo electronico: ");
  79.                //fgets(datos[i].email, 50, stdin);
  80.                scanf("%s",datos[i].email);
  81.                printf("Introduce dia de nacimiento: ");
  82.                scanf("%d",&datos[i].dia);
  83.                while(getchar() != '\n');
  84.                printf("Introduce mes de nacimiento: ");
  85.                scanf("%d",&datos[i].mes);
  86.                while(getchar() != '\n');
  87.                printf("Introduce ano de nacimiento: ");
  88.                scanf("%d",&datos[i].ano);
  89.                i++;
  90.                break;
  91.           case 2:
  92.                for(j=0;j<i;j++)
  93.                {
  94.                  printf("%s\n",datos[j].nombre);
  95.                }
  96.                  
  97.                  
  98.                break;
  99.           case 3:
  100.               printf("Introduce el nombre de la persona de la que desea visualizar los datos:");
  101.              scanf("%s",comprobar);
  102.               for(j=0;j<i;j++)
  103.               {
  104.                 if(strcmp(datos[j].nombre,comprobar)==0)
  105.                 {
  106.                   printf("Nombre: %s\n",datos[j].nombre);
  107.                   printf("Direccion: %s\n",datos[j].direccion);
  108.                   printf("Movil: %d\n",datos[j].movil);
  109.                   printf("Email: %s\n",datos[j].email);
  110.                   printf("Dia de nacimiento: %d\n",datos[j].dia);
  111.                   printf("Mes de nacimiento: %d\n",datos[j].mes);
  112.                   printf("Ano de nacimiento: %d\n",datos[j].ano);
  113.                 }
  114.               }
  115.                break;
  116.           case 4:
  117.                break;
  118.           default:
  119.                   printf("Opcion no valida!\n");
  120.         }
  121.        
  122.         }while(opcion<1||opcion>4);
  123.        
  124.         }while(opcion!=4);
  125.         }
  126.         aux=i;
  127.         for(i=0;i<aux;i++)
  128.         {
  129.           fprintf(fichero, "%s\n", datos[i].nombre);
  130.           fprintf(fichero, "%s\n", datos[i].direccion);
  131.           fprintf(fichero, "%d\n", datos[i].movil);
  132.           fprintf(fichero, "%s\n", datos[i].email);
  133.           fprintf(fichero, "%d\n", datos[i].dia);
  134.           fprintf(fichero, "%d\n", datos[i].mes);
  135.           fprintf(fichero, "%d\n", datos[i].ano);
  136.           }
  137.        fclose(fichero);
  138.        
  139.         printf("\n\nPulse una tecla para continuar");
  140.         getchar();
  141.         return 0;
  142.     }

A diferencia de tu programa decidi usar scanf en ves de fgets ¿por que? porque fgets guarda el caracter nueva linea: \n en el bufer lo cual trae mucho dolor de huevo. Si queres proba el fgets pero no te lo recomiendo para este programa. Ademas fijate que agregue la funcion rewind, fijate el comentario que hice.

Espero se entienda el programa cualquier cosa pregunta

Saludos

Última edición por cesar_casla; 11/02/2012 a las 14:01
  #10 (permalink)  
Antiguo 11/02/2012, 14:13
 
Fecha de Ingreso: enero-2012
Mensajes: 68
Antigüedad: 12 años, 11 meses
Puntos: 0
Respuesta: Problema creando agenda con ficheros

¡Muchísimas gracias!

Gracias a tu ayuda he logrado entender el programa!

Saludos.

Etiquetas: agenda, creando, fichero, ficheros, funcion, programa, string, struct
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 02:47.