Foros-FIUBA Foros HostingPortal
 FAQ  •  Buscar  •  Wiki  •  Apuntes  •  Planet  •  Mapa  •  Eyeon  •  Chat
Preferencias  •  Grupos de Usuarios
Registrarse  •  Perfil  •  Entrá para ver tus mensajes privados  •  Login
Ver tema siguiente
Ver tema anterior

Responder al tema Ver tema anteriorEnviar por mail a un amigo.Mostrar una Lista de los Usuarios que vieron este TemaGuardar este Tema como un archivoPrintable versionEntrá para ver tus mensajes privadosVer tema siguiente
Autor Mensaje
M1thrand1r
Nivel 4


Edad: 31
Registrado: 08 Abr 2013
Mensajes: 92

Carrera: Electrónica
russia.gif
MensajePublicado: Mar Dic 03, 2013 1:42 pm  Asunto:  Duda con estructura dinamica y archivo binario. Responder citandoFin de la PáginaVolver arriba

Hola! Les hago una consulta... Necesito guardar vectores dinamicos que forman parte de una estructura en un archivo binario. El tema es que cuando quiero leer los strings me los corta, para empezar dejo la estructura y la funcion que uso para guardarlo, me gustaria q me digan si hay algun error ahi. Saludos!

typedef struct
{
char *nom;
char *ape;
long dni;
Tfecha f_nac;
} Tpaciente;

void guardar_pacientes(Tpaciente **paciente,int cantidad)
{
int aux,aux2,i;
FILE *fpacientes;

fpacientes=fopen("pacientes.dat","wb");

for(i=0;i<cantidad>nom);

fwrite(paciente[i]->nom,sizeof(char),aux,fpacientes);

aux2=strlen(paciente[i]->ape);

fwrite(paciente[i]->ape,sizeof(char),aux2,fpacientes);

fwrite(&(paciente[i])->dni,sizeof(long),N,fpacientes);

fwrite(&(paciente[i])->f_nac.dd,sizeof(int),N,fpacientes);
fwrite(&(paciente[i])->f_nac.mm,sizeof(int),N,fpacientes);
fwrite(&(paciente[i])->f_nac.aa,sizeof(int),N,fpacientes);
}
fclose(fpacientes);
}


Virgo Género:Masculino Mono OfflineGalería Personal de M1thrand1rVer perfil de usuarioEnviar mensaje privado
Huey 7
Nivel 6



Registrado: 03 Mar 2010
Mensajes: 267

Carrera: Electrónica
CARRERA.electronica.5.gif
MensajePublicado: Mar Dic 03, 2013 7:05 pm  Asunto:  (Sin Asunto) Responder citandoFin de la PáginaVolver arriba

Vos tenés la struct Tpaciente, con campos nom y ape que apuntan a strings. Los estás escribiendo en el archivo con fwrite, usando cada vez como tercer argumento la longitud devuelta por strlen. Con eso estás escribiendo los caracteres que componen cada string, pero perdiste la información de la longitud de cada una. No puedo evitar preguntarme cómo estás haciendo para luego leer el archivo sin tener esa información, y, por lo tanto, cómo sabés dónde termina cada string y empieza el siguiente campo de la struct Tpaciente Smile

_________________
Comisión de Estudiantes de Ingeniería Electrónica (ComElec)
Lista de correo - Página Web - Facebook

 Género:Masculino  OfflineGalería Personal de Huey 7Ver perfil de usuarioEnviar mensaje privado
M1thrand1r
Nivel 4


Edad: 31
Registrado: 08 Abr 2013
Mensajes: 92

Carrera: Electrónica
russia.gif
MensajePublicado: Mar Dic 03, 2013 7:20 pm  Asunto:  (Sin Asunto) Responder citandoFin de la PáginaVolver arriba

Huey 7 escribió:
Vos tenés la struct Tpaciente, con campos nom y ape que apuntan a strings. Los estás escribiendo en el archivo con fwrite, usando cada vez como tercer argumento la longitud devuelta por strlen. Con eso estás escribiendo los caracteres que componen cada string, pero perdiste la información de la longitud de cada una. No puedo evitar preguntarme cómo estás haciendo para luego leer el archivo sin tener esa información, y, por lo tanto, cómo sabés dónde termina cada string y empieza el siguiente campo de la struct Tpaciente Smile


Para leer recorro los caracteres uno por uno hasta encontrar el '\0' con fwrite y los guardo en un string auxiliar. Lo q pasa ahi es lo sigiente:

el nombre es ''nostradamus'', lo leo.. guardo en el auxiliar y cuando imprimo el auxiliar para ver como quedo me imprime ''nostr''.

Cuando paso al campo del apellido me agarra las 3 primeras letras o imprime basura.


Virgo Género:Masculino Mono OfflineGalería Personal de M1thrand1rVer perfil de usuarioEnviar mensaje privado
Huey 7
Nivel 6



Registrado: 03 Mar 2010
Mensajes: 267

Carrera: Electrónica
CARRERA.electronica.5.gif
MensajePublicado: Mar Dic 03, 2013 7:36 pm  Asunto:  (Sin Asunto) Responder citandoFin de la PáginaVolver arriba

M1thrand1r escribió:
Para leer recorro los caracteres uno por uno hasta encontrar el '\0' con fwrite y los guardo en un string auxiliar.

¿Lees un caracter por vez del archivo hasta encontrar el '\0'? En tu función guardar_pacientes no estás escribiendo en el archivo ese '\0', porque no entra en el cómputo de longitud que hace strlen. Si quisieras escribirlo, tendrías que estar invocando fwrite con strlen(paciente[i]->nom) + 1 y strlen(paciente[i]->ape) + 1, respectivamente, como tercer argumento.

_________________
Comisión de Estudiantes de Ingeniería Electrónica (ComElec)
Lista de correo - Página Web - Facebook

 Género:Masculino  OfflineGalería Personal de Huey 7Ver perfil de usuarioEnviar mensaje privado
Sebastian Santisi
Administrador Técnico


Edad: 42
Registrado: 23 Ago 2005
Mensajes: 17451


argentina.gif
MensajePublicado: Mar Dic 03, 2013 7:52 pm  Asunto:  (Sin Asunto) Responder citandoFin de la PáginaVolver arriba

Por un lado, sí, te comiste el +1, nunca guardás el \0.

Por el otro lado, es mucho más razonable que cambies el formato de escritura a:

l = strlen(s);
fwrite(&l, sizeof(size_t), 1, f);
fwrite(s, sizeof(char), l, f); /* Acá ya no importa el +1 */

Con eso podés después leer sin iterar:
fread(&l, sizeof(size_t), 1, f);
fread(s, sizeof(char), l, f);
s[l] = '\0';


(Sobre el foro: Cuando vayas a postear fuentes, tildá "Deshabilitar HTML en este mensaje".)

_________________
Image[tex] ${. \ \ \ \ \ \ \ \ \ .}$ [/tex][tex] ${\Large Usá \LaTeX, no seas foro...}$ [/tex]

Aries Género:Masculino Perro OfflineGalería Personal de Sebastian SantisiVer perfil de usuarioEnviar mensaje privadoVisitar sitio web del usuario
M1thrand1r
Nivel 4


Edad: 31
Registrado: 08 Abr 2013
Mensajes: 92

Carrera: Electrónica
russia.gif
MensajePublicado: Mar Dic 03, 2013 7:56 pm  Asunto:  (Sin Asunto) Responder citandoFin de la PáginaVolver arriba

Huey 7 escribió:

¿Lees un caracter por vez del archivo hasta encontrar el '\0'? En tu función guardar_pacientes no estás escribiendo en el archivo ese '\0', porque no entra en el cómputo de longitud que hace strlen. Si quisieras escribirlo, tendrías que estar invocando fwrite con strlen(paciente[i]->nom) + 1 y strlen(paciente[i]->ape) + 1, respectivamente, como tercer argumento.


Si, me confundi al tipear, en el codigo lo tengo como decis vos.

Para cargar el nombre y el apellido uso fgets, puede ser que esa funcion no me tome el '\0' o algo asi?

Asi cargo nombre y apellido.

fgets(aux,N-1,stdin);
fflush(stdin);

paciente->nom=(char *)malloc(sizeof(char)*(strlen(aux)+1));
strcpy(paciente->nom,aux);

Desde ayer que estoy con este tema y no le puedo encontrar la vuelta.


Virgo Género:Masculino Mono OfflineGalería Personal de M1thrand1rVer perfil de usuarioEnviar mensaje privado
Sebastian Santisi
Administrador Técnico


Edad: 42
Registrado: 23 Ago 2005
Mensajes: 17451


argentina.gif
MensajePublicado: Mar Dic 03, 2013 8:06 pm  Asunto:  (Sin Asunto) Responder citandoFin de la PáginaVolver arriba

Si N es la longitud de aux, es fgets(aux, N, stdin);
fgets() siempre guarda el '\0'.

_________________
Image[tex] ${. \ \ \ \ \ \ \ \ \ .}$ [/tex][tex] ${\Large Usá \LaTeX, no seas foro...}$ [/tex]

Aries Género:Masculino Perro OfflineGalería Personal de Sebastian SantisiVer perfil de usuarioEnviar mensaje privadoVisitar sitio web del usuario
M1thrand1r
Nivel 4


Edad: 31
Registrado: 08 Abr 2013
Mensajes: 92

Carrera: Electrónica
russia.gif
MensajePublicado: Mar Dic 03, 2013 8:12 pm  Asunto:  (Sin Asunto) Responder citandoFin de la PáginaVolver arriba

Sebastian Santisi escribió:
Si N es la longitud de aux, es fgets(aux, N, stdin);
fgets() siempre guarda el '\0'.


N viene de #DEFINE N 100 nunca llego a usar 99 caracteres con el nombre.

Me lo deberia guardar igual haciendo N-1...creo. Recien probe hacer la lectura hasta llegar a '\n' en lugar de '\0', y ahi me impimio el nombre y apellido completos seguidos de basura y una carita feliz.


Virgo Género:Masculino Mono OfflineGalería Personal de M1thrand1rVer perfil de usuarioEnviar mensaje privado
Sebastian Santisi
Administrador Técnico


Edad: 42
Registrado: 23 Ago 2005
Mensajes: 17451


argentina.gif
MensajePublicado: Mar Dic 03, 2013 9:19 pm  Asunto:  (Sin Asunto) Responder citandoFin de la PáginaVolver arriba

Me parece que tenés un tema conceptual con el '\0'.

El '\0' no se lee, no se ingresa, no es parte de la entrada/salida.

El '\0' es un mecanismo de C para delimitar cadenas. Una cadena es un arreglo de caracteres que finaliza con un '\0'.

Ergo, fgets() devuelve cadenas, si devuelve cadenas tienen el '\0' porque si no no serían cadenas. Del mismo modo, si vos querés volcar cadenas de texto en un archivo binario tenés que de alguna manera incluír esa información que te permita reconstruir lo que tenías en memoria. Sea como sea que hagas la conversión de memoria a archivo, cuando lo volvés a levantar a memoria si no guardaste el '\0' como parte del volcado, tenés que volver a agregarlo (fijate en mi primer post).

El problema lo estás teniendo en cómo volcás / levantás de vuelta los datos. Fijate en los snippets que puse en mi primer post.

_________________
Image[tex] ${. \ \ \ \ \ \ \ \ \ .}$ [/tex][tex] ${\Large Usá \LaTeX, no seas foro...}$ [/tex]

Aries Género:Masculino Perro OfflineGalería Personal de Sebastian SantisiVer perfil de usuarioEnviar mensaje privadoVisitar sitio web del usuario
M1thrand1r
Nivel 4


Edad: 31
Registrado: 08 Abr 2013
Mensajes: 92

Carrera: Electrónica
russia.gif
MensajePublicado: Mar Dic 03, 2013 9:56 pm  Asunto:  (Sin Asunto) Responder citandoFin de la PáginaVolver arriba

Sebastian Santisi escribió:
Me parece que tenés un tema conceptual con el '\0'.

El '\0' no se lee, no se ingresa, no es parte de la entrada/salida.

El '\0' es un mecanismo de C para delimitar cadenas. Una cadena es un arreglo de caracteres que finaliza con un '\0'.

Ergo, fgets() devuelve cadenas, si devuelve cadenas tienen el '\0' porque si no no serían cadenas. Del mismo modo, si vos querés volcar cadenas de texto en un archivo binario tenés que de alguna manera incluír esa información que te permita reconstruir lo que tenías en memoria. Sea como sea que hagas la conversión de memoria a archivo, cuando lo volvés a levantar a memoria si no guardaste el '\0' como parte del volcado, tenés que volver a agregarlo (fijate en mi primer post).

El problema lo estás teniendo en cómo volcás / levantás de vuelta los datos. Fijate en los snippets que puse en mi primer post.



Sisi, probe de la forma que pusiste y funciona perfecto. Pero parte de la consigna que me dieron es que no podia modificar el formato del archivo binario. Es nombre-apellido-dni-...-etc... Agregando un numero antes de cada string estaria modificando la consigna... Por eso queria leer hasta \0.


Virgo Género:Masculino Mono OfflineGalería Personal de M1thrand1rVer perfil de usuarioEnviar mensaje privado
Hache
Nivel 8



Registrado: 13 May 2010
Mensajes: 574

Carrera: Informática
argentina.gif
MensajePublicado: Mar Dic 03, 2013 10:05 pm  Asunto:  (Sin Asunto) Responder citandoFin de la PáginaVolver arriba

Y.... la longitud sería parte del campo nombre si querés.
Eso o haces campos de texto de longitud fija.

_________________
Nosotros... Chat FIUBA!

   OfflineGalería Personal de HacheVer perfil de usuarioEnviar mensaje privadoVisitar sitio web del usuario
M1thrand1r
Nivel 4


Edad: 31
Registrado: 08 Abr 2013
Mensajes: 92

Carrera: Electrónica
russia.gif
MensajePublicado: Mar Dic 03, 2013 10:14 pm  Asunto:  (Sin Asunto) Responder citandoFin de la PáginaVolver arriba

Hache escribió:
Y.... la longitud sería parte del campo nombre si querés.
Eso o haces campos de texto de longitud fija.


Lo de la longitud fija lo tengo q descartar porque los strings son si o si dinamicos.

Mande un mail para ver si se puede modificar el formato del archivo agregandole la cantidad.


Virgo Género:Masculino Mono OfflineGalería Personal de M1thrand1rVer perfil de usuarioEnviar mensaje privado
Hache
Nivel 8



Registrado: 13 May 2010
Mensajes: 574

Carrera: Informática
argentina.gif
MensajePublicado: Mar Dic 03, 2013 10:18 pm  Asunto:  (Sin Asunto) Responder citandoFin de la PáginaVolver arriba

Es que tampoco es estrictamente necesario agregar un campo con el número.
Podes guardar el string con el \0 al final (como ya se dijo)

_________________
Nosotros... Chat FIUBA!

   OfflineGalería Personal de HacheVer perfil de usuarioEnviar mensaje privadoVisitar sitio web del usuario
Sebastian Santisi
Administrador Técnico


Edad: 42
Registrado: 23 Ago 2005
Mensajes: 17451


argentina.gif
MensajePublicado: Mar Dic 03, 2013 11:13 pm  Asunto:  (Sin Asunto) Responder citandoFin de la PáginaVolver arriba

Es más hinchapelotas, pero es válido:

fwrite(s, sizeof(char), strlen(s) + 1, f);

for(i = 0; fread(s + i, sizeof(char), 1, f) && s[i]; i++);

_________________
Image[tex] ${. \ \ \ \ \ \ \ \ \ .}$ [/tex][tex] ${\Large Usá \LaTeX, no seas foro...}$ [/tex]

Aries Género:Masculino Perro OfflineGalería Personal de Sebastian SantisiVer perfil de usuarioEnviar mensaje privadoVisitar sitio web del usuario
Mostrar mensajes de anteriores:      
Responder al tema Ver tema anteriorEnviar por mail a un amigo.Mostrar una Lista de los Usuarios que vieron este TemaGuardar este Tema como un archivoPrintable versionEntrá para ver tus mensajes privadosVer tema siguiente

Ver tema siguiente
Ver tema anterior
Podés publicar nuevos temas en este foro
No podés responder a temas en este foro
No podés editar tus mensajes en este foro
No podés borrar tus mensajes en este foro
No podés votar en encuestas en este foro
No Podéspostear archivos en este foro
No Podés bajar archivos de este foro


Todas las horas son ART, ARST (GMT - 3, GMT - 2 Horas)
Protected by CBACK CrackerTracker
365 Attacks blocked.

Powered by phpBB2 Plus, phpBB Styles and Kostenloses Forum based on phpBB © 2001/6 phpBB Group :: FI Theme :: Mods y Créditos

Foros-FIUBA está hosteado en Neolo.com Cloud Hosting

[ Tiempo: 0.7132s ][ Pedidos: 20 (0.4046s) ]