Problema para pasar una lista a fichero con Fwrite

Iniciado por samur88, 18 Febrero 2011, 02:30 AM

0 Miembros y 1 Visitante están viendo este tema.

samur88

Saludos.
Tengo el siguiente problema, quiero pasar una lista a un fichero, la lista tiene datos que yo previamente le he introducido y los he mostrado para verificar que los datos son correctos, el caso es que cuando intento pasar dicha lista un fichero de la siguiente forma con fwrite, solo me mete basura en el fichero.
Dejo el código a ver si podéis ayudarme:

Esta es la estructura de la lista:


typedef struct nodo_pacientes{
         int dni;
         int fecha;
         int edad;
         int medico;
         struct nodo_pacientes *next;
        }pacientes;


Esta es la función que uso para escribir en el fichero a la cual le paso un puntero por referencia al primer elemento de la lista:

int list_fic(pacientes **primero){
FILE *fp;
pacientes *aux;

int b = 0;
fp = fopen("pacientes.txt","wb");
aux = *primero;

while(aux != NULL){
  b = fwrite(&aux,sizeof(pacientes),1,fp);
  aux = aux->next;
}

fclose (fp);
printf("\n\n %d",b);
}


Un saludo, espero que podáis ayudarme.

_*p

Por lo que veo, está bien a simple vista... ¿Tienes una función para leer el .txt? Si lees con un editor de textos debería darte "basura" ya que es un binario...

samur88

Muchas gracias por la respuesta.
Tengo una función para leerlo, lo siento se me olvido adjuntarla, la pongo aqui, pero me da fallos, igual es la función la que esta mal:

int leer_fic(pacientes *first){
FILE *fp;
pacientes *aux;

fp = fopen("pacientes.dat","r+b");

fread(&first,sizeof(pacientes),1,fp);
fclose (fp);

aux = first;
printf("%d",aux->dni);
}

_*p

Es lo mismo leer un .txt que un .dat desde c?
Una pregunta... estás reservando la memoria para leer bloques de código?

samur88

Discúlpame, es que al ser un archivo binario decidí guardarlo en un .dat en vez de un .txt en teoría es lo mismo, así que supongo no habría problemas por eso.
En la estructura tengo datos insertados, los he comprado mostrándolo por pantalla, luego la función que tengo para guardar la estructura en el fichero es la que puse anteriormente y función que tengo para cargar los datos del fichero en la estructura es esa que puse ahora.
¿Tengo que reservar memoria para guardar los datos del archivo en la lista?
Un saludo y muchas gracias.

samur88

Disculpa, me olvide de decir que efectivamente si reservo memoria para la lista almacenada en el fichero a la hora de leer.
Ya que la lectura la hago desde otro programa, en el que tengo una estructura exactamente igual a la estructura del primero (programa que graba la lista en el fichero).

_*p

Tal vez te sirva esto   ;)


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

typedef struct _nodo {
   int dni;
   int fecha;
   struct _nodo *siguiente;
} tipoNodo;

typedef tipoNodo *pNodo;
typedef tipoNodo *Lista;

/* Funciones con listas: */
void Insertar(Lista *l, int d, int f);
void Borrar(Lista *l, int d);

int ListaVacia(Lista l);

void BorrarLista(Lista *);
void MostrarLista(Lista l);

void list_fic(Lista L);
void leer_fic();

int main()
{
   Lista lista = NULL;
   pNodo p;

   Insertar(&lista, 1111, 11 );
   Insertar(&lista, 2222, 22);


   MostrarLista(lista);
   list_fic(lista);
   leer_fic();
   return 0;
}

void Insertar(Lista *lista, int d, int f)
{
   pNodo nuevo, anterior;

   /* Crear un nodo nuevo */
   nuevo = (pNodo)malloc(sizeof(tipoNodo));
   nuevo->dni = d;
   nuevo->fecha = f;

   /* Si la lista está vacía */
   if(ListaVacia(*lista) || (*lista)->dni > d) {
      /* Añadimos la lista a continuación del nuevo nodo */
      nuevo->siguiente = *lista;
      /* Ahora, el comienzo de nuestra lista es en nuevo nodo */
      *lista = nuevo;
   }
   else {
      /* Buscar el nodo de valor menor a v */
      anterior = *lista;
      /* Avanzamos hasta el último elemento o hasta que el siguiente tenga
         un valor mayor que v */
      while(anterior->siguiente && anterior->siguiente->dni <= d)
         anterior = anterior->siguiente;
      /* Insertamos el nuevo nodo después del nodo anterior */
      nuevo->siguiente = anterior->siguiente;
      anterior->siguiente = nuevo;
   }
}

void Borrar(Lista *lista, int d)
{
   pNodo anterior, nodo;

   nodo = *lista;
   anterior = NULL;
   while(nodo && nodo->dni < d ) {
      anterior = nodo;
      nodo = nodo->siguiente;
   }
   if(!nodo || nodo->dni != d) return;
   else { /* Borrar el nodo */
      if(!anterior) /* Primer elemento */
         *lista = nodo->siguiente;
      else  /* un elemento cualquiera */
         anterior->siguiente = nodo->siguiente;
      free(nodo);
   }
}

int ListaVacia(Lista lista)
{
   return (lista == NULL);
}

void BorrarLista(Lista *lista)
{
   pNodo nodo;

   while(*lista) {
      nodo = *lista;
      *lista = nodo->siguiente;
      free(nodo);
   }
}

void MostrarLista(Lista lista)
{
   pNodo nodo = lista;

   if(ListaVacia(lista)) printf("Lista vacía\n");
   else {
      while(nodo) {
         printf("DNI-> %d -> ", nodo->dni);
         printf("FECHA-> %d -> ", nodo->fecha);
         nodo = nodo->siguiente;
     }
     printf("\n");
   }
}

void list_fic(Lista L)
{
FILE *fp;
tipoNodo *aux;

int b = 0;
fp = fopen("pacientes.txt","wb");
aux = L;

while(aux != NULL)
{
  b = fwrite(&aux,sizeof(tipoNodo),1,fp);
  aux = aux->siguiente;
}

fclose (fp);
}

void leer_fic(){
FILE *fp;
tipoNodo *aux;

fp = fopen("pacientes.txt","r+b");

fread(&aux,sizeof(tipoNodo),1,fp);

fclose (fp);
puts("LECTURA!");
printf("DNI:%d\n",aux->dni);
printf("FECHA:%d\n",aux->fecha);
puts("FIN DE LECTURA");
}


./listas
DNI-> 1111 -> FECHA-> 11 -> DNI-> 2222 -> FECHA-> 22 ->
LECTURA!
DNI:1111
FECHA:11
FIN DE LECTURA


samur88

#7
Muchisimas gracías por mostrarme la forma de escribir y leer correctamente con el archivo, solo una duda que tengo al respecto, es sobre mi forma de definir el trabajo con listas.

Tu defines dos nuevos tipo de datos que son en realidad dos punteros a la misma lista o mejor dicho defines la forma de trabajar con dos listas diferentes pero con la misma estructura de datos:

typedef struct _nodo {
 int dni;
 int fecha;
 struct _nodo *siguiente;
} tipoNodo;

typedef tipoNodo *pNodo;
typedef tipoNodo *Lista;


El caso es que yo eso lo hago de la siguiente forma:

typedef struct _nodo {
 int dni;
 int fecha;
 struct _nodo *siguiente;
}tipoNodo;

int main(){
tipoNodo *pNodo;
tipoNodo *Lista;

}


pero no consigo adaptar esas funciones y que el programa no de fallo de segmentación a la forma en la que lo hago, si me puedes indicar que hago mal lo agradecería mucho.

Lo siento, solucionado, fue un descuido, si puedes responderme a lo otro, lo agradecería mucho  >:D Disculpa otra duda que tendría sería, si quiero leer todos los nodos de la lista, lo hago de esta forma en el codigo que me has pasado pero no me funciona correctamente, el bucle se ejecuta no leyendo todos los nodos almacenados y luego el programa se cierra automáticamente:
void leer_fic(){
FILE *fp;
tipoNodo *aux;
while(!feof(fp)){
fp = fopen("pacientes.txt","r+b");

fread(&aux,sizeof(tipoNodo),1,fp);

puts("LECTURA!");
printf("DNI:%d\n",aux->dni);
printf("FECHA:%d\n",aux->fecha);
puts("FIN DE LECTURA");
aux = aux->siguiente;
getchar();
}
fclose (fp);
}



Un saludo y gracias de nuevo.


Ferno

#8
Cita de: samur88 en 19 Febrero 2011, 14:46 PM
Disculpa otra duda que tendría sería, si quiero leer todos los nodos de la lista, lo hago de esta forma en el codigo que me has pasado pero no me funciona correctamente, el bucle se ejecuta no leyendo todos los nodos almacenados y luego el programa se cierra automáticamente:
void leer_fic(){
FILE *fp;
tipoNodo *aux;
while(!feof(fp)){
fp = fopen("pacientes.txt","r+b");

fread(&aux,sizeof(tipoNodo),1,fp);

puts("LECTURA!");
printf("DNI:%d\n",aux->dni);
printf("FECHA:%d\n",aux->fecha);
puts("FIN DE LECTURA");
aux = aux->siguiente;
getchar();
}
fclose (fp);
}



Un saludo y gracias de nuevo.



Que alguien me corrija si me equivoco, pero estoy seguro que debes abrir el archivo antes de corroborar que no ha llegado a su fin (usar fopen antes de feof). Además debes sacarlo del bucle, sino estarías abriendo el archivo constantemente (si es que funciona!!).

samur88

Lo siento fermo jeje es tal y como dices, me dolía bastante la cabeza y tuve ese descuido y no sabía muy bien por que era, luego lo arregle y corregí el post que puse preguntando esa duda.

La única duda que tengo ahora mismo a la hora de insertar y leer desde el archivo es como puedo hacerlo usando punteros locales a la función main, sin definir nuevos tipos de datos que sean punteros a la propia estructura ya de por si, lo he intentado pero siempre me da fallos.

Un saludo y gracias por la corrección.