Запись / чтение структуры в файл с использованием функций, Visual C++ 2008 express

Я сделал три файла, используя Visual C++ 2008 Express для текстовой RPG-игры. Прежде чем я действительно погрузлюсь во все это, я хочу прояснить основы: новая игра, сохранение игры, продолжение игры, выход из игры. Пока что у меня есть секция создания персонажа (в данном случае найти оружие) и выход из игры. Я застрял на том, как передать статистику оружия из структуры в файл сохранения. Кажется, я передаю члены структуры без проблем и проверяю файл, чтобы найти "мусор": Ì и -858993460 вместо моих значений.

Как мне исправить ошибки save_game и continue_game? Я провел много исследований, пытаясь выяснить это, и ничто из того, что я пробовал, похоже, не поможет.

Вот важные части кода:

struct player_character
{
char type;
int damage;
int stability;
};

void save_game(player_character& pc, ofstream &save);
void continue_game(player_character& pc, ifstream &get);

int main()
{   
player_character pc;
ofstream save;
ifstream get;

//rest of main() goes here.

//pause screen
system("pause");
return 0;
}

//rest of functions go here.

void save_game(player_character &pc, ofstream &save_data) 
{
save_data.open  ("save.dat", ios::binary);
    if (save_data.is_open())
    {
    save_data << "pc.type = " << pc.type << endl;
    save_data << "pc.damage = " << pc.damage << endl;
    save_data << "pc.stability = " << pc.stability << endl;
                //doesn't work
    //save_data.write(reinterpret_cast<char*>(&pc), sizeof(pc));
    save_data.close();
    }
    else
    {
    cout << " Error. Unable to open file.";
    }
}

void continue_game(player_character &pc, ifstream &get_data) 
{
get_data.open("save.dat");
if (get_data.is_open())
    {
                //doesn't work
    //get.read(reinterpret_cast<char*>(&pc), sizeof(pc));
    get.close();
    }
    else
    {
    cout << " Error. Unable to open file.";
    }
}

Спасибо за ответ. Я пробую следующие ревизии. Функция continue_game работает. Я не получаю ошибок (пока). Когда я выбираю сохранить после создания символа, я получаю следующую ошибку: Необработанное исключение 0x69197a28 в Undone.exe: 0xC0000005: Место чтения нарушения доступа 0xffffffcc.

Google показывает это как своего рода проблему Windows.

Почему моя функция вызывает эту ошибку?

void save_game(ofstream &save, player_character const &pc) 
{
save.open  ("save.dat");
    if (save.is_open())
    {
    save.write(reinterpret_cast<char const *>(pc.type), sizeof pc.type); 
    save.write(reinterpret_cast<char const *>(pc.damage), sizeof pc.damage); 
    save.write(reinterpret_cast<char const *>(pc.stability), sizeof pc.stability); 
    save.close();
    }
    else
    {
    cout << " Error. Unable to open file.";
    }
}

int continue_game(ifstream &get) 
{
if (!get.read(reinterpret_cast<char *>(&pc.type), sizeof pc.type)) { /* error */ } 
if (!get.read(reinterpret_cast<char *>(&pc.damage), sizeof pc.damage)) { /* error */ } 
if (!get.read(reinterpret_cast<char *>(&pc.stability), sizeof pc.stability)) { /* error */ } 

return pc.type;
return pc.damage;
return pc.stability;
}

Я изменил код save_game и continue_game и включил его сюда. Я также собрал выходные данные отладчика и авто (небольшая версия авто, не все семь страниц). По-видимому, мои значения не оцениваются в save_game, поэтому continue_game не имеет с чем работать и не вызывает ошибок.

Вот код и распечатки отладчика / авто:

int save_game(ofstream &save, player_character& pc) 
{
save.open  ("save.dat", ios::binary);
if (save.is_open())
{
//the error hits here:
    save.write(reinterpret_cast<char const *>(pc.type), sizeof pc.type); 
    save.write(reinterpret_cast<char const *>(pc.damage), sizeof pc.damage); 
    save.write(reinterpret_cast<char const *>(pc.stability), sizeof pc.stability); 
    save.close();
}
else
{
    cout << " Error. Unable to open file.";
}
return pc.type;
return pc.damage;
return pc.stability;
}

int continue_game(ifstream &get, player_character& pc)
{
get.open  ("save.dat", ios::binary);
if (get.is_open())
{
    if (!get.read(reinterpret_cast<char *>(&pc.type), sizeof pc.type)) { /* error */ } 
    if (!get.read(reinterpret_cast<char *>(&pc.damage), sizeof pc.damage)) { /* error */ } 
    if (!get.read(reinterpret_cast<char *>(&pc.stability), sizeof pc.stability)) { /* error */ } 
    get.close();
}
else
{
    cout << " Error. Unable to open file.";
}
return pc.type;
return pc.damage;
return pc.stability;
}

Окно вывода отладчика: исключение первого шанса в 0x644e7a28 в Undone.exe: 0xC0000005: расположение чтения нарушения доступа 0xffffffcc. Необработанное исключение в 0x644e7a28 в Undone.exe: 0xC0000005: расположение чтения нарушения доступа 0xffffffcc.

Авто: - pc {type='Ì' урон =-858993460 стабильность =-858993460 } player_character & type -52 'Ì' повреждение чар -858993460 int стабильность -858993460 int pc.type -52 'Ì' char - save {_Filebuffer={...} } std::basic_ofstream > & + std::basic_ostream > {...} std::basic_ostream > + _Filebuffer {_Pcvt=0x00000000 _Mychar='Ì' _Wrotesome=false ...} std::basic_filebuf >


Ну, мне удалось добиться прогресса. Я обнаружил, что мне нужно поместить аргументы в мою функцию main_menu (учтите, я не говорю о функции main(), но я ее создал), чтобы они передавались в мою функцию save_game. Я также смог остановить ошибку доступа, добавив & в мою функцию записи. Итак, это:

save.write(reinterpret_cast<char const *>(&pc.type), sizeof pc.type); 
save.write(reinterpret_cast<char const *>(&pc.damage), sizeof pc.damage); 
save.write(reinterpret_cast<char const *>(&pc.stability), sizeof pc.stability); 

вместо:

save.write(reinterpret_cast<char const *>(pc.type), sizeof pc.type); 
save.write(reinterpret_cast<char const *>(pc.damage), sizeof pc.damage); 
save.write(reinterpret_cast<char const *>(pc.stability), sizeof pc.stability); 

Код savve_game все еще не работает должным образом, когда дело доходит до помещения данных в файл, но он выводит данные на экран.

3 ответа

Решение

Похоже, я понял это! Вот что я придумала: структура в массиве... и, кажется, она работает нормально.

void save_game(fstream& file, player_type& pc)
{
    file.open("save.dat");
    if (file.is_open())
        for (int i = 0; i < 1; i++)
        {
            file << pc.w_name << endl;
            file << pc.d_rate << endl;
            file << pc.s_rate << endl;
            file.close();
        }
        else
            cout << " Error. Unable to open file.";
    menu(pc);
}//end save function

void continue_game(fstream& file, player_type player[])
{
    file.open("save.dat");
    if (file.is_open())
        for (int i = 0; i < 1; i++)
        {
            file >> player[i].w_name;
            file >> player[i].d_rate;
            file >> player[i].s_rate;
            file.close();
        }                   
        else
            cout << " Error. Unable to open file.";
    for (int i = 0; i < 1; i++)
    {
        cout << "You are continuing the game with the following weapon: " << player[i].w_name << endl;
        cout << "Which has a damage rating of " << player[i].d_rate << " and a stability rating of " << player[i].s_rate << endl; 
    }
    cout << endl;
    menu(pc);
}//end continue_game

Вы должны читать и записывать каждый примитивный тип данных, один за другим, и использовать только неформатированный ввод-вывод. Пример:

void serialize(std::ostream & o, Player const & p)
{
    o.write(reinterpret_cast<char const *>(p.type), sizeof p.type);
    o.write(reinterpret_cast<char const *>(p.damage), sizeof p.damage);
    o.write(reinterpret_cast<char const *>(p.stability), sizeof p.stability);
}

Player deserialize(std::istream & i)
{
    Player p;
    char pt;
    int pd, ps;

    if (!i.read(reinterpret_cast<char *>(&pt), sizeof pt)) { /* error */ }
    if (!i.read(reinterpret_cast<char *>(&pd), sizeof pd)) { /* error */ }
    if (!i.read(reinterpret_cast<char *>(&ps), sizeof ps)) { /* error */ }

    p.type = pt; p.damage = pd; p.stability = ps;
    return p;
}

Продолжение предыдущего ответа и отредактированный вопрос.

Судя по вашей подписи continue_game,

int continue_game(ifstream &get)

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

Когда вы делаете это:

    return pc.type;
    return pc.damage;
    return pc.stability;

Функция может иметь только один тип возврата; будет возвращен только pc.type. Это не причина ошибки, а скорее недостаток дизайна, о котором вы должны знать.

Ваш первоначальный подход к continue_game, в котором вы передали соответствующую структуру в качестве параметра,

void continue_game(player_character &pc, ifstream &get_data) 

была намного лучшая идея. Я считаю, что если вы объедините два, вы найдете себя без ошибок.

Если ошибка не устранена, используйте отладчик и вставьте строку. Кроме того, я могу предоставить пример кода, который я описал, если вы пожелаете.

Другие вопросы по тегам