Запись / чтение структуры в файл с использованием функций, 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)
была намного лучшая идея. Я считаю, что если вы объедините два, вы найдете себя без ошибок.
Если ошибка не устранена, используйте отладчик и вставьте строку. Кроме того, я могу предоставить пример кода, который я описал, если вы пожелаете.