Programación General > C/C++

 [C] Estructuras y archivos binarios

<< < (2/2)

ProfesorX:
Bueno, ya te contestaron la mayoria de las dudas que tenias, solo añadire que no se recomienda el uso de scanf, ya que tiene el problema de que lee toda la entrada hasta que pulsas enter o encuentra un espacio.

Entonces ¿que pasa si tu defines tu cadena como de 12 caracteres, y por un error el usuario captura 15? pues que te guarda los 15 caracteres, pero como tu cadena es de 12, ocurre lo que se conoce como un desbordamiento de buffer, corrompiendo la memoria y con ella tu programa.

Cuando un programa es pequeño, estos desbordamientos no son fatales, pero en programas grandes si pueden serlo, ocasionando diversos problemas, entre ellos, el congelamiento o cuelgue del sistema.

Lo mas recomendable es usar fgets(), que te limita el total de caracteres que vas a leer, con esta funcion no puede haber un desbordamiento, ya que nunca leera mas de los caracteres que le digas que lea, aun cuando el usuario erronea o intencionalmente capture caracteres de mas. Claro que aun puede haber un desbordamiento de buffer si le dices que lea un maximo de 15, pero reservas para tu cadena menos de 15 caracteres, por ponerte un ejemplo.

Ademas, no es necesario que leas todo el archivo desde el principio para posicionarte al final del archivo, puedes usar la funcion fseek para esto, o abrir el archivo en modo append binario (ab+) si lo abres con append, automaticamente coloca el apuntador de archivo al final del archivo.

Te dejo el codigo que corregi, con comentarios para que quede mas claro :)


--- Código: C++ --- // Inserción en la tablavoid insert_into_table(){    int menu2_on = 1;     struct persona avance;     FILE *save_file;     save_file = fopen ("archivo.dat", "rb+");    // Coloca el apuntador de posicion de archivo al final del archivo    // No necesitas leer todo el archivo para posicionarte al final    // tambien podrias abrir el archivo con "ab+" en lugar de "rb+"    // y te evitas el tener que usar fseek    fseek(save_file, 0, SEEK_END);     do {         struct persona data_save;        // Variable de tipo cadena para capturar la edad con fgets, ya que fgets        // solo funciona con cadenas.        char edad[3];         printf("Rut de la personan");        // Borra el buffer de entrada, para que no haya nada al leer los datos        // con fgets        while(getchar() != 'n');        // El tercer parametro es la longitud de tu cadena con el caracter de        // fin de cadena incuido. Si necesitas guardar 11 caracteres,        // debes reservar espacio para 12 (11+fin cadena). Si necesitas        // guardar 12, debes reservar espacio para 13, y asi, siempre        // debes reservar espacio para un caracter mas, que es el fin de cadena        fgets(data_save.rut, 12, stdin);         printf("Edad de la personan");        while(getchar() != 'n');        fgets(edad, 3, stdin);        // Conviertes la edad        data_save.edad = atoi(edad);                printf("Nombre de la personan");        while(getchar() != 'n');        fgets(data_save.nombre, 255, stdin);         fwrite (&data_save , 1 , sizeof(struct persona) , save_file);         printf("¿Desea agregar otra tupla? (1 Si, 0 No)n");        scanf("%d", &menu2_on);     } while (menu2_on == 1);     fclose(save_file);     struct persona junior;    FILE  *test_file;     test_file = fopen ("archivo.dat", "rb");    if (test_file==NULL)        printf ("No se pudo abrir el archivon");     printf("Rut              Edad   Nombren");    printf("--------------------------------------------------------------------n");       while (!feof(test_file))    {           fread (&junior, sizeof(struct persona), 1, test_file);        // Necesitas volver a comprobar si despues de leer llegaste al final del archivo        if (!feof(test_file))        {            printf("%s     %d     %sn", junior.rut, junior.edad, junior.nombre);          }     }     // No olvides cerrar tus archivos    fclose(test_file);}  
Saludos :)

Amphoth3ra:
Bueno, en el programa final usé scanf y no fgets, aunque igual me funcionaba, lo tomaré en cuenta para después. El feof funcionó tal cual como me dijeron, el dato no se guardaba duplicado.

Saludos.

Navegación

[0] Índice de Mensajes

[*] Página Anterior

Ir a la versión completa