Ver Mensaje Individual
  #3 (permalink)  
Antiguo 18/01/2008, 04:17
numero5
 
Fecha de Ingreso: enero-2008
Mensajes: 5
Antigüedad: 16 años, 4 meses
Puntos: 0
Re: problema leyendo un archivo con estructuras

muchas gracias _Lucifer_, tienes razón. He corregido un poco el código, pero me sigue pasando lo mismo...el archivo gastos.dts contiene los siguientes registros en binario:

Código:
 |   0 |   Nombre 1 |                     Concepto 1 | 29/ 3/1989 |     0 |
 |   1 |   Nombre 2 |                     Concepto 2 | 30/ 3/1989 |     0 |
 |   2 |   Nombre 3 |                     Concepto 3 | 31/ 3/1989 |     0 |
 |   3 |   Nombre 4 |                     Concepto 4 |  1/ 4/1989 |     0 |
Con esto, la funcion abrir (en rojo las modificaciones) debería mostrarme siempre los 4 resgistros que hay en gastos.dts:

Código:
void abrir() {

    FILE * fp;
    fp = fopen("gastos.dts", "rb");
    _gasto *aux, *auxSIG;
    aux = (_gasto *) malloc(sizeof(_gasto));
    auxSIG = (_gasto *) malloc(sizeof(_gasto));
    aux->sigGasto = auxSIG;

    while (!feof(fp)) {
        fread(aux, sizeof(_gasto), 1, fp);
        printf(" | %3d | %10s | %30s | %2i/%2i/%4i | %5i |\n",
                aux->i, aux->nombre, aux->concepto, aux->fecha.dia,
                aux->fecha.mes, aux->fecha.ano, aux->importe);
        aux = aux->sigGasto;
    }

    fclose(fp);

    free(aux);
    free(auxSIG);
}
Y sin embargo, hay veces que si que me muestra los 4 resgistros, y otras que solo me muestra el primero, de una forma totalmente aleatoria. He probado ya todo lo que se me ocurre, y no consigo arreglarlo :(

La otra duda que me queda es que cuando declaro los punteros a la lista, me toca declarar un puntero para cada elemento que vaya a introducir, y reservarle memoria (en rojo lo que he añadido):

Código:
int main(char argv[], int argc) {

    DB = (_gasto *) malloc(sizeof(_gasto));
    DB->sigGasto = (_gasto *) malloc(sizeof(_gasto));
    DB->sigGasto->sigGasto = (_gasto *) malloc(sizeof(_gasto));
    DB->sigGasto->sigGasto->sigGasto = (_gasto *) malloc(sizeof(_gasto));

    abrir();

    free(DB);
    free(DB->sigGasto);
    free(DB->sigGasto->sigGasto);
    free(DB->sigGasto->sigGasto->sigGasto);
    return 0;
}
Y estoy seguro que se tiene que poder hacer de otra forma, sin tener que declarar 4 punteros y reservarle memoria a los 4...

Mi idea, por si no se entiende bien lo que estoy intentando hacer, es abrir un archivo con un número de registros que yo desconozco, e ir metiendolos en una lista enlazada. Y una vez esten en la lista enlazada, mostrarlos. No los muestro directamente porque después me tocará operar con ellos, por eso los necesito guardar de alguna forma en la memoria, y en la universidad me han dicho que debo hacerlo con listas enlazadas.

Aquí dejo otra vez el código entero con las modificaciones (en rojo) que le he hecho:
Código:
#include <stdio.h>
#define MAX_N 10 /* MAX_NOMBRE */
#define MAX_C 30 /* MAX_CONCEPTO */

typedef struct {
    int dia;
    int mes;
    int ano;
} _fecha;


struct gasto{
    int i;
    char nombre[MAX_N];
    char concepto[MAX_C];
    _fecha fecha;
    float importe;
    struct gasto * sigGasto;
};
typedef struct gasto _gasto;

_gasto *DB;

void abrir();
void guardar(_gasto *);

int main(char argv[], int argc) {

    DB = (_gasto *) malloc(sizeof(_gasto));
    DB->sigGasto = (_gasto *) malloc(sizeof(_gasto));
    DB->sigGasto->sigGasto = (_gasto *) malloc(sizeof(_gasto));
    DB->sigGasto->sigGasto->sigGasto = (_gasto *) malloc(sizeof(_gasto));

    abrir();

    free(DB);
    free(DB->sigGasto);
    free(DB->sigGasto->sigGasto);
    free(DB->sigGasto->sigGasto->sigGasto);
    return 0;
}


// Cada ejecucion da un resultado.
void abrir() {

    FILE * fp;
    fp = fopen("gastos.dts", "rb");
    _gasto *aux, *auxSIG;
    aux = (_gasto *) malloc(sizeof(_gasto));
    auxSIG = (_gasto *) malloc(sizeof(_gasto));
    aux->sigGasto = auxSIG;

    while (!feof(fp)) {
        fread(aux, sizeof(_gasto), 1, fp);
        printf(" | %3d | %10s | %30s | %2i/%2i/%4i | %5i |\n",
                aux->i, aux->nombre, aux->concepto, aux->fecha.dia,
                aux->fecha.mes, aux->fecha.ano, aux->importe);
        aux = aux->sigGasto;
    }

    fclose(fp);

    free(aux);
    free(auxSIG);
}


void guardar(_gasto *guardar) {

    FILE * fp;
    int contador = 0;

    /* Abro el archivo gastos.dts para escritura */
    fp = fopen("gastos.dts", "wb");

    /* Mientras que haya algun registro "gasto" lo escribe en el archivo gastos.dts */
    while (guardar != NULL) {
        fwrite(guardar, sizeof(_gasto), 1, fp);
        guardar = guardar->sigGasto;
        contador++;
    }

    /* Cierra el arhivo */
    fclose(fp);

    /* Libero memoria */
    free(guardar);

    printf("Datos guardados: %i", contador);
}
Muchas gracias,
saludos.