【问题标题】:write/read struct to file using functions , Visual C++ 2008 express使用函数将结构写入/读取到文件,Visual C++ 2008 express
【发布时间】:2012-06-03 19:56:21
【问题描述】:

我使用 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 功能似乎可以工作。我没有收到任何错误(还)。当我在创建一个字符后选择保存时,我收到以下错误:Undone.exe 中 0x69197a28 处的未处理异常: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;
}

调试器输出窗口: Undone.exe 中 0x644e7a28 处的第一次机会异常:0xC0000005:访问冲突读取位置 0xffffffcc。 Undone.exe 中 0x644e7a28 处未处理的异常:0xC0000005:访问冲突读取位置 0xffffffcc。

汽车: - pc {type='Ì' 伤害=-858993460 稳定性=-858993460 } player_character & 输入 -52 'Ì' 字符 伤害-858993460 int 稳定性-858993460 int pc.type -52 'Ì' 字符 - 保存 {_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 代码在将数据放入文件时仍然无法正常工作,但它会打印到屏幕上。

【问题讨论】:

  • 您可能不想混合格式化和未格式化的输出,并且您绝对不想一次序列化一个非原始类型。您必须对每个成员进行序列化。
  • 请使用调试器,它会准确显示导致错误的行。如果您可以向我们展示导致错误的行,我们可以提供更多帮助。顺便说一句,到目前为止,在使这个问题变得如此友好方面做得很好。

标签: c++ function struct read-write visual-c++-2008-express


【解决方案1】:

您必须逐个读取和写入每个原始数据类型,并且只能使用未格式化的 I/O。示例:

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;
}

【讨论】:

  • 我不明白为什么你必须一个一个地读取和写入每个原始数据类型,一次读取和写入结构应该可以正常工作,即o.write(reinterpret_cast&lt;const char*&gt;(&amp;p), sizeof p);
  • @JesseGood:不过,这不是便携式的。
【解决方案2】:

跟进上一个答案和编辑的问题。

根据您的 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) 

是一个更好的主意。我相信,如果你将两者结合起来,你会发现自己没有错误。

如果错误仍然存​​在,请使用调试器并粘贴该行。此外,如果您愿意,我可以提供我描述的代码示例。

【讨论】:

  • 您要我发布整页代码吗?它具有结构和我用来设计角色的所有函数以及 save_game 和 continue_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

【讨论】:

    猜你喜欢
    • 2016-09-04
    • 2014-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-13
    • 1970-01-01
    • 2012-09-20
    • 1970-01-01
    相关资源
    最近更新 更多