Ошибка при чтении объекта класса из файла - C++

210
28 июля 2018, 07:40

Долго я пытался решить проблему самостоятельно, а так же и искал ответы на форумах. Но в итоге не смог решить свою проблему.

Проблема в том, что я сохраняю свой класс в файл, и потом после перезапуска программы, когда в файле уже есть данные, то при компиляции идет логическая ошибка при чтении файла.

#include<iostream>
#include<windows.h>
#include<fstream>
#include<conio.h>
using namespace std;       
class Player{
public:
    Player(){
        age =  exp = 0;
        name = "player";
        level = 1;
        balance = 3000;
        HP = 100;
        nxtLvl = 500;
        damage = 150;
    }
    Player(int age, string name):Player(){
        this->age = age;
        this->name = name;
    }
    Player(const Player &obj){
        age = obj.age;
        name = obj.name;
        level = obj.level;
        balance = obj.balance;
        HP = obj.HP;
        nxtLvl = obj.nxtLvl;
        damage = obj.damage;
        exp = obj.exp;
    }
    string getName(){return name;}
    int getAge(){return age;}
    int getLevel(){return level;}
    int getHP(){return HP;}
    int getBalance(){return balance;}
    int getNxt(){return nxtLvl;}
    int getDamage(){return damage;}
    void printHero(){
        cout << name << " " << age << " лет.\n" << level << " lvl.\n"
        << "Бабки: " << balance << "$\nЗдоровье: " << HP << " ХП\n" << "Сила удара: максимум " << damage << "\nОпыт: " << exp << "/" <<nxtLvl << "\n";
    }
    void upLevel(){
        ++level;
        nxtLvl = nxtLvl * 2 + (nxtLvl/2);
        damage += (damage/10);
        }
    void addExp(int exp){this->exp += exp;}
    void addHealth(int health){HP += health;}
    void remHealth(int health){HP -= health;}
    void addDamage(int damage){this->damage += damage;}
private:
    int age, level, balance, HP, exp, nxtLvl, damage;
    string name;
};
void Arena();
void myHero();
void Shop();
main(){
    setlocale(LC_ALL, "rus");
    Player me;
    string path = "game_saves.txt";
    ofstream fout;
    fout.open(path, ofstream::app);
    fout.close();
    ifstream fin;
    fin.open(path);
    if(!fin.read((char*)&me, sizeof(Player))){
        cout << "Введите ваше имя:\n";
        string name;
        cin >> name;
        system("cls");
        cout << "Введите сколько вам лет:\n";
        int age;
        cin >> age;
        me = Player(age, name);
        ofstream fout;
        fout.open(path);
        fout.write((char*)&me, sizeof(Player));
        fout.close();
    }
    fin.close();
    system("cls");
     //int l; cin >> l;
    cout << "Hello " << me.getName() << "!\n";
    cout << ">Новая игра\n Продолжить игру\n";
    char c;
    int choose = 1;
    while(c != 13){
        c = _getch();
        if(c == 72){
            system("cls");
            cout << "Hello " << me.getName() << "!\n";
            cout << ">Новая игра\n Продолжить игру\n";
            choose = 1;
        }
        if(c == 80){
            system("cls");
            cout << "Hello " << me.getName() << "!\n";
            cout << " Новая игра\n>Продолжить игру\n";
            choose = 2;
        }
    }
    if(choose == 1){
        system("cls");
        cout << "Введите ваше имя:\n";
        string name;
        cin >> name;
        cout << "Введите сколько вам лет:\n";
        int age;
        cin >> age;
        ofstream fout;
        fout.open(path);
        fout.write((char*)&me, sizeof(Player));
        fout.close();
    }
    else{
        system("cls");
        cout << ">Арена\n Мой герой\n Магазин\n";
        char k='a';
        char vote = 1;
        while(k != 13){
            k = _getch();
            if(k == 72){
                system("cls");
                if(vote == 2){
                    cout << ">Арена\n Мой герой\n Магазин\n";
                    vote = 1;
                }
                if(vote == 3){
                    cout << " Арена\n>Мой герой\n Магазин\n";
                    vote = 2;
                }
            }
            if(k == 80){
                system("cls");
                if(vote == 1){
                    cout << " Арена\n>Мой герой\n Магазин\n";
                    vote = 2;
                }
                else{
                    cout << " Арена\n Мой герой\n>Магазин\n";
                    vote = 3;
                }
            }
        }
      /* if(vote == 1) Arena();
        if(vote == 2) myHero();
        if(vote == 3) Shop();*/    
    }    
}
void Arena(){    
}

Буду рад помощи. Прошу не ругаться, я начал изучать ООП и работу с файлами только позавчера.

Answer 1

Проблема в том, что у вашего класса есть переменная типа string. Она не хранит саму строку, а только указатель на строку в памяти.

Когда вы сохраняете класс этим кодом:

fout.write((char*)&me, sizeof(Player));

вы сохраняете указатель на строку в памяти, но после перезапуска программы. Этот указатель будет недействительным.

Вы должны либо поменять механизм сохранения/загрузки, либо заменить string name на char name[100] (динамическую строку на массив символов). Но работа с массивом символов отличается от работы со строкой string.

Answer 2

Почитай про сериализацию классов в С++. Можешь хранить данные не как бинарник а как Json или XML

Статья на хабре 1

Статья на хабре 2

READ ALSO
Нужно возвращать std::unique_ptr&lt;QJsonObject&gt; а я возвращаю QJsonObject, что делать?

Нужно возвращать std::unique_ptr<QJsonObject> а я возвращаю QJsonObject, что делать?

Как исправить ошибку? У меня есть функция

168
Вызов функций c++ из qml

Вызов функций c++ из qml

Подскажите что делаю не такНаписал простую функцию которую хочу вызвать в qml

212
Как запустить QTimer в QtConcurrent::run

Как запустить QTimer в QtConcurrent::run

Kак запустить запустить QTimer в QtConcurrent::run?

170
Приложение падает на вызове DeviceIoControl

Приложение падает на вызове DeviceIoControl

Необходимо получить смещение разделов жёсткого дискаЯ делаю это следующим образом:

190