ファイルの入出力

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
fa

ファイルの入出力

#1

投稿記事 by fa » 9年前

VisualStudioでDXライブラリを使用してちょっとしたマップエディタの作成を試みている者です。
描画まではなんとか完成したのですがファイルの入出力で躓いています。
vector(型は自分で定義した構造体Layer)に放り込まれたマップのデータをdatファイルに保存して後で読み込める機能を付けようと色々やってみました。
ですがファイル関係のものをプログラムをするのも初めてで、そもそもまともにプログラミングをしたことがないのでここ数日そこで詰んでいます。
以下ソースコードから、関係ある箇所の抜粋です。

コード:

/*構造体定義*/
typedef struct{
	int nLayer0;
	int nLayer1;
} Layer;

/*クラスのメンバ*/
std::vector<Layer> maLayer;
char sFile[64], stFile[64];

/*コンストラクタ内(別クラスにて画像を分割して配列に)*/
mTile = new Image("Graphic/mapchip0.bmp", 48, 48);
mTile2 = new Image("Graphic/mapchip1.bmp", 48, 48);

/*読み込み部分(char* sFile,int mSizeX,mSizeYは入力で取得)*/
for (auto i = 0; i != mSizeX * mSizeY; ++i) {maLayer.push_back({ 0,0 });}
FILE *hFile;
hFile = fopen(sFile,"rb");
fread(&maLayer, sizeof(std::vector<Layer>),maLayer.size(), hFile);
fclose(hFile);

/*描画部分(int mLocah,mLocawは画面スクロール用の変数。値は正常です)*/
for (auto i = 0; i != WIN_HEIGHT / 48; ++i) {
	for (auto j = 0; j != WIN_WIDTH / 2 / 48; ++j) {
	mTile->draw((j + mLocaw) * 48, (i + mLocah) * 48, maLayer[(i + mLocah) * mSizeX + j + mLocaw].nLayer0);
	mTile2->draw((j + mLocaw) * 48, (i + mLocah) * 48, maLayer[(i + mLocah) * mSizeX + j + mLocaw].nLayer1);
	}
}

/*描画用の別クラスの関数(int* mhaGraphには画像ハンドルを格納)*/
void Image::draw(int dstX, int dstY, int bArray) const {
	DrawGraph(dstX, dstY, mhaGraph[bArray], TRUE);
}

/*保存部分(char* stFileは入力で取得)*/
FILE *htFile = fopen(stFile,"wb");
fwrite(&maLayer, sizeof(std::vector<Layer>), maLayer.size(), htFile);
fclose(htFile);

ファイルを読み込んでいざ描画というときに、画像ハンドルの配列の添え字が範囲を超えていると怒られます。
※(例外がスローされました:読み取りアクセス違反 this->mhaGraphに~)と描画用の関数のところで止まる
ということは、ちゃんとファイルの読み込みができていないか書き出しの時点でアウトなのかどちらかですよね?
デバッグでvectorの中身を覗いてみると、かなり大きい数字が並んでいたりマイナスになっていたり???だったりしていたのでやはりfreadかfwrite関数の使い方がまずいのでしょうか?

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ファイルの入出力

#2

投稿記事 by みけCAT » 9年前

fa さんが書きました:freadかfwrite関数の使い方がまずいのでしょうか?
はい、両方の使い方がまずいですね。
std::vectorはポインタを含むことが予想されるので、その中身をファイルに書き出すことは無駄と言えるでしょう。
また、maLayerはポインタ操作において1要素の配列として扱うので、maLaher.size()が2以上のとき範囲外へのアクセスで未定義動作になります。

読み書きするために渡すポインタは&maLayerではなく&maLayer[0] (先頭要素へのポインタ)、
1要素のサイズはsizeof(std::vector<Layer>)ではなくsizeof(Layer)とするといいでしょう。
さらに、freadの戻り値を見てファイルが開けたかを確認するべきです。
また、読み込み前の要素の確保はダミーデータのpush_backのかわりにresize()を使ってもいいかもしれません。
※reserve()では要素が作られないのでダメです
fa さんが書きました:ということは、ちゃんとファイルの読み込みができていないか書き出しの時点でアウトなのかどちらかですよね?
書き出しの時点でアウトということになりますね。
ファイルの中身が期待したものかどうか、バイナリエディタやodなどで確認するのもいいでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

fa

Re: ファイルの入出力

#3

投稿記事 by fa » 9年前

とても具体的で分かりやすい回答ありがとうございます。
vectorについて全然理解できていませんでした。
これでやっと先に進めそうです。

閉鎖

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