こんにちは。
寿命の短いプログラムなら、epistemeさんのような方法が簡単で間違いがないので、よく使われます。
ただ、Test構造体を変更する場合、古いデータを捨てるか、苦労してデータ引継ぎ用プログラムを書くことになります。複数の古いバージョンをサポートするのは地獄なのであまり古いものは断念するしかないのが実態です。
それを緩和する方法として、ファイルにバージョン番号を記録し、Test構造体を変更したらバージョンを上げ、古いデータを新しいプログラムが読む時に変更を吸収するという手法があります。
そのためにはメンバ変数毎に最初から分離して読み出しておいた方が融通が効きます。
例えば、こんな感じです。(意外に面倒なのでそこまでやるのか?悩ましいですが。)
C++
1#include <iostream>
2#include <fstream>
3#include <string>
4#include <array>
5
6struct Test
7{
8 constexpr static int kVersion=1;
9 static inline int version;
10
11 std::string name;
12 int zanki;
13 int score;
14
15 Test() : name(""), zanki(0), score(0) { }
16
17 friend std::ostream& operator<<(std::ostream& os, Test const& rhs)
18 {
19 os << rhs.name << ":";
20 os << rhs.zanki << " " << rhs.score << "\n";
21 return os;
22 }
23 friend std::istream& operator>>(std::istream& is, Test& rhs)
24 {
25 std::getline(is, rhs.name, ':');
26 is >> rhs.zanki >> rhs.score;
27 is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
28 return is;
29 }
30};
31
32struct GameData
33{
34 std::array<Test, 5> player; //プレイヤー 保存対象
35 std::array<Test, 5> enemy; //敵 保存対象
36
37 GameData() { Test::version=Test::kVersion; }
38
39 friend std::ostream& operator<<(std::ostream& os, GameData const& rhs)
40 {
41 os << Test::version << "\n";
42 for(auto const& data : rhs.player) os << data;
43 for(auto const& data : rhs.enemy) os << data;
44 return os;
45 }
46 friend std::istream& operator>>(std::istream& is, GameData& rhs)
47 {
48 is >> Test::version;
49 is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
50 for(auto& data : rhs.player) is >> data;
51 for(auto& data : rhs.enemy) is >> data;
52 return is;
53 }
54};
55
56int main()
57{
58 {
59 GameData aGameData;
60 for(std::size_t i=0; i < aGameData.player.size(); ++i)
61 {
62 aGameData.player[i].name="player" + std::to_string(i);
63 aGameData.player[i].zanki=3;
64 aGameData.player[i].score=0;
65 }
66 for(std::size_t i=0; i < aGameData.enemy.size(); ++i)
67 {
68 aGameData.enemy[i].name="enemy" + std::to_string(i);
69 aGameData.enemy[i].zanki=1;
70 aGameData.enemy[i].score=100;
71 }
72
73 std::ofstream ofs("game_data.txt");
74 ofs << aGameData;
75 }
76
77 {
78 GameData aGameData;
79
80 std::ifstream ifs("game_data.txt");
81 ifs >> aGameData;
82 std::cout << aGameData;
83 }
84}
wandbox
boost::serializationは上記のような処理を簡単にかけるようになります。(メンバ変数一つひとつの保存と回復処理は意外に面倒です。)
私も似たようなライブラリを公開してます。operator<<, >>に相当する関数を書かなくて良いので更に簡単なのですが、う~~ん、最近は別件が忙しく開発が止まってて Visual C++ 2017のバージョンアップに対応できていないので今は動かないです。orz