Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Odczyt z pliku binarnego obiektów klasy ze składowymi std::string

Ostatnio zmodyfikowano 2015-10-24 16:08
Autor Wiadomość
carlosmay
Temat założony przez niniejszego użytkownika
[C++] Odczyt z pliku binarnego obiektów klasy ze składowymi std::string
» 2015-10-24 11:47:37
Program dla obiektów struktury działa prawidłowo, natomiast dla obiektów klasy zgłasza wyjątek.

C/C++
#include <iostream>
#include <fstream>
#include <conio.h>
#include <string>
#include <iomanip>
using namespace std;

struct Stoo {
    int st_lp;
    string st_name;
};

class Foo {
    string m_name;
    double m_weight;
public:
    Foo()
        : m_name( "" )
         , m_weight( 0 )
    { }
    Foo( const string & s, double wt )
        : m_name( s )
         , m_weight( wt )
    { }
    Foo( const Foo & f )
        : m_name( f.m_name )
         , m_weight( f.m_weight )
    { };
    ~Foo() { };
    friend ostream & operator <<( ostream & os, Foo & f ) {
        return os << setw( 15 ) << left << f.m_name << setw( 10 ) << fixed << left
        << setprecision( 2 ) << f.m_weight << endl;
    }
};

int main()
{
    Stoo st[ 2 ] = {
        { 1, "kolo" },
        { 2, "jozef" }
    };
   
    Foo foo[ 2 ] = {
        { "Earth", 1.00 },
        { "Jupiter", 317.83 }
    };
   
    fstream fout, fin;
    fout.open( "Users.dat", ios::out | ios::binary );
    if( fout.is_open() ) {
        fout.write(( char * ) & st, sizeof( st ) );
    }
    else {
        cerr << "Open file: error!" << endl;
        _getch();
        return EXIT_FAILURE;
    }
    fout.close();
   
    fout.open( "Planets2.dat", ios::out | ios::binary );
    if( fout.is_open() ) {
        fout.write(( char * ) & foo, sizeof( foo ) );
    }
    else {
        cerr << "Open file: error!" << endl;
        _getch();
        return EXIT_FAILURE;
    }
    fout.close();
   
    fin.open( "Users.dat", ios::in | ios::binary );
    if( fin.is_open() ) {
        Stoo temp[ 2 ];
        for( int i = 0; i < 2; i++ ) {
            fin.read(( char * ) & temp[ i ], sizeof( temp[ i ] ) );
            cout << temp[ i ].st_lp << " " << temp[ i ].st_name << endl;
        }
    }
    else {
        cerr << "Open file: error!" << endl;
        _getch();
        return EXIT_FAILURE;
    }
    fin.close();
   
    fin.open( "Planets2.dat", ios::in | ios::binary );
    if( fin.is_open() ) {
        Foo ftemp[ 2 ];
       
        for( int i = 0; i < 2; i++ ) {
            fin.read(( char * ) & ftemp, sizeof( ftemp ) );
            cout << ftemp[ i ];
        }
    }
    else {
        cerr << "Open file: error!" << endl;
        _getch();
        return EXIT_FAILURE;
    }
    fin.close();
   
    _getch();
    return EXIT_SUCCESS;
}
 
Program wypisuje na ekran dane ze struktury i klasy prawidłowo
1 kolo
2 jozef
Earth          1.00
Jupiter        317.83
 
i przy kończeniu programu zgłasza wyjątek
Zgłoszono wyjątek w lokalizacji 0x000B8CA0 w ConsoleApplication1.exe: 0xC0000005:
Naruszenie zasad dostępu podczas zapisywania w lokalizacji 0xDDDDDDDD.
 
Dlaczego tylko dla klasy zgłasza wyjątek?

Czy można całe obiekty klasy ze składowymi string zapisywać do pliku?
Jeśli tak to jak?
Czy jednak trzeba pisać przeciązenie '>>' do odczytu danych z pliku?
P-139093
Monika90
» 2015-10-24 12:01:11
Nie można tak zapisywać, a tym bardziej odczytywać obiektów std::string i nie ma znaczenia czy są w klasie czy w strukturze, bo struktura to też klasa.
P-139094
pekfos
» 2015-10-24 12:20:20
Temat tak powtarzający się i nudny, że doczekał się FAQ w formie artykułu..
Zapis binarny
to nawet proste, dodam sobie jeszcze stringa.. *wybuch atomowy*. Już nawet nie będę próbować liczyć, ile tematów na forum do tego można sprowadzić
P-139096
carlosmay
Temat założony przez niniejszego użytkownika
» 2015-10-24 16:08:05
C/C++
#include <iostream>
#include <fstream>
#include <conio.h>
#include <string>
#include <iomanip>
using namespace std;

class Foo {
    int m_position;
    string m_name;
    float m_weight;
public:
    Foo()
        : m_name( "" )
         , m_weight( 0 )
         , m_position( 0 )
    { }
    Foo( const string & nm, float wt, int pos )
        : m_name( nm )
         , m_weight( wt )
         , m_position( pos )
    { }
    Foo( const Foo & f )
        : m_name( f.m_name )
         , m_weight( f.m_weight )
         , m_position( f.m_position )
    { }
    ~Foo() { }
    friend ostream & operator <<( ostream & os, const Foo & f ) {
        return os << setw( 3 ) << left << f.m_position
        << setw( 15 ) << left << f.m_name
        << setw( 10 ) << right << fixed << setprecision( 3 ) << f.m_weight << endl;
    }
    void save();
    void load();
};

int main()
{
    Foo f1( "Earth", 1, 3 );
    cout << f1;
    f1.save();
    Foo f2;
    f2.load();
    cout << f2;
   
    _getch();
    return EXIT_SUCCESS;
}

void Foo::save() {
    fstream fout( "Planets.dat", ios::binary | ios::out /*| ios::app*/ );
    if( !fout.is_open() ) return;
   
    fout.write(( char * ) & m_position, sizeof( int ) );
    fout.write( m_name.c_str(), m_name.size() + 1 );
    fout.write(( char * ) & m_weight, sizeof( float ) );
}

void Foo::load() {
    fstream fin( "Planets.dat", ios::in | ios::binary );
    if( !fin.is_open() ) return;
   
    fin.read(( char * ) & m_position, sizeof( int ) );
    getline( fin, m_name, '\0' );
    fin.read(( char * ) & m_weight, sizeof( float ) );
}
Teraz działa.

Program dla obiektów struktury działa prawidłowo
 jednak nie działał prawidłowo.

Temat tak powtarzający się i nudny, że doczekał się FAQ w formie artykułu.
 dla kogoś z dużym doświadczeniem pewnie tak.
Googlowałem temat, przeczytałem kilka z tego serwisu, ale nie było jednoznacznej odpowiedzi, a na ten link akurat nie trafiłem.

Dzięki :)
P-139106
« 1 »
  Strona 1 z 1