Autor |
Mensaje |
M1thrand1r
Nivel 4
Edad: 31
Registrado: 08 Abr 2013
Mensajes: 92
Carrera: Electrónica
|
|
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);
}
|
|
|
|
|
|
|
|
|
Huey 7
Nivel 6
Registrado: 03 Mar 2010
Mensajes: 267
Carrera: Electrónica
|
|
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
|
|
|
|
_________________
|
|
|
|
|
M1thrand1r
Nivel 4
Edad: 31
Registrado: 08 Abr 2013
Mensajes: 92
Carrera: Electrónica
|
|
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
|
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.
|
|
|
|
|
|
|
|
|
Huey 7
Nivel 6
Registrado: 03 Mar 2010
Mensajes: 267
Carrera: Electrónica
|
|
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.
|
|
|
|
_________________
|
|
|
|
|
Sebastian Santisi
Administrador Técnico
Edad: 42
Registrado: 23 Ago 2005
Mensajes: 17451
|
|
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".)
|
|
|
|
_________________
|
|
|
|
|
M1thrand1r
Nivel 4
Edad: 31
Registrado: 08 Abr 2013
Mensajes: 92
Carrera: Electrónica
|
|
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.
|
|
|
|
|
|
|
|
|
Sebastian Santisi
Administrador Técnico
Edad: 42
Registrado: 23 Ago 2005
Mensajes: 17451
|
|
Si N es la longitud de aux, es fgets(aux, N, stdin);
fgets() siempre guarda el '\0'.
|
|
|
|
_________________
|
|
|
|
|
M1thrand1r
Nivel 4
Edad: 31
Registrado: 08 Abr 2013
Mensajes: 92
Carrera: Electrónica
|
|
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.
|
|
|
|
|
|
|
|
|
Sebastian Santisi
Administrador Técnico
Edad: 42
Registrado: 23 Ago 2005
Mensajes: 17451
|
|
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.
|
|
|
|
_________________
|
|
|
|
|
M1thrand1r
Nivel 4
Edad: 31
Registrado: 08 Abr 2013
Mensajes: 92
Carrera: Electrónica
|
|
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.
|
|
|
|
|
|
|
|
|
Hache
Nivel 8
Registrado: 13 May 2010
Mensajes: 574
Carrera: Informática
|
|
Y.... la longitud sería parte del campo nombre si querés.
Eso o haces campos de texto de longitud fija.
|
|
|
|
_________________
|
|
|
|
|
M1thrand1r
Nivel 4
Edad: 31
Registrado: 08 Abr 2013
Mensajes: 92
Carrera: Electrónica
|
|
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.
|
|
|
|
|
|
|
|
|
Hache
Nivel 8
Registrado: 13 May 2010
Mensajes: 574
Carrera: Informática
|
|
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)
|
|
|
|
_________________
|
|
|
|
|
Sebastian Santisi
Administrador Técnico
Edad: 42
Registrado: 23 Ago 2005
Mensajes: 17451
|
|
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++);
|
|
|
|
_________________
|
|
|
|
|
|
|
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 CrackerTracker365 Attacks blocked.
|