Lista de Me Gusta2
  • 1 Mensaje por eflix1
  • 1 Mensaje por eflix1

Escribiendo un objeto a un archivo en C++ con libboost

      • 9
      • mensajes
      • miembro desde
      • 05/09/12
    17/10/2012
    #1 Escribiendo un objeto a un archivo en C++ con libboost

    Buenas!. Tras investigar por internet sobre como se graba el estado de un objeto a un archivo, encontré varias soluciones, las cuales no pude implementar. La primera fue sobrecargar los operadores >> y <<, pero me daba error en la compilacion, luego encontré un método para agregar en la clase que graba lo que esta en la direccion del puntero this, pero esta función no anda del todo bien ya que cada tanto produce un segmentation fault. Finalmente encontre la biblioteca libboost, con la cual se puede hacer archivo << objeto y listo, pero me esta trayendo problemas a la hora de compilar, y no me queda claro si son problemas de sintaxis o de otra cosa.
    Aqui el código.

    Código:
    #include #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    
    
    class Triangulo
    {
    public:
      int iorden;
      double fladoa;
      double fladob;
      double fladoc;
      double farea;
      std::string tipo; 
      ~Triangulo() {};
      bool operator < (const Triangulo&) const;
      friend class boost::serialization::access;
      template
      void serialize(Archive &ar,const unsigned int version)
      {
      ar & iorden;
      ar & fladoa;
      ar & fladob;
      ar & fladoc;
      ar & farea;
      ar & tipo;
      }
    //  istream& operator>>(istream& is, Triangulo& tri);
    //  ostream& operator<<(ostream& os, const Triangulo& tri);
    /*   std::ostream& operator << (std::ostream& os)*/
      //{
      //Triangulo s;
      //return os<> (std::istream& is)*/
     //{
     //Triangulo s;
     //return is>>s.iorden>>"\t">>s.fladoa>>"\t">>s.fladob>>"\t">>s.fladoc>>"\t">>s.farea;
     /*}*/ 
    void escribe ();
    void lee ();
    
    
    };
    
    
    class Vec_trian
    {
    public: 
    std::vector vec_trian;
    friend class boost::serialization::access;
    template
    void serialize(Archive & ar,const unsigned int version)
        {
        ar & vec_trian;
        }
    void escribe ();
    void lee ();
    ~Vec_trian(){};
    };
    
    
    void Vec_trian::escribe()
    {
    ofstream ofs ("./obj.bin",ios::binary|ios_base::app);
    if (ofs.is_open())
        {
        ofs.write(reinterpret_cast (this),sizeof (*this));
        ofs.close(); 
        }
    }
    
    
    void Vec_trian::lee()
    {
    ifstream ifs ("./obj.bin");
    if (ifs.is_open())
        {
        ifs.read(reinterpret_cast (this),sizeof (*this));
        ifs.close();
        }
    
    
    }
    
    
    bool Triangulo::operator < (const Triangulo& t1) const
    {
    return (farea < t1.farea);
    }
    
    
    //struct menos_que
    //{
    //inline bool operator() (const Triangulo& t1, const Triangulo& t2)
        //{
        //return (t1.farea < t2.farea);
        //}
    //};
    
    
    //istream& Triangulo::operator>>(istream& is,Triangulo& tri)
    //{}
    //ostream& Triangulo::operator<<(ostream& os, const Triangulo& tri)
    //{}
    
    
    void ingreso_datos(double*,double*,double*);
    double calculo_area(double,double,double);
    bool equilatero(double,double,double);
    void imprimir_salida(int, std::vector);
    bool isosceles(double,double,double);
    bool escaleno(double,double,double);
    bool es_triangulo(double,double,double);
    void sort_array(std::vector *array);
    
    
    int main ()
    {
        int iNumerodeusuarios,iContador;
        double fPer;
        cout << "Numero de ternas a ingresar: ";
        cin >> iNumerodeusuarios;
        Vec_trian vector;
       // std::vector vec_trian; 
         for (iContador=0;iContador0) && iContador!=3)
        {
        cout << "Ingrese el primer lado del triangulo:\n ";
        cin >> d;
        iContador++;
        }
        iContador=0;
        while (!(e>0))
        {
        cout << "Ingrese el segundo lado del triangulo:\n ";
        cin >> e;
        }
        iContador=0;
        while (!(f>0))
        {
        cout << "Ingrese el tercer lado del triangulo:\n ";
        cin >> f;
        }
    *a=d;
    *b=e;
    *c=f;
    }
    
    
    double calculo_area(double a, double b, double c)
    {
        double r,fSper,fPrev;
        fSper=(a+b+c)/2;
        fPrev=fSper*(fSper-a)*(fSper-b)*(fSper-c);
        r=sqrt(fPrev);
        return r;
    
    
    
    
    }
    
    
    bool equilatero(double a, double b, double c)
    {
        if (a==b && b==c && a==c)
        {
        //cout << "Es un triangulo equilatero\n";
        return true;
        }
        else return false;
    }
    
    
    bool isosceles(double a, double b, double c)
    {
        if ((a==b && b!=c && a!=c) || (a==c && b!=c && b!=a) || (b==c && c!=a && b!=a))
        {
        return true;
        }
        else return false;
    }
    
    
    bool escaleno(double a, double b, double c)
    {
        if (a!=b && a!=c && b!=c)
        {
        return true;
        }
        else return false;
    }
    
    
    bool es_triangulo (double a, double b, double c)
    {
    if (a array)
    {
    
    
    
    
        for(std::vector::size_type i=0;i!=array.size();i++)
        { 
        if (equilatero(array[i].fladoa,array[i].fladob,array[i].fladoc))
            {array[i].tipo="EQUILATERO";}
        if (isosceles(array[i].fladoa,array[i].fladob,array[i].fladoc))
            {array[i].tipo="ISOSCELES";}
        if (escaleno(array[i].fladoa,array[i].fladob,array[i].fladoc))
            {array[i].tipo="ESCALENO";}
        }
        for (int i=0;i *array)
    {
    std::sort(array->begin(), array->end());
    std::reverse(array->begin(),array->end());
    }
    Como verán hay algunas cosas comentadas en el medio de los otros intentos de escribir a un archivo y despues de recuperar esos datos.
    Ahora el mensaje de error que me tira cuando quiero compilar con libboost.

    Spoiler


    Este es el compilador que estoy usando, en ubuntu de 64 bits:

    Código:
    g++ -vUsing built-in specs.
    COLLECT_GCC=g++
    COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.6.1/lto-wrapper
    Target: x86_64-linux-gnu
    Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.1-9ubuntu3' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++,go --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
    Thread model: posix
    gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3)
    En fin, la pregunta es cual es el error que estoy cometiendo en el programa, o en todo caso, ¿Conocen alguna forma de mejor escribir objetos a archivos?.
    Gracias!.
    a LUK1LL45 le gusta esto.
  1. ¿Este tema te pareció interesante? Compártelo!

    ¿No es lo que buscabas? Intenta buscar un tema similar

    6 comentarios / 336 Visitas

      • 17,262
      • mensajes
      • miembro desde
      • 09/09/05
    • Ars longa, vita brevis
    • Administrador
    18/10/2012
    #2 Re: Escribiendo un objeto a un archivo en C++ con libboost

    Lo que tenés es un error de linkeo.
    Lo que tenés que tener en cuenta es que la librería serialization de Boost debe ser linkeada además de incluída en los headers.

    Compilá tu programa así:

    g++ -o [nombre_del_ejecutable] [nombre_del_fuente] -lboost_serialization

    Lo que hace el parámetro -l de g++ (y de gcc) es incluir librerías.

    Tal como está, tu programa compila

    Salutes.

      • 9
      • mensajes
      • miembro desde
      • 05/09/12
    18/10/2012
    #3 Re: Escribiendo un objeto a un archivo en C++ con libboost

    Buenísimo Luk1ll45, ahora compila mi programa! Como siempre muchas gracias! . De todos modos voy a tener que modificar el programa porque al parecer no me admite dos objetos

    boost::archive::text_oarchive oa (osea uno para escritura y otro para lectura) en el mismo programa.
    Saludos!
      • 17,262
      • mensajes
      • miembro desde
      • 09/09/05
    • Ars longa, vita brevis
    • Administrador
    18/10/2012
    #4 Re: Escribiendo un objeto a un archivo en C++ con libboost

    Claro, pero para lectura usá boost::archive::text_iarchive.

      • 9
      • mensajes
      • miembro desde
      • 05/09/12
    18/10/2012
    #5 Re: Escribiendo un objeto a un archivo en C++ con libboost

    Si, claro, para la lectura tengo que usar el boost::archive::text_iarchive, pero fijate que si uso los dos, de entrada y salida en el mismo programa me da error de

    Código:
    terminate called after throwing an instance of 'boost::archive::archive_exception' 
    what(): invalid signature
    .
    Esto me sale si quiero leer el archivo después de grabarlo agregándole estas lineas al final de la función main().
    Código:
     Vec_trian vector2; 
       //rutina de lectura aqui
       std::ifstream ifs ("filename");
       boost::archive::text_iarchive ia(ifs);
       ia>>vector2.vec_trian;
       //fin rutina de lectura
       imprimir_salida(iNumerodeusuarios,vector2.vec_trian);
    Según este blog no pueden estar los dos objetos creados al mismo tiempo, pero no explica mucho más, asi que tengo que investigar un poquito en esto.

    Saludos!
      • 17,262
      • mensajes
      • miembro desde
      • 09/09/05
    • Ars longa, vita brevis
    • Administrador
    18/10/2012
    #6 Re: Escribiendo un objeto a un archivo en C++ con libboost

    Bueno, ese error lo salvás poniendo el código para escritura y para lectura entre llaves, con lo que definís un nuevo ámbito para las variables/objetos declarados entre esas llaves (el código que está fuera de las llaves "no ve" los objetos o variables que declares dentro de ellas). Cuando termina de ejecutarse el bloque, las variables u objetos que declaraste dentro de ellas son destruidos (y se llama al destructor de los objetos declarados). Algo así (copio pedazos de código de tu programa, así me entendés mejor):

    Código:
    //rutina de escritura aqui
    std::ofstream ofs("filename");        
    {
            boost::archive::text_oarchive oa(ofs);
            oa << vector.vec_trian;    
            // el objeto oa dura hasta aca, despues de la llave de cierre no lo tenes mas
    } 
    //fin rutina escritura
    Lo mismo para la lectura:

    Código:
    Vec_trian vector2; 
    //rutina de lectura aqui
    std::ifstream ifs ("filename");
    {
        boost::archive::text_iarchive ia(ifs);
        ia>>vector2.vec_trian;
    }   
    //fin rutina de lectura
    Con eso solucionás tu problema.
      • 9
      • mensajes
      • miembro desde
      • 05/09/12
    18/10/2012
    #7 Re: Escribiendo un objeto a un archivo en C++ con libboost

    Uh loco sos re groso!!!. Vos sabes estaba releyendo el tutorial de boost.org y recién ahi reparé que había llaves encerrando cada rutina de lectura y escritura y al toque veo tu mensaje que lo explica todo. Este ejercicio lo voy a dar por resuelto, y voy a ver cual otro ejercicio puedo encontrar por internet para hacer.
    De nuevo gracias por tu tiempo!!
    Saludos!

    a LUK1LL45 le gusta esto.