[C con Clase] Problema de escritura y lectura multiple

Davidson, Steven srd4121 en njit.edu
Lun Jul 6 18:10:48 CEST 2015


Hola Alberto,

El problema está en el parámetro que pasas a 'write()' y a 'read()'.
Escribes:

fsalida.write(reinterpret_cast<char *>(&v1[i]),sizeof(v1[i]));

Como explicas al final, la clase 'Persona' contiene tres objetos de tipo
'string'. He aquí el problema, porque copias toda la información en cada
objeto 'string'. Sin embargo, no toda la información tiene que ver con los
datos de la cadena de caracteres en sí. La clase 'string' representa una
cadena dinámica de caracteres por lo que usará punteros y memoria
dinámicamente adjudicada. Esto implica que no copias los caracteres de la
cadena sino el puntero junto con cualesquier otros datos gestores del
objeto (de la clase 'string').

La solución es obtener los datos que quieres guardar. Seguramente necesites
invocar 'write()' y 'read()' varias veces. Por ejemplo,

fsalida.write( v1[i].GetNombre().c_str(), v1[i].GetNombre().length() );
fsalida.write( v1[i].GetApellido1().c_str(), v1[i].GetApellido1().length()
);
fsalida.write( v1[i].GetApellido2().c_str(), v1[i].GetApellido2().length()
);
fsalida.write( reinterpret_cast<const char *>( &v1[i].GetEdad() ), sizeof
v1[i].GetEdad() );

Lo mismo sucede con 'read()'. Debes leer cada campo individualmente y
guardar los datos en su campo correspondiente. Sin embargo, surge otro
problema especialmente con las cadenas de caracteres. Al tratarse de un
fichero binario, la cantidad de caracteres es variable. Por lo tanto, nos
conviene guardar la cantidad de caracteres dentro del fichero. Al final,
haríamos esto:

string::size_type nLength = v1[i].GetNombre().length();
fsalida.write( reinterpret_cast<const char *>( &nLength ), sizeof nLength );
fsalida.write( v1[i].GetNombre().c_str(), nLength );

nLength = v1[i].GetApellido1().length();
fsalida.write( reinterpret_cast<const char *>( &nLength ), sizeof nLength );
fsalida.write( v1[i].GetApellido1().c_str(), nLength );

nLength = v1[i].GetApellido2().length();
fsalida.write( reinterpret_cast<const char *>( &nLength ), sizeof nLength );
fsalida.write( v1[i].GetApellido2().c_str(), nLength );

fsalida.write( reinterpret_cast<const char *>( &v1[i].GetEdad() ), sizeof
v1[i].GetEdad() );

El formato ahora es:

[CANTIDAD_NOMBRE] [NOMBRE] [CANTIDAD_APELLIDO1]
[APELLIDO1] [CANTIDAD_APELLIDO2] [APELLIDO2] [EDAD] ...

Esto ayuda la lectura, porque podemos averiguar la cantidad de caracteres
antes de leerlos y guardarlos en una cadena y así podemos hacer
preparaciones.


Espero que esto te ayude.

Steven


2015-07-06 5:06 GMT-04:00 Alberto <tuit.alberto.sinc en gmail.com>:

> Buenas tardes.
>
> De antemano, decir que uso DEV-c++ version 4.9.9.2
>
> Llevo ya un tiempo peleandome con este problema, y al verdad ya no se por
> donde van los tiros. Primero les dejo el codigo y luego escribo la duda
>
> Persona P("Alberto","Tuit","Jara",25),P2;
> vector<Persona> v1(6);
> vector<Persona> v2(6);
>
> for (int i=0;i<v1.size();i++){
>  v1[i]=P;
> }
>
>  ofstream fsalida("BBDDPersona.dat", ios::out | ios::binary);
>
> for (int i=0;i<v1.size();i++){
>          fsalida.write(reinterpret_cast<char *>(&v1[i]),sizeof(v1[i]));
>     }
> fsalida.close();
>
> ifstream fentrada("BBDDPersona.dat", ios::in | ios::binary);
> for (int i=0; i<v2.size();i++){
>
>  fentrada.read(reinterpret_cast<char *>(&v2[i]), sizeof(v2[i]));
>    }
>
> for (int i=0; i<v2.size();i++){
>    cout << v2[i].GetNombre() << endl;
>    cout << v2[i].GetApellido1() << endl;
>    cout << v2[i].GetApellido2() << endl;
>                                     cout <<v2[i].GetEdad(<<endl;
>    cout<<endl;
>    }
> fentrada.close();
>
> Teniendo la clase Persona 4 campos 3 string "nombre apellido1 y
> apellido2"  y un int "Edad" y como funciones constructores setters y
> getters.
>
> Bueno, el problema está en que el programa crashea despues de la lectura,
> no se si es por un fallo de liberación de memoria o porque.
>
> Muchas gracias por su tiempo.
> Alberto tuit
>
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.conclase.net/pipermail/cconclase_listas.conclase.net/attachments/20150706/3b9855a5/attachment.html>


Más información sobre la lista de distribución Cconclase