C++ 如何在c++;使用STL

C++ 如何在c++;使用STL,c++,windows,file-io,stl,binary,C++,Windows,File Io,Stl,Binary,我刚刚了解了STL的I/o部分,更具体地说是fstream。虽然我现在可以将二进制信息和我创建的类保存到硬盘上,但我不确定如何定义信息的读取方式 我从post中看到了制作文件格式的答案: 通常,您会定义许多记录/结构,例如 BITMAPINFOHEADER,并指定它们的排列顺序、排列方式 应该嵌套,并且您可能需要编写大量索引和 查找表。这些文件由许多记录组成(可能是 嵌套),查找表,神奇的单词(表示结构开始, 结构等)和自定义格式的字符串 我想知道的是如何用 STL和C++ + 来实现这一点。

我刚刚了解了STL的I/o部分,更具体地说是fstream。虽然我现在可以将二进制信息和我创建的类保存到硬盘上,但我不确定如何定义信息的读取方式

我从post中看到了制作文件格式的答案:

通常,您会定义许多记录/结构,例如 BITMAPINFOHEADER,并指定它们的排列顺序、排列方式 应该嵌套,并且您可能需要编写大量索引和 查找表。这些文件由许多记录组成(可能是 嵌套),查找表,神奇的单词(表示结构开始, 结构等)和自定义格式的字符串

我想知道的是如何用<强> STL和C++ + <强>来实现这一点。 由于这种格式只是为了游戏的使用,我想这会容易得多。格式应:

  • 是可遍历的(我可以查看它,找到结构的开头,也许还可以检查它的名称
  • 能够在一个文件中保存多个类和数据
  • 具有可识别的节的开始和结束:例如文本文件中的空格
  • 也许有它自己的图标来代表它

<> >强> >如何在C++中执行此操作?<强> > /p> < p>确定如何构造保存文件的第一阶段是确定需要存储什么信息。 实现映射格式最好的方法之一是为每个类都有一个save解析器(有些可以从基类的save解析器派生)。因此,例如,如果您有一个从CBaseNPC派生的player类,您很可能只是从CBaseNPC派生,重写解析器,调用基类函数,并添加任何其他必要的字段,例如,如果我们有(伪代码):

那么对于您的玩家类:

void CPlayer::Save() {
     CBaseNPC::Save();
     SaveToFile( achievement_progress );
}
显然,这只是一个简单的例子,毫无疑问,您保存的解析器将有更多字段等需要处理

处理文件本身的结构时,您需要担心的主要问题是分隔符,您的主加载解析器如何识别每个字段对应的内容

我想解释这一点的最好方法是用一个例子,下面是保存文件的简单开始:

Map: {mapname}
Gametime: {gametime}

===Player===
Health: {health}
Armor: {armor}
Weapons: {wep1 (wep1Ammo), wep2 (wep2Ammo), wep3 (wep3Ammo)}
Position: {x, y, z}
Angles: {yaw, pitch, roll} // Could be quaternion instead.
AchievementProgress: {arbritraryData}
===Player===

===NPC-npc_name===
Health: {health}
Armor: {armor}
Weapons: {wep1 (wep1Ammo), wep2 (wep2Ammo), wep3 (wep3Ammo)}
Position: {x, y, z}
Angles: {yaw, pitch, roll} // Could be quaternion instead.
===NPC-npc_name===

===Entity-item_name===
Position: {x, y, z}
Angles: {yaw, pitch, roll}
Model: {modelname}
===Entity-item_name===
在这里,我们使用“==”字符串作为类参数开头的分隔符,并使用新行作为每个类中参数的分隔符

然后,一个相对简单的问题是构造解析器,使其读入地图名称并加载,然后将游戏时间设置为保存文件中指定的值

然后,它查看文件,直到找到一个“==”读取它遇到的字符串,并从字典(可能是
std::map
std::unordered_map
)中查找它,以确定要创建(或编辑)的类使用文件中的信息。一旦确定了类类型,它就可以继续从该类调用
Load()
函数,该函数将检索包含的所有信息。解析器然后查找“=={遇到的字符串}==”的下一个实例并关闭该类。然后对遇到的下一个类执行相同的过程

很抱歉,这篇文章太长了,我相信它会变得更简短,而且我可能错过了一些东西,我只是在脑海中写下了这篇文章,所以这里可能有错误的地方,但我希望它能让你找到一个可行的保存文件格式。:)


如果您对我的帖子还有任何问题或疑问,请发表评论,我会尽力及时回答。

确定如何构建保存文件的第一步是确定需要存储哪些信息。假设您有一个实体列表,每个实体都有通用信息(可能来自少数几个基类中的一个),例如位置、速度等

实现映射格式最好的方法之一是为每个类都有一个save解析器(有些可以从基类的save解析器派生)。例如,如果您有一个从CBaseNPC派生的player类,您很可能只是从CBaseNPC派生,重写解析器,调用基类函数,并添加任何其他必要的字段,例如,如果我们有(伪代码):

那么对于您的玩家类:

void CPlayer::Save() {
     CBaseNPC::Save();
     SaveToFile( achievement_progress );
}
显然,这只是一个简单的例子,毫无疑问,您保存的解析器将有更多字段等需要处理

处理文件本身的结构时,您需要担心的主要问题是分隔符,您的主加载解析器如何识别每个字段对应的内容

我想解释这一点的最好方法是用一个例子,下面是保存文件的简单开始:

Map: {mapname}
Gametime: {gametime}

===Player===
Health: {health}
Armor: {armor}
Weapons: {wep1 (wep1Ammo), wep2 (wep2Ammo), wep3 (wep3Ammo)}
Position: {x, y, z}
Angles: {yaw, pitch, roll} // Could be quaternion instead.
AchievementProgress: {arbritraryData}
===Player===

===NPC-npc_name===
Health: {health}
Armor: {armor}
Weapons: {wep1 (wep1Ammo), wep2 (wep2Ammo), wep3 (wep3Ammo)}
Position: {x, y, z}
Angles: {yaw, pitch, roll} // Could be quaternion instead.
===NPC-npc_name===

===Entity-item_name===
Position: {x, y, z}
Angles: {yaw, pitch, roll}
Model: {modelname}
===Entity-item_name===
在这里,我们使用“==”字符串作为类参数开头的分隔符,并使用新行作为每个类中参数的分隔符

然后,构造解析器是一个相对简单的问题,以便它读入映射名并加载它。然后将游戏时间设置为保存文件中指定的值

然后,它查看文件,直到找到一个“==”读取它遇到的字符串,并从字典(可能是
std::map
std::unordered_map
)中查找它,以确定要使用文件中的信息创建(或编辑)的类。一旦确定了类类型,它就可以继续从该类调用
Load()
函数,该函数将检索包含的所有信息。然后,解析器查找“=={string expected}===”的下一个实例并关闭该类。然后,它继续执行以下步骤: