セーブデータのロード

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
レフェリア
記事: 33
登録日時: 12年前

セーブデータのロード

#1

投稿記事 by レフェリア » 12年前

クラスを使用してコンソール上でのRPG風のプログラムを作成しているのですが、
データをセーブした後、起動しなおしてデータをロードするとプログラムが終了してしまいます。
そして、ブレークポイントを設定してデバッグをすると
Game.exe の 0x5624ad7a (msvcp100d.dll) で初回の例外が発生しました: 0xC0000005: 場所 0x0058856c を読み込み中にアクセス違反が発生しました。
Game.exe の 0x5624ad7a (msvcp100d.dll) でハンドルされていない例外が発生しました: 0xC0000005: 場所 0x0058856c を読み込み中にアクセス違反が発生しました。
と出てきてどうすればいいか分かりません。
アドバイスよろしくお願いします<(_ _)>

以下メイン関数・セーブ関数・ロード関数・クラス設定

コード:

typedef struct{

	string name;
	int maxhp;
	int hp;
	int atk;
	int def;
	int exp;
	int nextexp;
	double job[3];

}save_data_t;

void savedata_load( chara& mych );
void savedata_save( chara mych );
void job_sel( chara& mych );
void battle( chara& mych );
void battle_loop( chara& mych, chara& enemy );
void enemy_select( chara& enemy );
int damage_Set( int, int );

int main()
{
	int fl = 0;
	int a = 0;
	chara mych;
	string name;

	cout << "***RPG風ゲームを開始します***\n";

	cout << "セーブデータをロードしますか?\n[1…はい/それ以外…いいえ]:";
	cin >> a;

	if( a != 1 ){
	cout << "名前を入力してください。\n";
	cin >> name;
	mych.SetNAME( name );
	job_sel( mych );
	}
	else
	{
		savedata_load( mych );
	}
	
	battle( mych );

	cout << "今回のキャラクターをセーブしますか?[1…はい/それ以外…いいえ]:";
	cin >> a;
	if( a == 1 )
		savedata_save( mych );
}

//セーブしたデータをロードする関数
void savedata_load( chara& my )
{
	errno_t error;
	FILE *fp;
	save_data_t save_data;

	error = fopen_s( &fp, "セーブデータ.dat", "rb" );

	if( error != 0 )
	{
		return ;
	}
	else{
		//ファイルからデータを読み込む
		fread( &save_data, sizeof(save_data), 1, fp );
		fclose( fp );//解放

		my.SetNAME( save_data.name );
		my.SetMAXHP( save_data.maxhp );
		my.SetHP( save_data.hp );
		my.SetATK( save_data.atk );
		my.SetDEF( save_data.def );
		my.SetEXP( save_data.exp );
		my.SetNEXTEXP( save_data.nextexp );
		my.SetJOB( save_data.job );

		cout << " 名前:" << my.GetNAME() << "\n";
		cout << " HP:" << my.GetHP() << " / " << my.GetMAXHP() << "\n";
		cout << "攻撃力:" << my.GetATK() << "\n";
		cout << "防御力:" << my.GetDEF() << "\n";
		cout << "経験値:" << my.GetEXP() << " / " << my.GetNEXTEXP() << "\n";

		cout << "ロードしました!\n\n";
	}
}

//データをセーブする関数
void savedata_save( chara my )
{
	errno_t error;
	FILE *fp;
	save_data_t save_data;

	error = fopen_s( &fp, "セーブデータ.dat", "wb" );

	save_data.name = my.GetNAME();
	save_data.maxhp = my.GetMAXHP();
	save_data.hp = my.GetHP();
	save_data.atk = my.GetATK();
	save_data.def = my.GetDEF();
	save_data.exp = my.GetEXP();
	save_data.nextexp = my.GetNEXTEXP();
	for( int i = 0; i < 3 ; i++ )
		save_data.job[i] = my.GetJob( i );

	if( error != 0 ){
		cout << "ファイルエラー\n";
		return ;
	}
	else{
		fwrite( &save_data, sizeof(save_data), 1, fp );
		fclose( fp );
		cout << "セーブが完了しました\n\n";
	}
}

/*-------以下略--------*/

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: セーブデータのロード

#2

投稿記事 by h2so5 » 12年前

どこでエラーが出ているかデバッガの呼出履歴を使って確認してください。

レフェリア
記事: 33
登録日時: 12年前

Re: セーブデータのロード

#3

投稿記事 by レフェリア » 12年前

>>h2so5さん
h2so5 さんが書きました:どこでエラーが出ているかデバッガの呼出履歴を使って確認してください。
デバッガを使ったことが無いのですが、この時にアクセス違反だと言われました。
msvcp100d.dll!std::_Container_base12::_Orphan_all() 行 201 + 0x12 バイト C++

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: セーブデータのロード

#4

投稿記事 by h2so5 » 12年前

save_data_tのメンバの string name が問題です。クラス型を直接 fwrite で書き出すことはできません。

レフェリア
記事: 33
登録日時: 12年前

Re: セーブデータのロード

#5

投稿記事 by レフェリア » 12年前

>>h2so5さん

ありがとうございます。
string 型を char 型か何かに変換してみようと思います。

レフェリア
記事: 33
登録日時: 12年前

Re: セーブデータのロード

#6

投稿記事 by レフェリア » 12年前

コード:

//セーブデータをロードする関数
void savedata_load( chara& my )
{
	errno_t error;
	FILE *fp;
	save_data_t save_data;

	error = fopen_s( &fp, "セーブデータ.dat", "rb" );

	if( error != 0 )
	{
		cout << "データを取得できませんでした。\n";
		return ;
	}
	else{
		//ファイルからデータを読み込む
		fread( &save_data, sizeof(save_data), 1, fp );
		fclose( fp );//解放

		my.SetNAME( string(save_data.name) );
		my.SetMAXHP( save_data.maxhp );
		my.SetHP( save_data.hp );
		my.SetATK( save_data.atk );
		my.SetDEF( save_data.def );
		my.SetEXP( save_data.exp );
		my.SetNEXTEXP( save_data.nextexp );
		my.SetJOB( save_data.job );

		cout << " 名前:" << my.GetNAME() << "\n";
		cout << " HP:" << my.GetHP() << " / " << my.GetMAXHP() << "\n";
		cout << "攻撃力:" << my.GetATK() << "\n";
		cout << "防御力:" << my.GetDEF() << "\n";
		cout << "経験値:" << my.GetEXP() << " / " << my.GetNEXTEXP() << "\n";

		cout << "ロードしました!\n\n";
	}
}

void savedata_save( chara my )
{
	errno_t error;
	FILE *fp;
	save_data_t save_data;

	error = fopen_s( &fp, "セーブデータ.dat", "wb" );
	//ここを追加
	//ポインタ型のchar型配列にString型のデータを格納
	char *tmp = new char[ my.GetNAME().length() + 1 ];
	strcpy( tmp , my.GetNAME().c_str() );

	//ここでtmpの内容を代入
	save_data.name = tmp;
	save_data.maxhp = my.GetMAXHP();
	save_data.hp = my.GetHP();
	save_data.atk = my.GetATK();
	save_data.def = my.GetDEF();
	save_data.exp = my.GetEXP();
	save_data.nextexp = my.GetNEXTEXP();
	for( int i = 0; i < 3 ; i++ )
		save_data.job[i] = my.GetJob( i );

	if( error != 0 ){
		cout << "ファイルエラー\n";
		return ;
	}
	else{
		fwrite( &save_data, sizeof(save_data), 1, fp );
		fclose( fp );
		cout << "セーブが完了しました\n\n";
	}
}
といった風に変更をすると
msvcr100d.dll!strlen(unsigned char * buf) 行 81 Asm
ここで同じようなエラーが出ました。
どうしたらいいでしょうか?

レフェリア
記事: 33
登録日時: 12年前

Re: セーブデータのロード

#7

投稿記事 by レフェリア » 12年前

すいません、追記です。
今回はロード時に中断され、今回はデータが入力されていません。
前回のコードの場合は関数終了後に中断がかかりました。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: セーブデータのロード

#8

投稿記事 by softya(ソフト屋) » 12年前

ポインタをセーブしたら同じですよ。
char name[256];などならOKです。
つまり、ポインタの先をセーブしないと意味がありません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

レフェリア
記事: 33
登録日時: 12年前

Re: セーブデータのロード

#9

投稿記事 by レフェリア » 12年前

>>softya(ソフト屋)さん

ありがとうございます。

string型からchar型への変換がうまくいかないのですが
どうしたらよいでしょうか?

逆のchar型からstring型への変換はできました^^;

レフェリア
記事: 33
登録日時: 12年前

Re: セーブデータのロード

#10

投稿記事 by レフェリア » 12年前

質問内容変更です<(_ _)>
char型からstd::String型への変換時に文字化けをする原因の検討はついているのですが、
それを修繕する方法がわかりません。

【原因(予測)】
1文字2バイトでのstd::String型から1文字1バイトのchar型に変更したための情報落ち。

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: セーブデータのロード

#11

投稿記事 by h2so5 » 12年前

レフェリア さんが書きました: 【原因(予測)】
1文字2バイトでのstd::String型から1文字1バイトのchar型に変更したための情報落ち。
違います。stringでもcharでも文字あたりのbyte数は同じ扱いです。

レフェリア
記事: 33
登録日時: 12年前

Re: セーブデータのロード

#12

投稿記事 by レフェリア » 12年前

>>h2so5さん

ありがとうございます!

今までchar型は1バイトだと思っていました(;ーー)

それと、自己解決しました。
返信してくださった h2so5さん、softya(ソフト屋)さん
本当にありがとうございました!

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: セーブデータのロード

#13

投稿記事 by h2so5 » 12年前

レフェリア さんが書きました: 今までchar型は1バイトだと思っていました(;ーー)
char型は1byteですよ。どんな文字が入っていてもchar型は1byteです。

閉鎖

“C言語何でも質問掲示板” へ戻る