Datos del Tema
Creado el 28.11.08 a las 12:03
- 0 Votos
-
0
Favoritos - 2339
Visitas - 5
Mensajes
¡Tema agregado a Favoritos!
Ya tienes este tema en Favoritos
Error
¡Buen Tema!0 Votos Disponibles
¡Tu voto ha sido enviado!
Ya has votado por este tema
[Error]
No puedes votar tu propio tema
No puedes votar a usuarios baneados
No puedes votar en un tema cerrado
Temas Relacionados
| Hola! soy José Luís estoy estudiando C++, programación orientada a objetos y tengo un problema con la persistencia de archivos. Usando read y write con archivos binarios, ¿puedo leer una clase completa de una pasada? es decir, tengo la clase A, y declaro la variable: ClaseA objeto; Y me interesa guardar todo lo que tenga almacenado A en un fichero de forma binaria: fstream fentrada("archivo.dat",ios::in|ios::binary); fentrada.read(reinterpret_cast<char *>(&objeto),sizeof(ClaseA)); Esto funcionaría? es que me da unos errores y no se si son por la lectura / escritura o por el manejo de los punteros. Guardo de esta manera: fstream fsalida("archivo.dat",ios::out|ios::binary); fsalida.write(reinterpret_cast<char *>(&objeto),sizeof(ClaseA)); El contenido private de la clase A es el siguiente: int id; string name; ClaseB vectorb[MAX_ELEM_CLASEB]; int num_elem_claseb; ClaseC vectorc[MAX_ELEM_CLASEC]; int num_elem_clasec; int errcode; Es decir tengo otras dos clases creadas, y en la ClaseA tengo dos vectores de elementos, del tipo de las otras dos clases. Read y Write deberían funcionar así? o debo leer campo a campo de la clase? Muchisimas gracias de antemano.Saludos | ||
| no tengo mucha idea de C++, pero me da la sensación que estas queriendo interpretar un objeto como una string de caracteres, y copiar esta string a un archivo. Es así? Supongo que no te debería tirar error ni la lectura ni la escritura al archivo, pero creo que no te va un funcionar; me parece que el tipo string (el que usas en el campo name) es básicamente un puntero; e.d el nombre no se almacena en directamente en ClaseA (por ej siseof(ClaseA) no tiene en cuenta la longitud de la string). Después que hagas la lectura y quieras ir a leer el campo nombre vas a ir a parar a cualquier lado en memoria ya que vas a estar siguiendo la dirección que guardaste. En general este tipo de escritura/lectura en bruto solo te va a funcionar para clases que NO TENGAN internamente ninguna referencia; si la clase tiene una referencia directa o indirectamente, no funciona nunca. La persistencia de objetos en general es un tema complicado y no creo que lo vayas a solucionar así de simple. Para este caso particular creo que lo solucionas guardando ademas del objeto, el campo nombre (y cuando lees, después de leer el objeto, lees la string, y se la asocias nuevamente al campo nombre). "It is better to be beatiful than to be good. But... it is better to be good than to be ugly." (Oscar Wilde) Era jodido Oscarcito... "Why do programmers get Halloween and Christmas mixed up? Because OCT(31) = DEC(25)" "De vez en cuando la vida toma conmigo ferne' ...." (el_bot) AntiMW VBS Tools (saca los virus con notepad!!!) Última edición por el_bot: 16 de agosto de 1981 a la tardecita. Razón: nací. | ||
| ya entiendo... El resultado que me da ese código es correcto mientras tengo el programa abierto, pero si cierro el programa y lo vuelvo a abrir, al leer el campo name me sale un monton de variables del sistema y me pita el ordenador varias veces, supongo que es por lo que tu dices. Voy a probar de quitar el campo name, y comprobar que los demás campos funcionan correctamente, si me funcionan significará que tendré que leer el nombre por separado del resto de la clase, ¿es a lo que te refieres verdad? De todas formas, yo sabía que un string en C (vector de caracteres) sí era un puntero al primer carácter, pero no que un objeto string en C++ también lo era. Oye, ¿los vectores no me darán esos problemas si uso memoria automática no? De todas formas ahora lo prueba y te cuento. Muchas gracias de verdad, el mundo de la programación es complicadillo al principio, siempre vienen muy bien este tipo de ayudas Saludos | ||
| exacto, mientras el programas esta abierto la dirección de memoria que almacena el campo nombre aún es valida y contiene la misma string que tenias; cuando vuelvas a abrir el programa en ese dirección va a haber cualquier cosa. El objeto string creo que bajo c++ no toma el nombre de "puntero", pero en el fondo lo sigue siendo. En C++ una variable de tipo string le podes asignar "a" o "aaa" o "aaaaaaaa" o lo que quieras (e.d le podes asignar algo de cualquier tamaño); es obvio que la variable no almacena directamente estos datos; lo tiene que hacer indirectamente (a esto llamalo puntero, referencia, como quieras, la idea es la misma). Y sí, me referia a que el campo name lo tenes que guardar y leer por separado (en el mismo archivo si queres, pero concepualmente tenes que hacer dos escrituras y dos lecturas). Los vectores.... no lo se; lo que yo tengo entendido por memoria automatica es basicamente "la pila". El problema de los datos que estan en la pila (es decir variables locales de una función) es que uno no deberia devolver nunca un puntero o referencia a estos datos (el puntero o la referencia estaria apuntando a un dato en la pila que solo "existe" mientras la función esta ejecutando). Si vos al objeto lo guardas desde la función que lo define en una de sus variable automaticas no hay problema; pero una vez que volves de la la función no deberias ni siquiera intentar acceder a ese objeto (ya no existe). Igual, tu problema idependientemente de si los datos estan en la pila o en el heap (o monticulo como le dicen algunos) es que te deberias asegurar 1) de nunca guardar una dirección (puntero o referencia) en el archivo, ya que son solo validas durante la ejecución actual 2) guardar todos lo datos que conforman el objeto (no solo los datos almacenados directamente en el objeto si no tambien los indirectos, como el contenido de las strings). Te vuelvo a repetir que lo que estas queriendo hacer en complejo en el caso general. El concepto se llama deep copy (deep serialization, seria en tu caso, pero la idea es la misma); vos lo que hiciste antes se denomina shallow copy. Para que veas que es un tema complejo Solo los usuarios registrados pueden ver los links. ¡Registrate ahora, es gratis! ; pero si queres probar una solución general intenta usar esta libreria Solo los usuarios registrados pueden ver los links. ¡Registrate ahora, es gratis! Provee serialización de objetos, aunque me parece que no es tan simple de usar. Fijate que las metas 4 y 5 son 4 - Deep pointer save and restore. That is, save and restore of pointers saves and restores the data pointed to. (Guardado y restuauración de punteros en profundidad. Esto es, salvar y restaurar un puntero salva y restaura los datos apuntados por este) 5 - Proper restoration of pointers to shared data. (esto quiere decir que si uno tiene dos campos apuntando al mismo objeto, este objeto se va a guardar una sola vez y cuando se restaure estos dos campos van a seguir a puntando al mismo objeto) "It is better to be beatiful than to be good. But... it is better to be good than to be ugly." (Oscar Wilde) Era jodido Oscarcito... "Why do programmers get Halloween and Christmas mixed up? Because OCT(31) = DEC(25)" "De vez en cuando la vida toma conmigo ferne' ...." (el_bot) AntiMW VBS Tools (saca los virus con notepad!!!) Última edición por el_bot: 16 de agosto de 1981 a la tardecita. Razón: nací. | ||
| Muchas gracias! El problema de mi proyecto es que tenia muchos campos (dentro de la Clase B ) tipo string. Al final, en ClaseA hice un método que pasaba toda la información a un stringstream, cada campo lo separaba con un salto de linea, el resultado un string, que guarde en el fichero modo texto. Para leer los datos, usando un getline y en los sitios necesarios un get para extraer el caracter delimitador (el final de linea). De todas formas, es una pena porque me interesaba muchisimo poderlo guardar de esta manera En fin! al final toca complicarse un poco, y yo que creía que era tan facil como hacer un read >.< Muchas gracias por tu ayuda, me mirare los links a ver si saco algo más, pero el problema que tenía ya lo tengo aclarado. Saludos! | ||
| buenísimo. Igual para molestarte un poco más: tené en cuenta que las strings pueden tener internamente finales de linea y eso haría que tu programe falle, se confundiría (creo que la forma mas simple de meter un final de linea es asignar la string literal "\r\n" a un objeto string...). Creo que la forma general es almacenarlo cada campo en un formato de la forma: Logintud de campo en bytes - datos (es decir precedes cada cosa que almancenes con la longitud; cuando lees el campo primero lees la logitud, luego esa cantidad de los datos; despues pasa al proximo campo). si tenes que guardar la string "string1" y "otrastring" el en archivo te quedaria algo como ( los numeros los deberias almacenar en formato binario asi te ocupan siempre 4 bytes, o almacenarlos como texto pero debeiras separarlo de los datos con algo, un espacio por ejemplo; si no estas en el mismo problema): (4 bytes con el valor entero 7)string1(4 bytes con el valor entero 10)otrastring con el fornato con numeros en modo texto seria algo asi (separando con espacios) 7 string1 10 otrastring Lo bueno de la segunda forma es que podes leer la longitudes con un simple fscanf("%d", &long) y que podes leerlas con cualquier editor de texto. Este formato (numero de bytes seguidos de datos) es general, lo podes usar para guardar cualquier cosa (no solo strings; por ej, podes guardar mas de un objeto en archivo) y no tenes que preocuparte por encontrar separadores. "It is better to be beatiful than to be good. But... it is better to be good than to be ugly." (Oscar Wilde) Era jodido Oscarcito... "Why do programmers get Halloween and Christmas mixed up? Because OCT(31) = DEC(25)" "De vez en cuando la vida toma conmigo ferne' ...." (el_bot) AntiMW VBS Tools (saca los virus con notepad!!!) Última edición por el_bot: 16 de agosto de 1981 a la tardecita. Razón: nací. | ||
| Herramientas | Buscar en este tema |
| |


