[ Foro de C ]

duda ejercicio pagina 93 del curso

15-Oct-2009 01:50
Roberto rrs
13 Respuestas

Hola.
He conseguido llegar hasta aqui sin problemas, pero este ejercicio me esta volviendo loco.
Por eso agradeceria que me respondierais sobre como hacer de manera correcta la parte de visualizar los nombres de todas las fichas existentes, os pongo la parte que no funciona de mi programa:

case 2: /*Visualizar los nombres de las fichas existentes*/

              fichero=fopen("agenda.dat", "rt");
              b=0;
              while (!feof(fichero))
              {   fgets (fichas[b].nombre, 15, fichero);
                  puts (fichas[b].nombre);
                  puts ("\n");
                  if (fichas[b].nombre==NULL) break;
                  b++;
              }
               fclose (fichero);

El struct que he creado es el siguiente:
struct
    { char nombre[15];
      char direccion[30];
      int movil;
      unsigned short dia;
      unsigned short mes;
      unsigned short anyo;
      } fichas[100];

Cuando ejecuto este programa lo que pasa es que me muestra todo el fichero y no solo los nombres de las fichas.

saludos.


22-Oct-2009 07:54
Jesús S.

¡Hola!

Yo también ando enredado en este mismo ejercicio de la página 93, pero más retrasado que tú. De todos modos te voy a decir un par de cosas por si te sirven.

Doy por sentado que tendrás definido b como int. Por otro lado la condición while (!feof(fichero)) pienso que es válida si estás mirando el archivo completo, pero si sólo revisas la primera línea no te encontrará el feof. Quizá modificando  la condición a que encuentre vacío ("") el nombre te pueda ayudar algo.

Esto son sólo sugerencias. La verdad es que no sé por qué diablos te muestra el archivo completo. A ver que es lo que dice el profe.

Saludos.


22-Oct-2009 21:05
mario moreno

Si lo que quieres es ver solamente los nombres de las diferentes fichas que tienes creadas, tendras que valerte del bucle "for".

ejem. for (i=0; i<b; i++) (para que haga un recorrido por las fichas. Espero haberte ayudado.


22-Oct-2009 23:33
Roberto rrs

Hola.
Os pongo todo lo que llevo echo de programa, sigo liado con la opcion 2.
ya consigo que solo muestre los nombres, el problema es que solo los muestra cuando los escribo en la misma ejecucion del programa.
Si cierro el programa y lo vuelvo a abrir ya no me muestra los nombres.
Los sigo intentando.
Saludos.



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

main ()
{
    struct
    { char nombre[15];
      char direccion[30];
      int movil;
      unsigned short dia;
      unsigned short mes;
      unsigned short anyo;
      } fichas[100];
int opcion,a=0, b;
char textoTemporal[15];
char agenda[80]="c:\\agenda.dat";


FILE* fichero;


do {

printf ("MENU:\n");
printf ("1.-Introducir ficha nueva\n");
printf ("2.-Visualizar los nombres de las fichas existentes\n");
printf ("3.-Mostrar todos los datos de una persona\n");
printf ("4.-Salir\n");
printf ("Elegir una opcion: ");
gets (textoTemporal);
sscanf (textoTemporal, "%d", &opcion);
switch (opcion)
{
      case 1: /*Introducir nueva ficha*/
              fichero=fopen("agenda.dat", "at");
              do {          
              printf ("Introduce nueva ficha:\n");
              printf ("Introduce nombre: ");
              gets (fichas[a].nombre);
              if (strlen(fichas[a].nombre)==0) break;
              fputs (fichas[a].nombre, fichero);
     
             
              printf ("Introduce direccion: ");
              gets (fichas[a].direccion);
              fprintf (fichero, "%30s\n", fichas[a].direccion);
             
              printf ("Introduce movil: ");
              gets (textoTemporal);
              sscanf (textoTemporal, "%10d", &fichas[a].movil);
              fprintf (fichero, "%10d\n", fichas[a].movil);
             
              printf ("Introduce dia: ");
              gets (textoTemporal);
              sscanf (textoTemporal, "%2d", &fichas[a].dia);
              fprintf (fichero, "%2d\n", fichas[a].dia);
             
              printf ("Introduce mes: ");
              gets (textoTemporal);
              sscanf (textoTemporal, "%2d", &fichas[a].mes);
              fprintf (fichero, "%2d\n", fichas[a].mes);
             
              printf ("Introduce anyo: ");
              gets (textoTemporal);
              sscanf (textoTemporal, "%7d", &fichas[a].anyo);
              fprintf (fichero, "%7d\n", fichas[a].anyo);
             
              a++;
              }while (a!=100);
              if (a==100) printf ("YA SE HAN AGOTADO LAS 100 FICHAS");
              fclose (fichero);
              break;
      case 2: /*Visualizar los nombres de las fichas existentes*/
              b=0;
              fichero=fopen("agenda.dat", "rt");
              while (!feof(fichero))
              {   fgets (textoTemporal, 15, fichero);}
              fclose (fichero);
              do {
              fgets (fichas[b].nombre,15, fichero);
              if (strlen(fichas[b].nombre)==0) break;
              puts (fichas[b].nombre);
              b++;}
             while (strlen(fichas[b].nombre)!=0);
             break;
      case 3: /*Mostrar todos los datos de una persona*/
             
             
              break;
      case 4: /*Salir*/
              printf ("FINAL DEL PROGRAMA");
              break;
     
     
      default: /*Opcion no valida*/  
               break;    
      }
} while (opcion!=4);
}

     


23-Oct-2009 16:13
mario moreno

Yo no soy el más indicado para darte consejos, pero yo quitaría esta línea del "do" (puts (fichas[b].nombre);).

Luego haría un bucle "for" y entonces si introduciría esa línea.


23-Oct-2009 16:29
Roberto rrs

Os pongo mis ultimos adelantos, el case 2 ya me funciona a excepción de un ultimo dato que no se porque me sale.
El case 3 todavia no logro que funcione; lo sigo intentando.



case 2: /*Visualizar los nombres de las fichas existentes*/
              b=0,c=0;
              fichero=fopen("agenda.dat", "rt");
              while (!feof(fichero))
              { fgets (linea,30, fichero);
                if (b==c) {puts (linea);
                           c=b+6;}
                b++;
                }
              fclose(fichero);
             break;
      case 3: /*Mostrar todos los datos de una persona*/
              printf ("Escribe el nombre de la ficha que quieres ver: ");
              gets (textoTemporal);
              fichero=fopen("agenda.dat","rt");
              while (!feof(fichero))
              { fgets (linea,30, fichero);
                if (strcmp(textoTemporal, linea)==0)
                   {printf ("Nombre de la ficha: %s", linea);
                    fgets (linea, 30, fichero);
                    printf ("Direccion: %s", linea),
                    fgets (linea, 30, fichero);
                    printf ("Movil: %d", linea);
                    fgets (linea, 30, fichero);
                    printf ("Dia de nacimiento: %d", linea);
                    fgets (linea, 30, fichero);
                    printf ("Mes de nacimiento: %d", linea);
                    fgets (linea, 30, fichero);
                    printf ("Anyo de nacimiento: %d", linea); }
                }
              fclose(fichero);


23-Oct-2009 23:01
Nacho Cabanes (+83)

Un par de mejoras:

- En la opción 2, en general, si haces

while (!feof(fichero))
fgets (linea,30, fichero);
puts(linea);

no muestras sólo los nombres, sino todo lo que contiene el fichero. Lo de contar para mostrar sólo una de cada seis lineas es una solución, pero sería más legible con nombres de variables más expresivos, algo como:

if (lineaActual == lineaAMostrar) ...

Aun así, posiblemente la opción más elegante sería dejar claro que lees el nombre, el tlf, la dirección, etc., con varios "fgets", pero usar sólo un "puts" cuando acabas de leer el nombre.

En cualquier caso, siguiendo el enunciado de forma estricta, deberías leer todos los datos cuando comienza el programa, así que esta opción no buscaría ya en fichero, sino que recorrería el array en memoria, con algo como:

for (i=0; i<cantidadDatos; i++)
 puts(dato[i].nombre);

- En la opción 3, la idea es la misma: recorres el array en memoria, y muestras todos los datos del que coincida, con

for (i=0; i<cantidadDatos; i++)
 if (strcmp(textoTemporal, dato[i].nombre)==0) { ...


24-Oct-2009 00:49
Roberto rrs

En primer lugar darte muchas gracias por tu tiempo y explicaciones.
Ya he corregido el ejercicio y lo he amoldado según me comentas, el unico problema que me queda es que me funciona en la primera ejecucion, cuando cierro y vuelvo a ejecutar ya el case 3 no funciona.
Creo que el problema esta en los espacios con los que se guardan los datos en el fichero, seguire intentando dar con la solucion.

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

main ()
{
    struct
    { char nombre[30];
      char direccion[30];
      char movil[30];
      unsigned short dia;
      unsigned short mes;
      unsigned short anyo;
      } fichas[100];
int opcion, numeroFichas, a=0, b;
char textoTemporal[30], linea[30];


FILE* fichero;

fichero=fopen("agenda.dat", "r+t");
while (!feof(fichero))
{fgets (fichas[a].nombre, 30, fichero);
fgets (fichas[a].direccion, 30, fichero);
fgets (fichas[a].movil, 30, fichero);
fgets (linea, 30, fichero);
sscanf (linea, "%2u", &fichas[a].dia);
fgets (linea, 30, fichero);
sscanf (linea, "%2u", &fichas[a].mes);
fgets (linea, 30, fichero);
sscanf (linea, "%4u", &fichas[a].anyo);
a++;}

do {

printf ("MENU:\n");
printf ("1.-Introducir ficha nueva\n");
printf ("2.-Visualizar los nombres de las fichas existentes\n");
printf ("3.-Mostrar todos los datos de una persona\n");
printf ("4.-Salir\n");
printf ("Elegir una opcion: ");
gets (textoTemporal);
sscanf (textoTemporal, "%d", &opcion);
switch (opcion)
{
      case 1: /*Introducir nueva ficha*/
              do {          
              printf ("Introduce nueva ficha:\n");
              printf ("Introduce nombre: ");
              gets (fichas[a].nombre);
              if (strlen(fichas[a].nombre)==0) break;
              fputs (fichas[a].nombre, fichero);
              fputs ("\n", fichero);
             
              printf ("Introduce direccion: ");
              gets (fichas[a].direccion);
              fputs (fichas[a].direccion, fichero);
              fputs("\n", fichero);
             
              printf ("Introduce movil: ");
              gets (fichas[a].movil);
              fputs (fichas[a].movil, fichero);
              fputs ("\n", fichero);
             
              printf ("Introduce dia: ");
              gets (textoTemporal);
              sscanf (textoTemporal, "%2u", &fichas[a].dia);
              fprintf (fichero, "%2u\n", fichas[a].dia);
             
              printf ("Introduce mes: ");
              gets (textoTemporal);
              sscanf (textoTemporal, "%2u", &fichas[a].mes);
              fprintf (fichero, "%2u\n", fichas[a].mes);
             
              printf ("Introduce anyo: ");
              gets (textoTemporal);
              sscanf (textoTemporal, "%4u", &fichas[a].anyo);
              fprintf (fichero, "%4u\n", fichas[a].anyo);
             
              a++;
              }while (a!=100);
              if (a==100) printf ("YA SE HAN AGOTADO LAS 100 FICHAS");
              break;
      case 2: /*Visualizar los nombres de las fichas existentes*/
              numeroFichas=a-1;
              for (b=0;b<=numeroFichas;b++)
              {puts (fichas[b].nombre);}
             break;
      case 3: /*Mostrar todos los datos de una persona*/
             printf ("Introduce el nombre de la ficha a mostrar: ");
             gets (textoTemporal);
             numeroFichas=a-1;
             for (b=0;b<=numeroFichas;b++)
             { if (strcmp(textoTemporal, fichas[b].nombre)==0)
                  { printf ("Nombre: %s\n", fichas[b].nombre);
                    printf ("Direccion: %s\n", fichas[b].direccion);
                    printf ("Movil: %s\n", fichas[b].movil);
                    printf ("Dia: %u\n", fichas[b].dia);
                    printf ("Mes: %u\n", fichas[b].mes);
                    printf ("Anyo: %u\n", fichas[b].anyo);}
             }
             
              break;
      case 4: /*Salir*/
              printf ("FINAL DEL PROGRAMA");
              fclose(fichero);
              break;
     
     
      default: /*Opcion no valida*/    
               break;    
      }
} while (opcion!=4);
}

     


24-Oct-2009 02:37
Roberto rrs

Ya he solucionado el case3, os lo pongo:

case 3: /*Mostrar todos los datos de una persona*/
             printf ("Introduce el nombre de la ficha a mostrar: ");
             gets (textoTemporal);
             strcat (textoTemporal,"\n");
             numeroFichas=a-1;
             for (b=0;b<=numeroFichas;b++)
             { if (strcmp (textoTemporal, fichas[b].nombre)==0)
                   {printf ("Nombre: %s\n", fichas[b].nombre);
                    printf ("Direccion: %s\n", fichas[b].direccion);
                    printf ("Movil: %s\n", fichas[b].movil);
                    printf ("Dia: %u\n", fichas[b].dia);
                    printf ("Mes: %u\n", fichas[b].mes);
                    printf ("Anyo: %u\n", fichas[b].anyo);}
             }


24-Oct-2009 12:04
Nacho Cabanes (+83)

Perfecto, Roberto, esa es la idea.

Cuando lees con "fgets", conserva el "\n" del final de cada línea, así que para poder comparar tienes dos soluciones:

- Borrar el \n de las frases que lees (por ejemplo, reemplazándolo por un \0)

- Añadir un \n a la frase que quieres comparar, como tú has hecho.

Aun así, la mejor opción es la primera, porque si no, cuando vuelves a guardar en fichero puedes obtener un \n\n, y vas desordenando los datos poco a poco, separándolos entre ellos, y no los leerás bien.


26-Oct-2009 01:35
Roberto rrs

Hola Nacho, en primer lugar muchas gracias por aclarar las dudas y dedicar parte de tu tiempo.
He modificado el programa para quitar el avance de linea, no sabia si se puede hacer directamente, y lo he hecho de esta manera, ¿que tal quedaria asi?:
(Aprovecho para consultarte una duda y es que cuando se lee el fichero el ultimo dato almacenado me lo lee por duplicado y aparece como el ultimo nombre metido cuando eso no es cierto, ¿porque sucede eso?)

while (!feof(fichero))
{fgets (linea, 30, fichero);
strncpy (fichas[a].nombre, linea, (strlen(linea)-1));
fgets (linea, 30, fichero);
strncpy (fichas[a].direccion, linea, (strlen(linea)-1));
fgets (linea, 30, fichero);
strncpy (fichas[a].movil, linea, (strlen(linea)-1));
fgets (linea, 30, fichero);
strncpy (textoTemporal, linea, (strlen(linea)-1));
sscanf (textoTemporal, "%2u", &fichas[a].dia);
fgets (linea, 30, fichero);
strncpy (textoTemporal, linea, (strlen(linea)-1));
sscanf (textoTemporal, "%2u", &fichas[a].mes);
fgets (linea, 30, fichero);
strncpy (textoTemporal, linea, (strlen(linea)-1));
sscanf (textoTemporal, "%4u", &fichas[a].anyo);
a++;}


26-Oct-2009 20:33
mario moreno

Hola Roberto. Yo siguiendo un consejo en otro foro lo he solucionado con esto.

if(linea[strlen(linea)-1] == '\n');
linea[strlen(linea)-1] = '\0';
strcpy(fichas[a].nombre, linea);

pero por lo que veo, creo que viene a ser lo mismo. :)


27-Oct-2009 00:29
Nacho Cabanes (+83)

Yo lo habría hecho de la forma que indica Mario: reemplazar el último carácter por un carácter nulo, que indica el final de la cadena. Es más rápido que copiar parte de la cadena con strnpcy.

(De hecho, así es la solución que preparé en su día para mis alumnos, y que puedo buscar si quereis echarle un ojo).

Eso sí: si acabas de leer de fichero, ni siquiera hará falta el "if": sabes seguro que terminará en \n (bueno, salvo que los datos del fichero sean demasiado largos... y en ese caso también es preferible cortarlos con el \0 o cuando hagas un "printf" te mostrará dos campos seguidos en vez de uno).

Además, un matiz importante en la solución de Roberto: no recuerdo que el estándar ANSI C garantice que "strncpy" se encargue de añadir un carácter nulo al final, de modo que después de esa orden tendrías tú que añadir el caracter nulo a mano, en cualquier caso, de la forma que ha indicado Mario.


27-Oct-2009 19:14
Roberto rrs

La verdad es que tenéis razón, yo también pienso que queda mejor de esa manera, así que ya lo he modificado, como podéis ver al final.
Ademas es curioso (desconozco la razón) que al hacerlo de esta manera ya no me pasa lo que me sucedía anteriormente de que el ultimo dato guardado en el fichero me lo leía por duplicado.
Así que sigo adelante con el curso, ahora con el fread y fwrite.
Saludos.

fichero=fopen(agenda, "r+t");
while (!feof(fichero))
{fgets (linea, 30, fichero);
linea[strlen(linea)-1]='\0';
strcpy (fichas[a].nombre, linea);
fgets (linea, 30, fichero);
linea[strlen(linea)-1]='\0';
strcpy (fichas[a].direccion, linea);
fgets (linea, 30, fichero);
linea[strlen(linea)-1]='\0';
strcpy (fichas[a].movil, linea);
fgets (linea, 30, fichero);
linea[strlen(linea)-1]='\0';
strcpy (textoTemporal, linea);
sscanf (textoTemporal, "%2u", &fichas[a].dia);
fgets (linea, 30, fichero);
linea[strlen(linea)-1]='\0';
strcpy (textoTemporal, linea);
sscanf (textoTemporal, "%2u", &fichas[a].mes);
fgets (linea, 30, fichero);
linea[strlen(linea)-1]='\0';
strcpy (textoTemporal, linea);
sscanf (textoTemporal, "%4u", &fichas[a].anyo);
a++;}






(No se puede continuar esta discusión porque tiene más de dos meses de antigüedad. Si tienes dudas parecidas, abre un nuevo hilo.)