[ Foro de C ]

Capítulo 6: Manejo de Ficheros. Primeros ejercicios.

05-Jul-2012 04:22
Pablo Rampa
19 Respuestas

He aquí los primeros 3 ejercicios del Capítulo6: Manejo de Ficheros.

6.1_ Crea un programa que vaya leyendo las frases que el usuario teclea y las guarde en un fichero
de texto llamado “registroDeUsuario.txt”. Terminará cuando la frase introducida sea "fin" (esa frase
no deberá guardarse en el fichero).


#include <stdio.h>
#include <string.h>
 
int main()
{
   FILE* ptFichero;
   char fin[]="fin";  
   char frase[60];
       
   ptFichero = fopen("registroDeUsuario.txt", "wt");
   printf(" PROGRAMA para ESCRIBIR FRASES.\nCuando quiera salir," 
          "escriba la palabra fin.\n\n");
   do
   {
      puts("\nEscriba una FRASE:\n(o fin). \n");
      gets(frase);
      if (strcmp(frase, fin) == 0)
         break;
      fprintf(ptFichero, "%s\n", frase);
   }
   while (strcmp(frase, fin) != 0);
      
   fclose(ptFichero);
   return 0;
}


6.3.i_ Un programa que pida al usuario que teclee frases, y las almacene en el fichero
“frases.txt”. Acabará cuando el usuario pulse Intro sin teclear nada. Después deberá mostrar
el contenido del fichero.  


#include <stdio.h>
#include <string.h>
 
int main()
{
   FILE* ficheroU;
   char frase[61];
   int i=0;
       
   ficheroU = fopen("frases.txt", "wt");
   printf(" PROGRAMA para ESCRIBIR y almacenar FRASES.\n"
      "Cuando quiera salir, simplemente pulse \"Intro\".\n\n");
   do
   {
      if (i == 0)
         puts("\nEscriba una FRASE:\n(o pulse \"Intro\"). \n");
      else
         puts("\nEscriba otra FRASE:\n(o pulse \"Intro\"). \n");
      gets(frase);
      fprintf(ficheroU, "%s\n", frase);
      i++;
   }
   while (strcmp(frase, "") != 0);
   printf("He aqui lo que escribio:\n\n");
   fclose(ficheroU);
   
   ficheroU = fopen("frases.txt", "rt");
   do
   {
      fgets(frase, 60, ficheroU);
      puts(frase);
   }
   while (!feof(ficheroU));
   getchar();
   printf("...Hasta luego!");
   getchar();
   fclose(ficheroU);
   
   return 0;
}


6.3.ii_ Un programa que pregunte un nombre de fichero y muestre en pantalla el contenido de ese
fichero, haciendo una pausa después de cada 25 líneas, para que dé tiempo a leerlo. Cuando el usua-
rio pulse intro, se mostrarán las siguientes 25 líneas, y así hasta que termine el fichero.


#include <stdio.h>
#include <stdlib.h>

int main()
{ 
    FILE *fichero;
    char linea[100], nombre[40];
    int i=0;
   do
   {
      printf("\nNombre de fichero: ");
      gets(nombre);
   
      fichero = fopen(nombre, "rt");
   
      if (fichero == NULL)
      {
          printf("No existe el fichero\n\n");
          i++;
          if (i == 5)
             exit(1);
      } 
    }
    while (fichero == NULL);
    while (!feof(fichero))
    {
        for (i=0; i<25; i++){
            fgets(linea, 100, fichero);
            if (!feof(fichero))
            {
                puts(linea);                
            }
    }
    getchar();       
    }
    fclose(fichero);
    return 0;
}

   
     .....Saludos!
     
     


08-Jul-2012 10:59
Nacho Cabanes (+84)

En el 6.3.i haces una cosa peligrosa:

 getchar();
 printf("...Hasta luego!");
 getchar();
 fclose(ficheroU);

Por una parte, aunque esto va en gustos, los "getchar" no deberían conservarse en un "programa terminado", porque los necesitas sólo si lanzas tu programa "de consola" desde uno "de ventanas", de modo que se cierra la consola sin darte tiempo a leer. Si lanzas tu programa de consola desde una ventana de consola (que debería ser "lo natural"), esos "getchar" son innecesarios. Lo mismo ocurre si usas un entorno "de ventanas" que sí haga una pausa al terminar la ejecución. Por ejemplo, yo uso Geany, que se comporta así.

Por otra parte, cierra siempre los ficheros tan pronto como sea posible, para evitar una posible pérdida de datos. Si tienes que incluir algún "getchar" o alguna petición de datos al usuario, cierra primero el fichero (esto es especialmente crítico si escribes en fichero, no tan importante si lees de él):

 fclose(ficheroU);
 printf("...Hasta luego!");
 getchar();
 getchar();


20-Jul-2012 21:08
Pablo Rampa

Gracias, estimado Nacho, por las observaciones.
Mi sistema operativo es Windows XP, el entorno es Dev-C++.
Olvido quitar los getchar(), sin los cuales no puedo ver nada.
Realmente me encuentro paralizado. Estoy tratando de asimilar
un poco más el manejo de ficheros. Parece que he llegado a donde
no es permitido a un simple mortal.
El ejercicio de la agenda me tiene bloqueado.
Por el momento dejo pendiente el ejercicio 6.4.iii, hasta que lo pueda realizar a mi manera.

He aquí los siguientes ejercicios, saltándome por el momento el
de la agenda(6.4.iii):

/*6.4.i_ 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. */


#include <stdio.h>

int main()
{
   struct datos
   {
      char nombre[21];
      int edad;
      char ciudad[21];
   }persona;
   
   FILE *fichero;
   int i;
   
   fichero = fopen("gente.dat", "wt");
   if (fichero == NULL)
      printf("No se pudo abrir el archivo.\n");
   else
   {
      puts("Nombre:");
      gets(persona.nombre);
      fprintf(fichero, "%s ", persona.nombre);
      puts("Edad:");
      scanf("%d", &persona.edad);
      getchar();
      fprintf(fichero, "%d ", persona.edad);
      puts("Ciudad:");
      gets(persona.ciudad);
      fputs(persona.ciudad, fichero);
      fclose(fichero);
   }
   fichero = fopen("gente.dat", "rt");
   if (fichero == NULL)
      printf("No se pudo abrir el archivo.\n"); 
   else
   {  
       while (!feof(fichero))
      // while (feof(fichero) == 0)   
       { 
         fgets(persona.nombre, 60, fichero);
         puts(persona.nombre);
         fscanf(fichero, "%d", &persona.edad);
         getchar();
         printf("%d", persona.edad); 
         fgets(persona.ciudad, 60, fichero);
         puts(persona.ciudad);
       }   
   fclose(fichero);
   }
   return 0;
}
 /* 6.4.ii_ Ampliar el programa anterior para que use un “array de structs”, de forma que se puedan 
 tener datos de 10 personas. Se deberá pedir al usuario los datos de las 10 personas y guardarlos
 en el fichero. Después se pedirá al usuario un número del 1 al 10 y se mostrarán los datos de la
 persona indicada por ese número, que se deberán leer de fichero (1 será la primera ficha, y 10 será
 la última). Por ejemplo, si el usuario indica que quiere ver los datos de la persona 3 (tercera),
 se deberá leer las dos primeras, ignorando su contenido, y después leer la tercera, que sí se deberá 
 mostrar. */

#include <stdio.h>
#include <stdlib.h>

int main()
{
   struct datos
   {
      char nombre[21];
      int edad;
      char ciudad[21];
   }persona[10];            // Array de struct con datos para 10 personas.
   
   FILE *fichero;
   int i, numero=0;
   
   fichero = fopen("gente.dat", "wt");
   if (fichero == NULL)
      printf("No se pudo abrir el archivo.\n");
   else
   {
      for (i=0; i<10; i++) //Pide datos de 10 personas y los guarda en el fichero.
      {
         puts("Nombre:");
         gets(persona[i].nombre);
         fprintf(fichero, "%s", persona[i].nombre);
         puts("Edad:");
         scanf("%d", &persona[i].edad);
         getchar();
         fprintf(fichero, "%d", persona[i].edad);
         puts("Ciudad:");
         gets(persona[i].ciudad);
         fputs(persona[i].ciudad, fichero);
      }
   }
   fclose(fichero);
      fichero = fopen("gente.dat", "rt");
      if (fichero == NULL)
         printf("No se pudo abrir el archivo.\n"); 
      else
      {  
         do   
         {
            puts("Escriba el numero del fichero a leer:\n" // Pide número del 1 al 10.
                 "(Para salir, digite 0).");
            scanf("%d", &numero);
            for (i=0; i<numero; i++)  // Muestra los datos de la persona indicada por su número.
            {                            // Se leen todas las anteriores al número
               if (i == (numero-1))      // indicado, pero no se muestran.
               {
                  printf("Nombre:%s\nEdad:%d\nCiudad:%s\n", 
                     persona[i].nombre, persona[i].edad, persona[i].ciudad);   
                  getchar();   
               }
            }
         }
while(numero!=0);                                                  
         fclose(fichero);
     }
     return 0;
}

 /*6.6.i_ Un programa que pida al usuario que teclee frases, y las almacene en el fichero 
 "registro.txt", que puede existir anteriormente (y que no deberá borrarse, sino añadir al final 
 de su contenido). Cada sesión acabará cuando el usuario pulse Intro sin teclear nada. */
 
#include <stdio.h>
#include <string.h>

int main()
{
   FILE *fichero;
   char frase[61];
   int i;
    
   fichero = fopen("registro.txt", "a+");
   if (fichero == NULL)
      printf("No se pudo abrir el archivo.\n");
   else
   {
      do
      {
         fgets(frase, 60, fichero);
         puts(frase);
      }
      while (!feof(fichero));
      
      puts("Escriba algunas frases.\n  \"Enter\" para salir.\n");
      do
      {
         puts("Frase: \n");
        
         gets(frase);
         fprintf(fichero, "%s\n", frase);
      }
      while (strcmp(frase, "") != 0); 
      fclose(fichero);
   }
   return 0;
}
        
  /* 6.6.ii_ Crear un programa que pida al usuario pares de números enteros y escriba su suma (con el 
 formato "20 + 3 = 23") en pantalla y en un fichero llamado "sumas.txt", que se encontrará en un 
 subdirectorio llamado "resultados". Cada vez que se ejecute el programa, deberá añadir los nuevos 
 resultados a continuación de los resultados de las ejecuciones anteriores. */
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
   FILE *resultados;
   int numero1=0, numero2=0, suma=0;
    
   resultados = fopen("sumas.txt", "a+");
   if (resultados == NULL)
      printf("No se pudo abrir el archivo.\n");
   else
   {
      do
      {
         fscanf(resultados, "%d + %d = %d", &numero1, &numero2, &suma);
         if (feof(resultados))
            break;
         printf("%d + %d = %d\n", numero1, numero2, suma);
      }
      while (!feof(resultados));
      
      printf("Escriba dos numeros.\n\"000\" para salir.\n");
      do
      {
         printf("Primer numero: ");
         scanf("%d", &numero1);
         if (numero1 == 0) 
            exit(1);  
         printf("Segundo numero: ");
         scanf("%d", &numero2);    
         suma = numero1 + numero2;   
         printf("%d + %d = %d\n", numero1, numero2, suma);
         fprintf(resultados, "%d + %d = %d\n", numero1, numero2, suma);
      }
      while (numero1 != 0); 
      fclose(resultados);
   }
   return 0;
}



   
   Saludos....!  


22-Jul-2012 22:35
Nacho Cabanes (+84)

Pablo, apenas un par de comentarios a tus últimas aportaciones:

- En el 6.6.i, no es necesario que leas los datos existentes en el fichero, basta con que añadas al final.

- En el 6.6.ii, cuidado con el "exit", porque abandonas el programa en un punto inesperado... y no cierras el fichero, lo que puede provocar una pérdida de datos. Por eso es preferible intentar evitar los "exit" y plantear las condiciones de otra forma. En tu caso, podría ser "si el número no es cero, pedir el otro número... etc".

- La parte básica del ejercicio de la agenda se parece al 6.4.ii. ¿Qué dudas tienes?


24-Jul-2012 06:15
Pablo Rampa

Gracias nuevamente, estimado Nacho, por las valiosas 0bservaciones.
Es que la agenda me confundió más porque empecé a buscar en el foro
y revolví los conceptos entre las varias versiones que muchos han
aportado. Me está preocupando el uso de fwrite y fread,
pero creo que ya le voy a ir dando forma.
También me tiene confundido el 6.8.i con el 6.8.ii, no encuentro
la diferencia. Supongo que el 6.8.ii debe ser la promoción del an-
terior, pero no encuentro eso en el enunciado.

Este es uno de los mencionados:


 /*6.8.i_ Mejorar la agenda anterior(6.4.i), para guardar y leer cada “ficha” (struct) de una vez, 
 usando fwrite/fread y sizeof, como en el último ejemplo. */
  
#include <stdio.h>

int main()
{
   struct datos
   {
      char nombre[21];
      int edad;
      char ciudad[20];
   }persona;
   
   FILE *fichero;
     
   if ((fichero = fopen("gente.dat", "wb")) == NULL)
      printf("No se pudo abrir el archivo.\n");
   else
   {
      printf("Nombre: ");
      scanf("%s", persona.nombre);
      printf("Edad: ");
      scanf("%d", &persona.edad);
      printf("Ciudad: ");
      scanf("%s", persona.ciudad);
      
      fwrite(&persona, 1, sizeof(struct datos), fichero); 
      
      fclose(fichero);
  } 
  
  if((fichero = fopen("gente.dat", "rb")) == NULL)
     printf("No se pudo abrir el archivo.\n"); 
  else
  {    
     fread(&persona, sizeof (struct datos), 1, fichero);
     printf("\n%s", persona.nombre); 
     printf("\n%d", persona.edad); 
     printf("\n%s", persona.ciudad);
     
     fclose(fichero);
  }
  return 0;   
}


 Saludos...!


25-Jul-2012 01:17
Pablo Rampa

Siempre solicitándole su valiosa ayuda, estimado nacho. Este es el
ejercicio 6.4c(yo lo tenía como 6.4.iii) el de la agenda que había
dejado pendiente.
Me compila, pero al correr la opción 3, no me muestra los datos de
la última persona. Al correrlo varias veces se llena de ceros y otras locuras. Entiendo que en parte es por la falta de detalles como los que Ud. le pone: Por ejemplo, borrar el \n del final de la línea. Esa parte no la entiendo.
Si es tan amable, me puede decir  qué es lo más grave de este código. O sea, cómo quedaría lo más sencillo posible sin muchas complicaciones, pero que funcione.


  6.4c_ Una agenda que maneje los siguientes datos: nombre, dirección, tlf móvil, email, y día,
mes y año de nacimiento (estos tres últimos datos deberán ser números enteros cortos). Deberá
tener capacidad para 100 fichas. Se deberá poder añadir un dato nuevo, visualizar los nombres
de las fichas existentes, o mostrar todos los datos de una persona (se preguntará al usuario
cual es el nombre de esa persona que quiere visualizar). Al empezar el programa, leerá los datos
de un fichero llamado “agenda.dat” (si existe). Al terminar, guardará todos los datos en ese
fichero.

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

int main()      
{          
  struct agenda
  {      
     char nombre [21];
     char direccion [31];
     char celular[13];
     char email[31];
     unsigned short int diaNac, mesNac, anyoNac;
  }persona[100];

  FILE* fichero;      
  char textoTemporal[21];
  int opcion, personas=-1;          
  int i;              
                   
  fichero = fopen("agenda.dat", "rt");  
  if (fichero != NULL)
  {
     while (! feof(fichero))
     {                          
        fscanf(fichero, "%s", persona[i].nombre);    
        if (feof(fichero)) break;    
        printf("%s\n", persona[i].nombre);
           
        fscanf(fichero, "%s", persona[i].direccion);    
        if (feof(fichero)) break;
        printf("%s\n", persona[i].direccion);
           
        fscanf(fichero, "%s", persona[i].celular);    
        if (feof(fichero)) break;
        printf("%s\n", persona[i].celular);
           
        fscanf(fichero, "%s", persona[i].email);    
        if (feof(fichero)) break;
        printf("%s\n", persona[i].email);
           
        fscanf(fichero, "%hd%hd%hd", &persona[i].diaNac, &persona[i].mesNac, &persona[i].anyoNac);    
        if (feof(fichero)) break;
        printf("%hd %hd %hd\n\n", persona[i].diaNac, persona[i].mesNac, persona[i].anyoNac);
        personas++;

     }
     fclose(fichero);                
  }
  printf("Leidos %d datos", personas+1);
           
  do    
  {
     puts("\n\n  MENU:\n");
     puts("1.- Agregar un nuevo dato.");
     puts("2.- Ver todos los datos existentes.");
     puts("3.- Ver todos los datos de una persona.");
     puts("0.- Terminar.");
     puts("   Elija una opcion: ");
       
     scanf("%d", &opcion);
     getchar();                          

     switch (opcion)
     {
        case 1:    /* Agregar un nuevo dato */
           printf ("Introduce nombre: ");
           gets (persona[personas+1].nombre);
           fprintf(fichero, "%s", persona[personas+1].nombre);
           printf ("Introduce direccion: ");
           gets (persona[personas+1].direccion);
           fprintf(fichero, "%s", persona[personas+1].direccion);
           printf ("Introduce celular: ");
           gets (persona[personas+1].celular);
           fprintf(fichero, "%s", persona[personas+1].celular);
           printf ("Introduce correo electronico: ");
           gets (persona[personas+1].email);
           fprintf(fichero, "%s", persona[personas+1].email);
           printf ("Introduce dia de nacimiento: ");
           scanf("%hd", &persona[personas+1].diaNac);
           fprintf(fichero, "%hd", persona[personas+1].diaNac);
           printf ("Introduce mes de nacimiento: ");
           scanf ("%hd", &persona[personas+1].mesNac);
           fprintf(fichero, "%hd", persona[personas+1].mesNac);
           printf ("Introduce año de nacimiento: ");
           scanf ("%hd", &persona[personas+1].anyoNac);
           fprintf(fichero, "%hd", persona[personas+1].anyoNac);
           personas ++;
           break;

        case 2:    /* Ver todos los nombres */
           puts ("Ver todos los nombres existentes:");
           for (i=0; i<=personas; i++)
              puts (persona[i].nombre);
           break;
               
        case 3:    /* Ver todos los datos de una persona */
           printf ("Nombre a buscar? ");
           for (i=0; i<=personas; i++)
           {
              gets(textoTemporal);
              if (strcmp (textoTemporal, persona[i].nombre) != 0) break;
              {
                 puts (persona[i].nombre);
                 puts (persona[i].direccion);
                 puts (persona[i].celular);
                 puts (persona[i].email);
                 printf("%hd %hd %hd.\n", persona[i].diaNac,
                    persona[i].mesNac, persona[i].anyoNac);
              }
                             
           }
           break;
        }
      }
      while (opcion != 0);
     
      fichero = fopen("agenda.dat", "wt");  
      for (i=0; i<=personas; i++)
      {
         fprintf (fichero, "%s\n", persona[i].nombre);
         fprintf (fichero, "%s\n", persona[i].direccion);
         fprintf (fichero, "%s\n", persona[i].celular);
         fprintf (fichero, "%s\n", persona[i].email);
         fprintf (fichero, "%hd %hd %hd\n",
            persona[i].diaNac, persona[i].mesNac, persona[i].anyoNac);
      }
      fclose(fichero);
      return 0;
                           
}


  Agradezco su ayuda. Saludos.


25-Jul-2012 23:51
Pablo Rampa

Así entendí el ejercicio 6.8b:


 6.8b_ 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”, usando “fwrite”. Cerrar el fichero, volverlo a abrir para lectura y mostrar los datos
que se habían guardado, que se deben leer con “fread”.
 
#include <stdio.h>

struct datos
  {
     char nombre[21];
     int edad;
     char ciudad[20];
  }persona[10];       /* Para mejorar el ejercicio anterior,
                         agregué arreglo de 10 structs. */
int main()
{
  FILE *fichero;
  int i=0;
   
  if ((fichero = fopen("gente.dat", "wb")) == NULL)
     printf("No se pudo abrir el archivo.\n");
  else
  {    
     do
     {
        printf("Nombre: ");
        fflush(stdout);
        gets(persona[i].nombre);
        printf("Edad: ");
        fflush(stdout);
        scanf("%d", &persona[i].edad);
        printf("Ciudad: ");
        fflush(stdout);
        scanf("%s", persona[i].ciudad);
        fflush(stdin);
        i++;
     }
     while (i < 10);
     
     
     fwrite(&persona[i], sizeof(persona), 1, fichero);
     
     fclose(fichero);
 }
 
 if((fichero = fopen("gente.dat", "rb")) == NULL)
    printf("No se pudo abrir el archivo.\n");
 else
 {
    fread(&persona[i], sizeof (persona), 1, fichero);
    for (i=0; i<10; i++)
    {
       printf("\n%s ", persona[i].nombre);
       printf("%d ", persona[i].edad);
       printf("%s\n", persona[i].ciudad);
    }
     
    fclose(fichero);
 }
 
}  
   
 Saludos.....!    


26-Jul-2012 00:53
Pablo Rampa

Estimado Nacho, en este ejercicio tengo problemas con fread.
6.8c_ Ampliar el programa anterior para que use un “array de structs”, de forma que se puedan
tener datos de 10 personas. Se deberá pedir al usuario los datos de las 10 personas y guardarlos
en el fichero, usando “fwrite”. Después se pedirá al usuario un número del 1 al 10 y se mostra-
rán los datos de la persona indicada por ese número, que se deberán leer de fichero (1 será la
primera ficha, y 10 será la última). Por ejemplo, si el usuario indica que quiere ver los datos
de la persona 3 (tercera), se deberá leer las dos primeras (con “fread”), ignorando su contenido,
y después leer la tercera, que sí se deberá mostrar.


#include <stdio.h>

struct datos
  {
     char nombre[21];
     int edad;
     char ciudad[20];
  }persona[10];      

int main()
{
  FILE *fichero;
  int i=0, numero;
   
  if ((fichero = fopen("gente.dat", "wb")) == NULL)
     printf("No se pudo abrir el archivo.\n");
  else
  {    
     do
     {
        printf("Nombre: ");
        fflush(stdout);
        gets(persona[i].nombre);
        printf("Edad: ");
        fflush(stdout);
        scanf("%d", &persona[i].edad);
        printf("Ciudad: ");
        fflush(stdout);
        scanf("%s", persona[i].ciudad);
        fflush(stdin);
        i++;
     }
     while (i < 10);
     
     
     fwrite(&persona[i], sizeof(persona), 1, fichero);
     
     fclose(fichero);
 }
 
 if((fichero = fopen("gente.dat", "rb")) == NULL)
    printf("No se pudo abrir el archivo.\n");
 else
 {
   /*  AQUÍ no sé cómo usar FREAD. ¡Ayuda, por favor!  */
   
 /* while (fread(&persona[i], sizeof(persona), 1, fichero) == 1)
     printf("Nombre:%s\nEdad:%d\nCiudad:%s\n",
        persona[i].nombre, persona[i].edad, persona[i].ciudad); */
         
    do
    {
       puts("Escriba el numero del fichero a leer:\n"
                "(Para salir, escriba 0).");
       scanf("%d", &numero);
       for (i=0; i<numero; i++)
       {  
          if (i == (numero-1))    
          {
             printf("Nombre:%s\nEdad:%d\nCiudad:%s\n",
                persona[i].nombre, persona[i].edad, persona[i].ciudad);  
             getchar();  
          }
       }
    }  
    while ((numero > 0) && (numero <= 10));  
                                                         
    fclose(fichero);
    }
   
}
           .....Saludos!


26-Jul-2012 21:16
Pablo Rampa

  S... O... S..!!!
Si alguien me puede ayudar, le agradeceré por el resto de mi vida, jejeje!
Creía que ya los manejaba, pero acabo de darme cuenta que no puedo usar la tripleta
FWRITE/FREAD/SIZEOF, ni en el más sencillo de los ejercicios.
  El profesor Nacho da un buen ejemplo del uso de estas funciones cuando copia un archivo en
otro; pero, no logro adaptarlo a este ejercicio que aparentemente es más sencillo. Lo básico:
escribir en, y leer de un archivo.
  Probando con el siguiente código, eliminé (comenté) las dos líneas que incluyen a fread/fwrite
y sizeof, y el resultado fué el mismo. O sea que, no estoy ni guardando en archivo  ni leyendo
del archivo. Simplemente estoy recuperando de la manera más vulgar lo que  guardé en el struct.
  Si alguien me puede decir qué hay de malo con el código siguiente, qué es lo que le falta, y,
cómo se lograría de la manera más sencilla posible:


6.8.i_ Mejorar la agenda anterior(6.4.i), para guardar y leer cada “ficha” (struct) de una vez,
   usando fwrite/fread y sizeof, como en el último ejemplo.
   


#include <stdio.h>

int main()
{
   struct datos
   {
      char nombre[21];
      int edad;
      char ciudad[21];
   }persona;    /* El ejercicio pide un array, pero aún para una sola ficha no me funciona. */
   
   FILE *fichero;
     
   if ((fichero = fopen("gente.dat", "wb")) == NULL)
      printf("No se pudo abrir el archivo.\n");
   else
   {
      printf("Nombre: ");
      scanf("%s", persona.nombre);
      printf("Edad: ");
      scanf("%d", &persona.edad);
      printf("Ciudad: ");
      scanf("%s", persona.ciudad);
      
         /* Da lo mismo, si quito la siguiente línea. */
      fwrite(&persona, sizeof(struct datos), 1, fichero); 
      
      fclose(fichero);
  } 
  
  if((fichero = fopen("gente.dat", "rb")) == NULL)
     printf("No se pudo abrir el archivo.\n"); 
  else
  {   
        /* Igual, si elimino esta otra, o ambas. */
     fread(&persona, sizeof (struct datos), 1, fichero);
     printf("\n%s", persona.nombre); 
     printf("\n%d", persona.edad); 
     printf("\n%s", persona.ciudad);
     
     fclose(fichero);
  }
  return 0;
}


  Creo que si entiendo este sencillo ejercicio voy a poder encarar los que siguen, pues éste
es como el prerequisito.

 .....Gracias de antemano!    
   


26-Jul-2012 21:59
Antonio Rodriguez

Mientras no viene Nacho te comento algo para que vayas intentándolo tu:

En primer lugar, creo que esta parte no es correcta (sobra lo de "datos")


 struct datos
   {
       char nombre[21];
       int edad;
       char ciudad[21];
   }persona;


Creo que debiera ser:


 struct {
       char nombre[21];
       int edad;
       char ciudad[21];
   }persona;




Por lo tanto, cuando pones lo de sizeof(struct datos) debiera ser sizeof(persona), y con eso creo que el programa ya te funciona.

Un saludo!


26-Jul-2012 22:15
Antonio Rodriguez

Hay alguna otra cosa que debieras corregir, como por ejemplo cambiar los "scanf" cuando recibes cadenas de texto por "gets"


gets(persona.nombre);


para evitar problemas con los espacios (y me parece que codigo queda más limpio xD)

Además debieras añadir un getchar() despues del scanf que recibe la edad, para evitar problemas con el "enter" que pulsa el usuario después de introducir la edad


printf("Edad: ");
scanf("%d", &persona.edad);
getchar();


Un saludo!


27-Jul-2012 00:34
Nacho Cabanes (+84)

Veamos Pablo...

En el ejercicio, 6.4.3, de la agenda: en general está bastante bien, pero tiene algún fallo. Por ejemplo:

- No inicializas la variable "i", de modo que el "fscanf(fichero, "%s", persona[i].nombre);" puede estar accediendo a cualquier sitio, no necesariamente a la ficha inicial, y quizá incluso fuera del rango de los datos. Si miras mi propuesta de solución, verás que guardo usando el contador de fichas (ultimaFicha+1). En tu caso sería: fscanf(fichero, "%s", persona[personas+1].nombre);

- Cuando lees la fecha de nacimiento (día, mes, año), no los separas por ningún espacio ni ningún carácter distintivo, de moo que algo como 12101980 parecería un "único número grande". Compara tu "fscanf(fichero, "%hd%hd%hd"," con mi "%hd %hd %hd"

- En general, se parece mucho al mío, así que supongo que te habrás basado en él, en vez de hacerlo desde cero. Si lo que tienes son dudas con el esqueleto básico del programa, mira la propuesta para el ejercicio 5.5.2b:

http://www.nachocabanes.com/c/curso/c_soluciones.php#050502b

Puedes añadir soporte de ficheros a ese ejemplo, para practicar. En un primer acercamiento, podrías leer todo al principio de la ejecución y guardar todo al salir, como en el 6.4c.


27-Jul-2012 06:47
Pablo Rampa

Gracias Antonio por tu deferencia.
Ya hice lo que me recomiendas y lo mismo.
El programa funciona, pero no están operando las funciones de
guardar en archivo (fwrite), leer de archivo (fread), ni tam-
poco sizeof. Lo sé por estas dos razones que he comprobado:
1.- Elimino la línea que contiene fwrite, o la que contiene a
   fread, o ambas, y funciona igual que con ellas.
2.-Si abro el archivo en el modo "ab", me sigue presentando los
  datos que tenía cuando lo abrí la última vez en el modo "wb"
  y no me presenta los datos que estoy introduciendo actualmente.
De lo anterior deduzco que no estoy guardando en archivo, ni estoy leyendo del archivo; sino más bien, sólo estoy recuperando lo que se guardó en el struct.

Mi preocupación es que no puedo usar FWRITE/FREAD/SIZEOF.

Este ejercicio me gusta para poderlo entender bien, porque es de los más sencillos.
Reitero: el código parece que funciona (así lo creí al principio),
pero no es así.

Si tienes algotra sugerencia, te lo agradeceré; de lo contrario,
esperaré a ver qué dice el Profesor (sé que a él ésto le va a parecer "muerto de la risa", pero para mí es por el momento un
completo valladar).

Saludos, Antonio.


27-Jul-2012 07:18
Pablo Rampa

Gracias, estimado Nacho por su respuesta.
Antes que nada quiero disculparme por tergiversar los números de los ejercicios. Por ejemplo, a éste lo nominé como 6.4.iii, después
me dí cuenta que es el 6.4c. En adelante utilizaré esta nomencla-
tura.
A propósito de este ejercicio (la agenda), expresé que me tenía confundido y realmente quiero dejar muy claro ante el honorable foro que no me basé en su fuente para realizarlo; jamás haría algo tan vil. Más bien fue una copia textual, pero mal hecha, jejeje.
Prometo que al ordenar un poco las ideas lo tengo que realizar por
mi cuenta.
Estimado Profesor: por elmomento lo que más me preocupa es el uso
de FWRITE/FREAD/SIZEOF que me parece que son funciones básicas en el trabajo con ficheros de acceso aleatorio o de tipo binario.

Específicamente es el ejercicio 6.8a que trata de un array de 10
structs; y que para simplificarlo aún más, lo realizo con una simple variable de tipo struct (persona). Y ni así lo puedo hacer funcionar. De hecho funciona aparentemente; pero no estoy escribiendo ni leyendo del fichero.
Mi preocupación es por el hecho de ser un ejercicio sencillo, muy
bonito para poder entender el uso de esas funciones básicas; y no
lo he podido concretar.
...Si su paciencia da todavía para más, estaré muy agradecido por su valiosa atención.

  Saludo cordial.


27-Jul-2012 07:41
Pablo Rampa

Perdón Profesor, es el ejercicio que está como a seis correos
de distancia de aquí hacia atrás. Es el 6.8a, pero que lo nombré  
como 6.8i. Es el que inicié con un S...O...S..!

Gracias de nuevo.


27-Jul-2012 11:01
Antonio Rodriguez

Hola Pablo.

Debo decirte que a mí el código sí me funciona, he hecho unas modificaciones para comprobarlo, lo pego aquí y te comento un par de detalles:


#include <stdio.h>

 int main()
 {
   struct   {
       char nombre[21];
       int edad;
       char ciudad[21];
   }persona;   
   
   FILE *fichero;
     
   if ((fichero = fopen("gente8.dat", "ab")) == NULL)
       printf("No se pudo abrir el archivo.\n");
   else
   {
       printf("Nombre: ");
       gets(persona.nombre);
       printf("Edad: ");
       scanf("%d", &persona.edad);
       getchar();
       printf("Ciudad: ");
       gets(persona.ciudad);
       
       fwrite(&persona, sizeof(persona), 1, fichero); 
       
       fclose(fichero);
   } 
   
   if((fichero = fopen("gente8.dat", "rb")) == NULL)
     printf("No se pudo abrir el archivo.\n"); 
   else
   {  
	while (! feof(fichero)) {
     fread(&persona, sizeof(persona), 1, fichero);
     printf("\n%s", persona.nombre); 
     printf("\n%d", persona.edad); 
     printf("\n%s", persona.ciudad);
	}
     
     fclose(fichero);
   }
   return 0;
 }



En primer lugar, la línea en la que abrimos el fichero:


   if ((fichero = fopen("gente8.dat", "ab")) == NULL)


Como ves, he llamado el fichero de otra forma (gente8.dat) pero lo he hecho solamente para que no me sobreescriba en mis propios ficheros :D Otra cosa que he cambiado es el modo de apertura ("ab") para que al ejecutar el programa añada los datos que introducimos al final del fichero y no cree un fichero nuevo cada vez que se ejecute (que es lo que hacía con "wd") Esto también nos vale para verificar que fwrite funciona, ya que si tras ejecutar el programa un par de veces abrimos el archivo gente8.dat (con el block de notas, por ejemplo) los datos serán ilegibles en su mayoría, pero veremos que van aumentando a medida que ejecutamos el programa, con lo que efectivamente está escribiendo.

En la parte de lectura del fichero he hecho otra modificación:


while (! feof(fichero)) {
     fread(&persona, sizeof(persona), 1, fichero);
     printf("\n%s", persona.nombre); 
     printf("\n%d", persona.edad); 
     printf("\n%s", persona.ciudad);
}


Simplemente he añadido "while (! feof(fichero))" para que la lectura se haga de todos los datos del fichero, así verás que no solamente lee los datos de la ultima ficha introducida, si no que está leyendo los datos que has introducido en otras ejecuciones del programa (y que han sido guardados en el fichero gracias a que estamos escribiendo con "ab").


Espero que estas indicaciones sirvan para orientarte, y no para confundirte todavía más :)

Un saludo!


27-Jul-2012 12:16
Nacho Cabanes (+84)

Vamos por partes...

El enunciado del 6.8a dice

Apartado 6.8a: Mejorar la agenda anterior, para guardar y leer cada “ficha” (struct) de una vez, usando fwrite/fread y sizeof, como en el último ejemplo.

No dice que se base en el 6.4a, que no es la agenda sino una primera toma de contacto. Está pensado para que te bases en el 6.4c, pero claro, para eso primero tienes que haber asimilado correctamente el 6.4c. Por eso decía que era interesante analizar y entender primero el 5.5.2b.

Si quieres convertir el 6.4a para que use fread y fwrite, me parece un ejercicio razonable como primer acercamiento, pero no es lo que se pide en el 6.8a. En ese caso, retrocedo a tu propuesta para el 6.4a, miro la del 6.8a y comparo, para ver los fallos, aunque eso que hablas del modo "ab" ya me hace sospechar, porque el modo "a" (añadir, append) está pensado para ficheros de texto. Pero es que, en cualquier caso, el 6.4a estaba pensado para guardar una única ficha, no varias...

Veamos... tu propuesta para el 6.4a es:


#include <stdio.h>

int main()
{
  struct datos
  {
      char nombre[21];
      int edad;
      char ciudad[21];
  } persona;
  
  FILE *fichero;
  int i;
  
  fichero = fopen("gente.dat", "wt");
  if (fichero == NULL)
      printf("No se pudo abrir el archivo.\n");
  else
  {
      puts("Nombre:");
      gets(persona.nombre);
      fprintf(fichero, "%s ", persona.nombre);
      puts("Edad:");
      scanf("%d", &persona.edad);
      getchar();
      fprintf(fichero, "%d ", persona.edad);
      puts("Ciudad:");
      gets(persona.ciudad);
      fputs(persona.ciudad, fichero);
      fclose(fichero);
  }
  fichero = fopen("gente.dat", "rt");
  if (fichero == NULL)
      printf("No se pudo abrir el archivo.\n"); 
  else
  {  
      while (!feof(fichero))
      // while (feof(fichero) == 0)  
      { 
        fgets(persona.nombre, 60, fichero);
        puts(persona.nombre);
        fscanf(fichero, "%d", &persona.edad);
        getchar();
        printf("%d", persona.edad); 
        fgets(persona.ciudad, 60, fichero);
        puts(persona.ciudad);
      }  
  fclose(fichero);
  }
  return 0;
}


Correcciones necesarias:

- Dado que "fgets" lee una línea, lo razonable es que cuando escribas los datos, los termines con \n, no con un espacio en blanco.

- El "getchar" que hay por ahí no sirve de nada: lee de consola y tú estás accediendo a fichero.

- El "fclose" debería ir dentro del "else": no puedes cerrar un fichero que no has conseguido abrir.


Vamos ahora con tu propuesta para la variante que usa "fwrite":


#include <stdio.h>

int main()
{
  struct datos
  {
      char nombre[21];
      int edad;
      char ciudad[21];
  }persona;    /* El ejercicio pide un array, pero aún para una sola ficha no me funciona. */
  
  FILE *fichero;
    
  if ((fichero = fopen("gente.dat", "wb")) == NULL)
      printf("No se pudo abrir el archivo.\n");
  else
  {
      printf("Nombre: ");
      scanf("%s", persona.nombre);
      printf("Edad: ");
      scanf("%d", &persona.edad);
      printf("Ciudad: ");
      scanf("%s", persona.ciudad);
      
        /* Da lo mismo, si quito la siguiente línea. */
      fwrite(&persona, sizeof(struct datos), 1, fichero); 
      
      fclose(fichero);
  } 
  
  if((fichero = fopen("gente.dat", "rb")) == NULL)
    printf("No se pudo abrir el archivo.\n"); 
  else
  {  
        /* Igual, si elimino esta otra, o ambas. */
    fread(&persona, sizeof (struct datos), 1, fichero);
    printf("\n%s", persona.nombre); 
    printf("\n%d", persona.edad); 
    printf("\n%s", persona.ciudad);
    
    fclose(fichero);
  }
  return 0;
}


Comentarios sobre éste:

- La estructura es buena, salvo por pequeños detalles, como que yo usaría "gets" en vez de "scanf" para las cadenas, para permitir espacios en blanco intermedios (ya sabes que eso puede obligar a que añadas algún "getchar").

- Dará igual si eliminas las dos líneas, efectivamente, porque los datos están en memoria. Si no guardas en fichero y no lees, se siguen mostrando los valores que había en la memoria. Aunque sí existirá una diferencia: el fichero estará vacío. Para comprobar que sí está funcionando, puedes "borrar" los valores entre la lectura y la escritura, haciendo

strcpy(persona.nombre, "");
persona.edad = 0;
strcpy(persona.ciudad, "");

Si después de eso, lees y consigues mostrar los valores correctos, estará claro que está funcionando.


27-Jul-2012 23:11
Pablo Rampa

Me siento honrado y altamente agradecido por las esclarecedoras respuestas brindadas por Antonio y el Profesor Nacho.
Voy a dedicar un buen rato a asimilar tan valiosos aportes y a
ordenar ideas y volver a realizar algunos ejercicios que había mal interpretado, ya sea conceptual o mecanograficamente.
Nuevamente gracias y me voy a recluir por un buen rato. Luego saldré a la luz con más fuentes resueltos, espero; y alguna que
otra consulta.

  .....Saludos cordiales.


01-Aug-2012 01:00
Pablo Rampa

He aquí otros ejercicios resueltos:
(Aclaro que la primera versión de la agenda es una copia mutilada
de la que muestra el Profesor Nacho).  :-I  


/*6.4c_ Una agenda (AGENDA versión 0.01) que maneje los siguientes datos: nombre, dirección, tlf móvil, email, y día,
 mes y año de nacimiento (estos tres últimos datos deberán ser números enteros cortos). Deberá 
 tener capacidad para 100 fichas. Se deberá poder añadir un dato nuevo, visualizar los nombres 
 de las fichas existentes, o mostrar todos los datos de una persona (se preguntará al usuario 
 cual es el nombre de esa persona que quiere visualizar). Al empezar el programa, leerá los datos
 de un fichero llamado “agenda.dat” (si existe). Al terminar, guardará todos los datos en ese 
 fichero. */

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

int main()      
{          
   struct agenda
   {       
      char nombre [21];
      char direccion [31];
      char celular[13];
      char email[31];
      unsigned short int dia, mes, anyo;
   }persona[100];

   FILE* fichero;       
   char textoAux[21];
   int opcion, personas=0;          
   int i, j;               
                    
   fichero = fopen("agenda.dat", "rt");
   if (fichero != NULL)  
   {   
        while (! feof(fichero))
        {                           
            fgets(textoAux, 20, fichero);     
            if (feof(fichero)) break;          
            if (strlen(textoAux) > 0)     
                textoAux[strlen(textoAux) -1] = '\0';
            strcpy(persona[personas].nombre, textoAux);
            puts(persona[personas].nombre);
            
            fgets(textoAux, 20, fichero);     
            if (feof(fichero)) break;  
            if (strlen(textoAux) > 0)      
                textoAux[strlen(textoAux) -1] = '\0';
            strcpy(persona[personas].direccion, textoAux);
            puts(persona[personas].direccion);
            
            fgets(textoAux, 20, fichero);     
            if (feof(fichero)) break;  
            if (strlen(textoAux) > 0)      
                textoAux[strlen(textoAux) -1] = '\0';
            strcpy(persona[personas].celular, textoAux);
            puts(persona[personas].celular);
            
            fgets(textoAux, 20, fichero);     
            if (feof(fichero)) break; 
            if (strlen(textoAux) > 0)      
                textoAux[strlen(textoAux) -1]  = '\0';
            strcpy(persona[personas].email, textoAux);
            puts(persona[personas].email);
            
            fgets(textoAux, 20, fichero);
            if (feof(fichero)) break;    
            sscanf(textoAux, "%hd %hd %hd", &persona[personas].dia,
                &persona[personas].mes,
                &persona[personas].anyo);
            if ((persona[personas].dia == 0) || (persona[personas].mes == 0) ||
                (persona[personas].anyo == 0))
               break;
            puts(textoAux);  
            personas++;   
        }
        fclose(fichero);               
    }
    if (personas == 0) printf("No hay ninguna ficha guardada.");
    else
       if (personas == 1) printf("He ahi la unica ficha guardada.");
       else
          printf("He ahi las %d fichas guardadas.", personas);            
    do     
    {
      puts("\n\n  MENU:\n");
      puts("1.- Agregar un nuevo dato.");
      puts("2.- Ver todos los datos existentes.");
      puts("3.- Ver todos los datos de una persona.");
      puts("0.- Terminar.");
      puts("   Elija una opcion: ");
        
      scanf("%d", &opcion);
      getchar();                           

      switch (opcion)
      {
         case 1:    /* Agregar un nuevo dato */
            printf ("nombre: ");
            gets (persona[personas].nombre);
            fprintf(fichero, "%s", persona[personas+1].nombre);
            printf ("Direccion: ");
            gets (persona[personas].direccion);
            fprintf(fichero, "%s", persona[personas+1].direccion);
            printf ("Celular: ");
            gets (persona[personas].celular);
            fprintf(fichero, "%s", persona[personas+1].celular);
            printf ("Correo electronico: ");
            gets (persona[personas].email);
            fprintf(fichero, "%s", persona[personas+1].email);
            printf ("Dia de nacimiento: ");
            scanf("%hd", &persona[personas].dia);
            fprintf(fichero, "%hd", persona[personas+1].dia);
            printf ("Mes de nacimiento: ");
            scanf ("%hd", &persona[personas].mes);
            fprintf(fichero, "%hd", persona[personas+1].mes);
            printf ("Año de nacimiento: ");
            scanf ("%hd", &persona[personas].anyo);
            fprintf(fichero, "%hd", persona[personas].anyo);
            personas ++;
            break;

         case 2:    /* Ver todos los nombres */
            j = 0;
            puts ("Ver todos los nombres existentes:");
            for (i=0; i<=personas; i++)
            {
               puts (persona[i].nombre);
               j ++;
            }
            if (j == 0)
               printf("No hay ningun nombre guardado.");
            break;
                
         case 3:    /* Ver todos los datos de una persona */
            puts("Nombre a buscar:");
            gets(textoAux);
            j = 0;
            for (i=0; i<=personas; i++)
            {
               if (strcmp (textoAux, persona[i].nombre) == 0) 
               {
                  puts (persona[i].nombre);
                  if (strcmp(persona[i].nombre, "") == 0)
                     break;
                  puts (persona[i].direccion);
                  puts (persona[i].celular);
                  puts (persona[i].email);  
                  printf("%hd %hd %hd.\n", persona[i].dia,
                     persona[i].mes, persona[i].anyo);
                  j ++;
               }              
            }
            if (j == 0)
               printf("No existe esa ficha.");
            break;
         }
       }
       while (opcion != 0);
       
       fichero = fopen("agenda.dat", "wt");   
       for (i=0; i<=personas; i++)
       {
          fprintf (fichero, "%s\n", persona[i].nombre);
          fprintf (fichero, "%s\n", persona[i].direccion);
          fprintf (fichero, "%s\n", persona[i].celular);
          fprintf (fichero, "%s\n", persona[i].email);
          fprintf (fichero, "%hd %hd %hd\n",
             persona[i].dia, persona[i].mes, persona[i].anyo);
       }
       fclose(fichero);
       return 0;
                            
 }




 /*6.8a_ Mejorar la agenda anterior(6.4c), para guardar y leer cada “ficha” (struct) de una vez, 
 usando fwrite/fread y sizeof, como en el último ejemplo. */

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

int main()      
{          
   struct agenda
   {       
      char nombre [21];
      char direccion [31];
      char celular[13];
      char email[31];
      unsigned short int dia, mes, anyo;
   }persona[100];

   FILE* fichero;       
   char textoAux[21];
   int opcion, personas=0;          
   int i, j;               
                    
   fichero = fopen("agenda.dat", "rb");
   if (fichero != NULL)
   {
      while (! feof(fichero))
      {                           
         fread(&persona[i],sizeof(persona), 1, fichero);
         if (feof(fichero)) break;     
         printf("%s\n", persona[i].nombre);
         if (feof(fichero)) break;  
         printf("%s\n", persona[i].direccion);
         if (feof(fichero)) break; 
         printf("%s\n", persona[i].celular);
         if (feof(fichero)) break;
         printf("%s\n", persona[i].email);
         if (feof(fichero)) break;
         printf("%hd %hd %hd\n\n", persona[i].dia, persona[i].mes, persona[i].anyo);
         if (feof(fichero)) break;
         personas++;  
      }
      fclose(fichero);                 
   }
             
   do     
   {
      puts("\n\tMENU:\n");
      puts("1.- Agregar un nuevo dato.");
      puts("2.- Ver todos los datos existentes.");
      puts("3.- Ver todos los datos de una persona.");
      puts("0.- Terminar.");
      puts("   Elija una opcion: ");
        
      scanf("%d", &opcion);
      getchar();                           

      switch (opcion)
      {
         case 1:    /* Agregar un nuevo dato */
            printf ("Nombre: ");
            gets (persona[personas].nombre);
            printf ("Direccion: ");
            gets (persona[personas].direccion);
            printf ("Celular: ");
            gets (persona[personas].celular);
            printf ("Correo electronico: ");
            gets (persona[personas].email);
            printf ("Dia de nacimiento: ");
            scanf("%hd", &persona[personas].dia);
            printf ("Mes de nacimiento: ");
            scanf ("%hd", &persona[personas].mes);
            printf ("Año de nacimiento: ");
            scanf ("%hd", &persona[personas].anyo);
            personas ++;
            fwrite(&persona[i], sizeof(persona), 1, fichero);
            break;

         case 2:    /* Ver todos los nombres */
            puts ("Ver todos los nombres existentes:");
            for (i=0; i<personas; i++)
               puts (persona[i].nombre);
            break;
                
         case 3:    /* Ver todos los datos de una persona */
            printf ("Nombre a buscar? ");
            gets(textoAux);
            j = 0;
            for (i=0; i<=personas; i++)
            { 
               if (strcmp (textoAux, persona[i].nombre) == 0)
               {
                  puts (persona[i].nombre);
                  if (strcmp(persona[i].nombre, "") == 0)
                     break;
                  puts (persona[i].direccion);
                  puts (persona[i].celular);
                  puts (persona[i].email);
                  printf("%hd %hd %hd.\n", persona[i].dia,
                     persona[i].mes, persona[i].anyo);
                  j ++;
               }                
            }
            if (j == 0)
               printf("No existe esa ficha.");
            break;
         }
       }
       while (opcion != 0);
       
       fichero = fopen("agenda.dat", "wb");  
       for (i=0; i<personas; i++)
          fwrite(&persona[i], sizeof(persona), 1, fichero);
           
       fclose(fichero);
       return 0;
                            
 }




 /* 6.8b_ 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”, usando “fwrite”. Cerrar el fichero, volverlo a abrir para lectura y mostrar los datos
 que se habían guardado, que se deben leer con “fread”. */
  
#include <stdio.h>

 struct datos
   {
      char nombre[21];
      int edad;
      char ciudad[20];
   }persona;       

int main()
{
   FILE *fichero;
   int i;
     
   if ((fichero = fopen("gente.dat", "wb")) == NULL)
      printf("No se pudo abrir el archivo.\n");
   else
   {     
      do
      {
         printf("Nombre: ");
         gets(persona.nombre);
         printf("Edad: ");  
         scanf("%d", &persona.edad);  
            /* Después de este primer scanf() no se necesita un getchar(). */
         printf("Ciudad: ");
         scanf("%s", persona.ciudad);
         getchar();     /* Aquí sí,  es necesario. */
         i++;
      }
      while (i < 10);
      
      
      fwrite(&persona, sizeof(persona), 1, fichero);
      
      fclose(fichero);
  } 
  
  if((fichero = fopen("gente.dat", "rb")) == NULL)
     printf("No se pudo abrir el archivo.\n"); 
  else
  { 
     fread(&persona, sizeof (persona), 1, fichero);   
     
     puts(persona.nombre); 
     printf("%d\n", persona.edad); 
     puts(persona.ciudad); 
     
       
     fclose(fichero);
  }
  getchar();
     
}




/*6.8c_ Ampliar el programa anterior para que use un “array de structs”, de forma que se puedan 
 tener datos de 10 personas. Se deberá pedir al usuario los datos de las 10 personas y guardarlos
 en el fichero, usando “fwrite”. Después se pedirá al usuario un número del 1 al 10 y se mostra-
 rán los datos de la persona indicada por ese número, que se deberán leer de fichero (1 será la
 primera ficha, y 10 será la última). Por ejemplo, si el usuario indica que quiere ver los datos 
 de la persona 3 (tercera), se deberá leer las dos primeras (con “fread”), ignorando su contenido,
 y después leer la tercera, que sí se deberá mostrar. */
 
#include <stdio.h>
#include <string.h>

 struct datos
   {
      char nombre[21];
      int edad;
      char ciudad[20];
   }persona[10];       

int main()
{
   FILE *fichero;
   int i=0, numero;
     
   if ((fichero = fopen("gente.dat", "wb")) == NULL)
      printf("No se pudo abrir el archivo.\n");
   else
   {     
      do
      {
         printf("Nombre: ");
         gets(persona[i].nombre);
         printf("Edad: "); 
         scanf("%d", &persona[i].edad);
         printf("Ciudad: ");
         scanf("%s", persona[i].ciudad);
         fflush(stdin);                       /* Un getchar() bastaría. */ 
         i++;
      }
      while (i < 10);
       
      fwrite(&persona[i], sizeof(persona), 1, fichero);
      
      fclose(fichero);
  } 
  
  if((fichero = fopen("gente.dat", "rb")) == NULL)
     printf("No se pudo abrir el archivo.\n"); 
  else
  {        
     do 
     {
        puts("Escriba el numero del fichero a leer:\n" 
                 "(Para salir, escriba 0).");
        scanf("%d", &numero);
        for (i=0; i<numero; i++)
        {  
           if (i == (numero-1))     
           {
              printf("Nombre:%s\nEdad:%d\nCiudad:%s\n", 
                 persona[i].nombre, persona[i].edad, persona[i].ciudad);   
              getchar();   
           }
        }
     }   
     while ((numero > 0) && (numero <= 10));   
                                                          
     fclose(fichero);
     }
     getchar();
}




 /* 6.9_ Ampliar el programa anterior (el “array de structs” con 10 personas) para que el dato que 
 indique el usuario se lea sin leer y descartar antes los que le preceden, sino que se salte 
 directamente a la ficha deseada usando “fseek”. */
 
#include <stdio.h>

 struct datos
   {
      char nombre[21];
      unsigned short int edad;
      char ciudad[21];
   }persona[10];       

int main()
{
   FILE *fichero;
   int i=0;
   unsigned short int numero;
     
   if ((fichero = fopen("gente.dat", "wb")) == NULL)
      printf("No se pudo abrir el archivo.\n");
   else
   {     
      do
      {
         puts("Nombre:");       
         gets(persona[i].nombre);       
         puts("Edad:");        
         scanf("%hd", &persona[i].edad);
         fflush(stdin);        
         puts("Ciudad:");      
         gets(persona[i].ciudad);   
         fwrite(&persona[i], sizeof(persona), 1, fichero);
         i++;
      }
      while (i < 10);    
      fclose(fichero);
  } 
  
  if((fichero = fopen("gente.dat", "rb")) == NULL)
     printf("No se pudo abrir el archivo.\n"); 
  else
  {   
     do 
     {
        puts("Escriba el numero del fichero a leer:\n" 
                 "(Para salir, escriba 0).");
        scanf("%d", &numero);  
        i = numero-1;
        fseek(fichero, 0, SEEK_END);
        fread(&persona[i], sizeof(persona), 1,  fichero);
        printf("Nombre:%s\n Edad:%hd\n Ciudad:%s\n\n", 
           persona[i].nombre, persona[i].edad, persona[i].ciudad);           
     }   
     while ((numero > 0) && (numero <= 10));                                            
     fclose(fichero);
  }
  
}


    .......Saludos a todos!


02-Aug-2012 18:30
Pablo Rampa

Perdón, en el ejercicio próximo anterior (6.9) no estoy usando
correctamente la función fseek; Es más, no está haciendo nada en
el programa. La corrección es la siguiente:


fseek(fichero, sizeof(persona)*(numero-1), SEEK_SET);
fread(&persona[i], sizeof(persona), 1,  fichero); 
printf("Nombre:%s\n Edad:%hd\n Ciudad:%s\n\n", 
persona[i].nombre, persona[i].edad, persona[i].ciudad);  


                        .....Saludos cordiales a todos.






(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.)