Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: samur88 en 18 Febrero 2011, 02:30 am



Título: Problema para pasar una lista a fichero con Fwrite
Publicado por: samur88 en 18 Febrero 2011, 02:30 am
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:

Código
  1. typedef struct nodo_pacientes{
  2.         int dni;
  3.         int fecha;
  4.         int edad;
  5.         int medico;
  6.         struct nodo_pacientes *next;
  7.        }pacientes;
  8.  

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:

Código
  1. int list_fic(pacientes **primero){
  2. FILE *fp;
  3. pacientes *aux;
  4.  
  5. int b = 0;
  6. fp = fopen("pacientes.txt","wb");
  7. aux = *primero;
  8.  
  9. while(aux != NULL){
  10.  b = fwrite(&aux,sizeof(pacientes),1,fp);
  11.  aux = aux->next;
  12. }
  13.  
  14. fclose (fp);
  15. printf("\n\n %d",b);
  16. }

Un saludo, espero que podáis ayudarme.


Título: Re: Problema para pasar una lista a fichero con Fwrite
Publicado por: _*p en 18 Febrero 2011, 02:53 am
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...


Título: Re: Problema para pasar una lista a fichero con Fwrite
Publicado por: samur88 en 18 Febrero 2011, 13:05 pm
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:

Código
  1. int leer_fic(pacientes *first){
  2. FILE *fp;
  3. pacientes *aux;
  4.  
  5. fp = fopen("pacientes.dat","r+b");
  6.  
  7. fread(&first,sizeof(pacientes),1,fp);
  8. fclose (fp);
  9.  
  10. aux = first;
  11. printf("%d",aux->dni);
  12. }


Título: Re: Problema para pasar una lista a fichero con Fwrite
Publicado por: _*p en 18 Febrero 2011, 13:57 pm
Es lo mismo leer un .txt que un .dat desde c?
Una pregunta... estás reservando la memoria para leer bloques de código?


Título: Re: Problema para pasar una lista a fichero con Fwrite
Publicado por: samur88 en 18 Febrero 2011, 14:05 pm
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.


Título: Re: Problema para pasar una lista a fichero con Fwrite
Publicado por: samur88 en 18 Febrero 2011, 14:10 pm
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).


Título: Re: Problema para pasar una lista a fichero con Fwrite
Publicado por: _*p en 18 Febrero 2011, 16:06 pm
Tal vez te sirva esto   ;)


Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3.  
  4. typedef struct _nodo {
  5.   int dni;
  6.   int fecha;
  7.   struct _nodo *siguiente;
  8. } tipoNodo;
  9.  
  10. typedef tipoNodo *pNodo;
  11. typedef tipoNodo *Lista;
  12.  
  13. /* Funciones con listas: */
  14. void Insertar(Lista *l, int d, int f);
  15. void Borrar(Lista *l, int d);
  16.  
  17. int ListaVacia(Lista l);
  18.  
  19. void BorrarLista(Lista *);
  20. void MostrarLista(Lista l);
  21.  
  22. void list_fic(Lista L);
  23. void leer_fic();
  24.  
  25. int main()
  26. {
  27.   Lista lista = NULL;
  28.   pNodo p;
  29.  
  30.   Insertar(&lista, 1111, 11 );
  31.   Insertar(&lista, 2222, 22);
  32.  
  33.  
  34.   MostrarLista(lista);
  35.   list_fic(lista);
  36.   leer_fic();
  37.   return 0;
  38. }
  39.  
  40. void Insertar(Lista *lista, int d, int f)
  41. {
  42.   pNodo nuevo, anterior;
  43.  
  44.   /* Crear un nodo nuevo */
  45.   nuevo = (pNodo)malloc(sizeof(tipoNodo));
  46.   nuevo->dni = d;
  47.   nuevo->fecha = f;
  48.  
  49.   /* Si la lista está vacía */
  50.   if(ListaVacia(*lista) || (*lista)->dni > d) {
  51.      /* Añadimos la lista a continuación del nuevo nodo */
  52.      nuevo->siguiente = *lista;
  53.      /* Ahora, el comienzo de nuestra lista es en nuevo nodo */
  54.      *lista = nuevo;
  55.   }
  56.   else {
  57.      /* Buscar el nodo de valor menor a v */
  58.      anterior = *lista;
  59.      /* Avanzamos hasta el último elemento o hasta que el siguiente tenga
  60.          un valor mayor que v */
  61.      while(anterior->siguiente && anterior->siguiente->dni <= d)
  62.         anterior = anterior->siguiente;
  63.      /* Insertamos el nuevo nodo después del nodo anterior */
  64.      nuevo->siguiente = anterior->siguiente;
  65.      anterior->siguiente = nuevo;
  66.   }
  67. }
  68.  
  69. void Borrar(Lista *lista, int d)
  70. {
  71.   pNodo anterior, nodo;
  72.  
  73.   nodo = *lista;
  74.   anterior = NULL;
  75.   while(nodo && nodo->dni < d ) {
  76.      anterior = nodo;
  77.      nodo = nodo->siguiente;
  78.   }
  79.   if(!nodo || nodo->dni != d) return;
  80.   else { /* Borrar el nodo */
  81.      if(!anterior) /* Primer elemento */
  82.         *lista = nodo->siguiente;
  83.      else  /* un elemento cualquiera */
  84.         anterior->siguiente = nodo->siguiente;
  85.      free(nodo);
  86.   }
  87. }
  88.  
  89. int ListaVacia(Lista lista)
  90. {
  91.   return (lista == NULL);
  92. }
  93.  
  94. void BorrarLista(Lista *lista)
  95. {
  96.   pNodo nodo;
  97.  
  98.   while(*lista) {
  99.      nodo = *lista;
  100.      *lista = nodo->siguiente;
  101.      free(nodo);
  102.   }
  103. }
  104.  
  105. void MostrarLista(Lista lista)
  106. {
  107.   pNodo nodo = lista;
  108.  
  109.   if(ListaVacia(lista)) printf("Lista vacía\n");
  110.   else {
  111.      while(nodo) {
  112.         printf("DNI-> %d -> ", nodo->dni);
  113.         printf("FECHA-> %d -> ", nodo->fecha);
  114.         nodo = nodo->siguiente;
  115.     }
  116.     printf("\n");
  117.   }
  118. }
  119.  
  120. void list_fic(Lista L)
  121. {
  122. FILE *fp;
  123. tipoNodo *aux;
  124.  
  125. int b = 0;
  126. fp = fopen("pacientes.txt","wb");
  127. aux = L;
  128.  
  129. while(aux != NULL)
  130. {
  131.  b = fwrite(&aux,sizeof(tipoNodo),1,fp);
  132.  aux = aux->siguiente;
  133. }
  134.  
  135. fclose (fp);
  136. }
  137.  
  138. void leer_fic(){
  139. FILE *fp;
  140. tipoNodo *aux;
  141.  
  142. fp = fopen("pacientes.txt","r+b");
  143.  
  144. fread(&aux,sizeof(tipoNodo),1,fp);
  145.  
  146. fclose (fp);
  147. puts("LECTURA!");
  148. printf("DNI:%d\n",aux->dni);
  149. printf("FECHA:%d\n",aux->fecha);
  150. puts("FIN DE LECTURA");
  151. }

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


Título: Re: Problema para pasar una lista a fichero con Fwrite
Publicado por: samur88 en 19 Febrero 2011, 14:46 pm
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:

Código
  1. typedef struct _nodo {
  2.  int dni;
  3.  int fecha;
  4.  struct _nodo *siguiente;
  5. } tipoNodo;
  6.  
  7. typedef tipoNodo *pNodo;
  8. typedef tipoNodo *Lista;

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

Código
  1. typedef struct _nodo {
  2.  int dni;
  3.  int fecha;
  4.  struct _nodo *siguiente;
  5. }tipoNodo;
  6.  
  7. int main(){
  8. tipoNodo *pNodo;
  9. tipoNodo *Lista;
  10.  
  11. }

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:
Código
  1. void leer_fic(){
  2. FILE *fp;
  3. tipoNodo *aux;
  4. while(!feof(fp)){
  5. fp = fopen("pacientes.txt","r+b");
  6.  
  7. fread(&aux,sizeof(tipoNodo),1,fp);
  8.  
  9. puts("LECTURA!");
  10. printf("DNI:%d\n",aux->dni);
  11. printf("FECHA:%d\n",aux->fecha);
  12. puts("FIN DE LECTURA");
  13. aux = aux->siguiente;
  14. }
  15. fclose (fp);
  16. }


Un saludo y gracias de nuevo.



Título: Re: Problema para pasar una lista a fichero con Fwrite
Publicado por: Ferno en 19 Febrero 2011, 17:54 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:
Código
  1. void leer_fic(){
  2. FILE *fp;
  3. tipoNodo *aux;
  4. while(!feof(fp)){
  5. fp = fopen("pacientes.txt","r+b");
  6.  
  7. fread(&aux,sizeof(tipoNodo),1,fp);
  8.  
  9. puts("LECTURA!");
  10. printf("DNI:%d\n",aux->dni);
  11. printf("FECHA:%d\n",aux->fecha);
  12. puts("FIN DE LECTURA");
  13. aux = aux->siguiente;
  14. }
  15. fclose (fp);
  16. }


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


Título: Re: Problema para pasar una lista a fichero con Fwrite
Publicado por: samur88 en 19 Febrero 2011, 18:24 pm
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.


Título: Re: Problema para pasar una lista a fichero con Fwrite
Publicado por: samur88 en 19 Febrero 2011, 18:55 pm
Fbin he estado haciendo pruebas con el codigo que me pusiste, pero he notado algunos fallos, supuestamente el fichero es independiente de la estructura, pero el caso es que si borro la estructura y luego leo el fichero me da lo que supuestamente tendría que ser dni, etc.. posiciones de memoría extrañas, no debería a ver problema si borrara la lista y luego leyese la estructura ¿no?, también he probado leyendo el archivo desde un programa externo y me da el mismo error, me lee y me da muchos números, adjunto el programa desde el cual he leido el fichero:

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. typedef struct _nodo {
  5.  int dni;
  6.  int fecha;
  7.  struct _nodo *siguiente;
  8. } tipoNodo;
  9.  
  10. void leer_fic(){
  11.     FILE *fp;
  12.     tipoNodo *aux;
  13.     int a = 0;
  14.  
  15.     fp = fopen("pacientes.txt","r+b");
  16.  
  17.     while(!feof(fp)){
  18.      a = fread(&aux,sizeof(tipoNodo),1,fp);
  19.      if(a != 0){
  20.           puts("LECTURA!");
  21.           printf("DNI:%d\n",aux->dni);
  22.           printf("FECHA:%d\n",aux->fecha);
  23.           printf("%d\n",a);
  24.           puts("FIN DE LECTURA\n");
  25.      }
  26.     }
  27.     fclose (fp);
  28. }
  29.  
  30. int main(){
  31. leer_fic();
  32. return 0;  
  33. }
  34.  

Un saludo.


Título: Re: Problema para pasar una lista a fichero con Fwrite
Publicado por: .:BlackCoder:. en 20 Febrero 2011, 03:19 am
Creo que debes asignarle memoria a aux en tu funcion...

Saludos...


Título: Re: Problema para pasar una lista a fichero con Fwrite
Publicado por: samur88 en 21 Febrero 2011, 01:06 am
Muchas gracias, al final me di cuenta de que la función fwrite y fread no reciben un puntero a una estructura si no una estructura en si, de esta forma los datos se almacenan en dicha estructura, ese era mi problema, usando un estructura auxiliar para leer los datos con fread lo he conseguido sin problemas.
Un saludo.