ベクターがメンバにある構造体の保存について

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

ベクターがメンバにある構造体の保存について

#1

投稿記事 by バスタブマン » 10年前

バイナリファイルにfwriteで構造体データを書き込む際に
例えば

コード:


struct flameData{
int a;
};

struct data{
int b;
vector<flameData> flame; 
};

というようなベクターをメンバに持った構造体を書き込む場合、

もし

コード:


int main(){
   FILE *fp = fopen( "Data.dat", "wb" );//バイナリファイルを開く
   data d;
   flameDara f;
   flameData f2;
   f.a = 0;
   f2.a = 2;
   d.b = 0;
   d.flame.push_back(f);
   d.flame.push_back(f2);
   fwrite(&d, sizeof(data), 1, fp);

   fclose( fp );
return 0;
}

とファイルに出力したとしたら、d.flameの部分はどのように出力されるのでしょうか。
push_backされただけ全て出力されるのでしょうか?

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

Re: ベクターがメンバにある構造体の保存について

#2

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

厳密な仕様を知ることはできませんが、とりあえず実験してみればいいと思います。
実験はしましたか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: ベクターがメンバにある構造体の保存について

#3

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

正しく出力されないはずです。
vectorクラスのメンバ変数が書きだされますが、ポインタを含んでいるはずですので再現性のない形で出力されると思います。
あと読みだして再現する方法が無いです。
クラス・構造体を完全に再現できる形でファイル出力するにはシリアライズが必要です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: ベクターがメンバにある構造体の保存について

#4

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

自分の環境(gcc 4.8.1)では、

コード:

#include <cstdio>
#include <vector>

using std::vector;

struct flameData{
	int a;
};

struct data{
	int b;
	vector<flameData> flame; 
};

typedef flameData flameDara;

int main(){
	FILE *fp = fopen( "Data.dat", "wb" );//バイナリファイルを開く
	data d;
	flameDara f;
	flameData f2;
	f.a = 0;
	f2.a = 2;
	d.b = 0;
	d.flame.push_back(f);
	d.flame.push_back(f2);
	fwrite(&d, sizeof(data), 1, fp);

	fclose( fp );
	return 0;
}
というプログラムを実行すると、Data.datの中身は

コード:

   |  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 0123456789ABCDEF
---+-----------------------------------------------------------------
00 | 00 00 00 00 F8 1F 8D 00 00 20 8D 00 00 20 8D 00 ......... ... ..
のようになりました。
このことから、この実装におけるvectorの中では要素を格納するバッファへのポインタがあり、
要素そのものは格納されていないと予想できます。

【修正】
・「この実装における」という表現を追加しました
・「おそらく」→「このことから」
最後に編集したユーザー みけCAT on 2014年2月22日(土) 19:20 [ 編集 1 回目 ]
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
usao
記事: 1889
登録日時: 11年前

Re: ベクターがメンバにある構造体の保存について

#5

投稿記事 by usao » 10年前

オフトピック
それは情報として何を示したいのですか?
vectorの意味(というのか)を考えればバッファのポインタを持ってる形であろうことは普通に予測できるし,
「いやいや実装依存だからそうは言い切れない」とかいう話なら,それはそれで特定の環境での実行結果を掲載しても意味無いだろうし…?

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

Re: ベクターがメンバにある構造体の保存について

#6

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

usao さんが書きました:
オフトピック
それは情報として何を示したいのですか?
vectorの意味(というのか)を考えればバッファのポインタを持ってる形であろうことは普通に予測できるし,
「いやいや実装依存だからそうは言い切れない」とかいう話なら,それはそれで特定の環境での実行結果を掲載しても意味無いだろうし…?
「それ」が何を示すかが確定できませんが、
質問者は「バッファのポインタを持ってる形であろうこと」を予測できていないからこの質問をした、と考えられませんか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

バスタブマン

Re: ベクターがメンバにある構造体の保存について

#7

投稿記事 by バスタブマン » 10年前

ベクターを配列のようなものと勘違いしていました。
要素の中身が出力されるわけではないのですね。
確かに普通に考えれば分かるはずのことだったのになんとも恥ずかしい限りです...

この場合の保存の方法についてはまた別の方法を自分で考えてみます。

皆さんありがとうございました。

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

Re: ベクターがメンバにある構造体の保存について

#8

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

色々と注意事項がありますが、こういうのがあります。
「letsboost::serialization」
http://www.kmonos.net/alang/boost/class ... ation.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
usao
記事: 1889
登録日時: 11年前

Re: ベクターがメンバにある構造体の保存について

#9

投稿記事 by usao » 10年前

ああ,失礼しました.
読み返してわかりました.

>のようになりました。
>おそらく、vectorの中では要素を格納するバッファへのポインタがあり、要素そのものは格納されていないと予想できます。

この2行は連続していない全く別の文なのですね.
で,
>のようになりました。
までの文は,単に
>とファイルに出力したとしたら、d.flameの部分はどのように出力されるのでしょうか。
という問いに対して出力例を示した,と.

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: ベクターがメンバにある構造体の保存について

#10

投稿記事 by ISLe » 10年前

環境依存だというのならたまたまvectorがfwriteしてfreadすると復元できる実装になっている可能性を無視できるのでしょうか。
その可能性がゼロだということを証明する必要があるのではないでしょうか。

仮に可能性がゼロだということを証明できたとして、環境依存というのは単にポインタの大きさの違いとかそういうことになるのでしょうかね。

『常に可能性を考慮する』ことを補強するための例であれば良いですが、ただの一例をすべてがそうだと思わせるように示すのは完全に間違っているとわたしは思います。

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

Re: ベクターがメンバにある構造体の保存について

#11

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

ISLe さんが書きました:ただの一例をすべてがそうだと思わせるように示すのは完全に間違っているとわたしは思います。
申し訳ありません。
「この実装における」という表現を追加しました。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

dic
記事: 657
登録日時: 13年前
住所: 宮崎県
連絡を取る:

Re: ベクターがメンバにある構造体の保存について

#12

投稿記事 by dic » 10年前

すいません、ちょっと横道はずれます

boostのシリアライズを使った方がはるかに効率的で、バグがはいらないのですが
boostを使えない場合は、自前で vector の中身を出力すればうまくできました。
いろいろ変数名とかつっこみがはいりそうですが、さっさと作りました。
Visual C++ 2010 Express
Windows 7

コード:

// vectorを保存.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"

#include	<vector>
using namespace std;


struct	fileData
{
	char	hello[80];
	int		number;
};

struct	data
{
	vector<fileData>	d;
};


//	vector の中身のみ保存する
void	func( data d )
{
	FILE	*file = fopen( "hoge.txt", "wb" );
	if( file )
	{
		int	i;
		for( i=0; i<d.d.size(); i++ )
		{
			fputs( d.d.at(i).hello, file );
			fwrite( &d.d.at(i).number, 1, sizeof(int), file );
		}
		fclose( file );
	}
}


int _tmain(int argc, _TCHAR* argv[])
{
	fileData	a;
	fileData	b;

	strcpy( a.hello, "hello" );
	a.number = 100;

	strcpy( b.hello, "hello2" );
	b.number = 200;

	data	d;
	d.d.push_back( a );
	d.d.push_back( b );

	func( d );

	return 0;
}



//---------------------------------------
追加
要素数が増えたらメンテナンスがたいへんですね
やはりライブラリをお勧めします。^^;

zeek

Re: ベクターがメンバにある構造体の保存について

#13

投稿記事 by zeek » 10年前

コード:

struct data{
    int b;
    vector<flameData> flame;
};

    data d;
    d.flame.push_back(f);
    d.flame.push_back(f2);
    fwrite(&d, sizeof(data), 1, fp);
直接格納しているかどうかについて参考までに...
d.flame の型は vector<flameData>
d.flame のサイズは sizeof(vector<flameData>)
つまり d.flame にオブジェクト f や f2 を push_back してもサイズは sizeof(vector<flameData>) のままであることになる。
となると d に直接 f や f2 を入れていないと推定するのは、ごく自然な思考かと思うのです。
規格を満足した上で d に直接 f や f2 を入れる方法が存在するかどうか何て考えたこともなかった。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: ベクターがメンバにある構造体の保存について

#14

投稿記事 by ISLe » 10年前

zeek さんが書きました:となると d に直接 f や f2 を入れていないと推定するのは、ごく自然な思考かと思うのです。
ごく自然な思考だとすれば、このトピックはなぜ生まれたのでしょうか。

実装によって判断するということは、例えばウィンドウズでは文字列リテラルを書き換えられるのでウィンドウズで文字列リテラルを書き換えるのは当然という主張があれば認めるということでしょうか。
認めるなら認めるでわたしはかまわないと思いますが、すべてにおいてそうであると誤解を招くような表現は避けるべきだと考えます。

zeek

Re: ベクターがメンバにある構造体の保存について

#15

投稿記事 by zeek » 10年前

ISLe さんが書きました:ごく自然な思考だとすれば、このトピックはなぜ生まれたのでしょうか。
単にサイズから推定すればそうではないかと提示したにすぎません。
「なぜ生まれたか」と言われれば、質問者さんに聞いていただかないと私からは答えようがないです。
ISLe さんが書きました:実装によって判断するということは、例えばウィンドウズでは文字列リテラルを書き換えられるのでウィンドウズで文字列リテラルを書き換えるのは当然という主張があれば認めるということでしょうか。
実装から判断すべきなどとは考えておりませんよ。参考に留めるのが適切でしょうね。
規格なり、仕様を判断の拠り所にすべきですね。
逆に
fwrite(&d, sizeof(data), 1, fp);
で実体が書き込まれた環境があっても、先のサイズからの推定から、これが汎用性のあるコードと考えていいか疑問を待たなくてはいけませんね。
ちょっと言葉が足りなくて誤解を与えたようですね。
単に実行を促すのは良くないと思います。どう考えられるかを提示した上で実行を促すのがよいでしょうね。
なお、「 d に直接 f や f2 を」は「 d.flame に直接 f や f2 を」の書き間違いでした。m(__)m

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: ベクターがメンバにある構造体の保存について

#16

投稿記事 by ISLe » 10年前

zeek さんが書きました:単にサイズから推定すればそうではないかと提示したにすぎません。
手元の実装で実験して推定したことを、いかなる条件下においても適用できる、とおっしゃっているとわたしが読み取るのは自由ですよね。
それを禁止したり回避したりする策を講じていないのは、誤解するのは誤解するやつが悪いとの考えですか?
zeek さんが書きました:「なぜ生まれたか」と言われれば、質問者さんに聞いていただかないと私からは答えようがないです。
質問文を読む限り質問者さんはサイズを確認して推定していないようです。
仮に、「push_backしたデータは出力されないようです。その理由は出力されたサイズを確認したからです。」と質問文が続いていたら、正にその通り、確認方法も正しい、ということになるのでしょうか。
zeek さんが書きました:実装から判断すべきなどとは考えておりませんよ。参考に留めるのが適切でしょうね。
規格なり、仕様を判断の拠り所にすべきですね。
逆に
fwrite(&d, sizeof(data), 1, fp);
で実体が書き込まれた環境があっても、先のサイズからの推定から、これが汎用性のあるコードと考えていいか疑問を待たなくてはいけませんね。
ちょっと言葉が足りなくて誤解を与えたようですね。
単に実行を促すのは良くないと思います。どう考えられるかを提示した上で実行を促すのがよいでしょうね。
なお、「 d に直接 f や f2 を」は「 d.flame に直接 f や f2 を」の書き間違いでした。m(__)m
これまでにこのトピックのどこにも規格や仕様を確認しろという指摘はありませんが。
どれだけ言葉を補ってもそもそもの順序が逆なので誤解はなくなりません。
頭の中でどのように考えていても実際には、実装がこうであるから、という指摘を繰り返しているだけです。

たまたま期待通りに動いてしまったらどうして疑問を持つことができるのでしょう。
何かに依存しているというのは、たまたまうまくいくかもしれないし、たまたまうまくいかないかもしれないということです。
たまたまうまくいくことなんて100%ないとしても説明としては完全に間違っています。

「格納されているデータは自前で個別に出力しなければいけません。シリアライズライブラリを利用することもできます。」という回答の理由は「vector型のメンバを書き出すとデータが入っていない(ことが分かる)から」ではなく「読み込んで復元できる保障がないから」です。
回答は「どのように出力されるかは環境依存なので気にしてはいけません。そのように出力したデータは読み込んでも復元できないので(以下略)。」と展開されるべきだと思います。

実装例を挙げることに意味があるのなら、vectorの実装例を数多く集めたらこのトピックはもっと良くなるのでしょうか。
そんなことをしてもこのトピックにおいては無意味ですね。
たくさん集めることが無意味になるということは、それは自己満足でしかないということです。

zeek

Re: ベクターがメンバにある構造体の保存について

#17

投稿記事 by zeek » 10年前

ISLe さんは、No: 13 の書き込みが気に入らないようですね。
「ベクターがメンバーにある構造体の保存について」のトピックに対してまだ誰からも提示されていない情報を提示したに過ぎない認識です。
「実装で判断すべきかどうか」のトピックではない認識です。
「実装で判断すべきかどうか」は、回答の一部で話題になったものですが、これに対しても見解を同時に書き込まないと気が済まないのでしょうかね。
No: 13 には「実装で判断する」などと一言も書いていません。
誤解されたようですので、私の考えは提示しました。
さらに、誤解されたことを悪いとも言っていないつもりですよ。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: ベクターがメンバにある構造体の保存について

#18

投稿記事 by ISLe » 10年前

実装に触れていること自体が問題なのですからNo.13は存在自体が問題です。
No.16にそう書いたつもりですが。

zeek さんが書きました:規格を満足した上で d に直接 f や f2 を入れる方法が存在するかどうか何て考えたこともなかった。
zeek さんが書きました:逆に
fwrite(&d, sizeof(data), 1, fp);
で実体が書き込まれた環境があっても、先のサイズからの推定から、これが汎用性のあるコードと考えていいか疑問を待たなくてはいけませんね。
ちょっと言葉が足りなくて誤解を与えたようですね。
単に実行を促すのは良くないと思います。どう考えられるかを提示した上で実行を促すのがよいでしょうね。
わたしは気に入らないのではなく疑問に思っているだけです。
そもそも考える必要もないことをどうして考えるのか。
何の目的でそれを初心者に情報として与えるのか。

アバター
usao
記事: 1889
登録日時: 11年前

Re: ベクターがメンバにある構造体の保存について

#19

投稿記事 by usao » 10年前

というプログラムを実行すると、Data.datの中身は

コード:

       |  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 0123456789ABCDEF
    ---+-----------------------------------------------------------------
    00 | 00 00 00 00 F8 1F 8D 00 00 20 8D 00 00 20 8D 00 ......... ... ..
のようになりました。
このことから、この実装におけるvectorの中では要素を格納するバッファへのポインタがあり、
要素そのものは格納されていないと予想できます。
すいません,話をぶった切ってしまうのと,便乗質問みたいになってしまうのですが,
この出力結果から,「…と予想できます」になる過程というか,何でそう読み取れるのか?的なことが
わからないので,ご教授いただけないでしょうか.
オフトピック
文章が修正されたのを見ると,元の文章に対する私のNo.9の解釈は全く違ってたのですね.

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

Re: ベクターがメンバにある構造体の保存について

#20

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

usao さんが書きました:
というプログラムを実行すると、Data.datの中身は

コード:

       |  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 0123456789ABCDEF
    ---+-----------------------------------------------------------------
    00 | 00 00 00 00 F8 1F 8D 00 00 20 8D 00 00 20 8D 00 ......... ... ..
のようになりました。
このことから、この実装におけるvectorの中では要素を格納するバッファへのポインタがあり、
要素そのものは格納されていないと予想できます。
すいません,話をぶった切ってしまうのと,便乗質問みたいになってしまうのですが,
この出力結果から,「…と予想できます」になる過程というか,何でそう読み取れるのか?的なことが
わからないので,ご教授いただけないでしょうか.
出力されたデータの中にint型(この環境では4バイト)の"2"という値は含まれていないので、
「要素そのものは格納されていない」ということが予想できます。
しかし、確かに格納されている要素数のデータが見当たらないのも直感的ではないですし、
「要素を格納するバッファへのポインタがあり」という推論もおかしかったかもしれません。

また適当なことを書いてしまい、申し訳ございませんでした。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
usao
記事: 1889
登録日時: 11年前

Re: ベクターがメンバにある構造体の保存について

#21

投稿記事 by usao » 10年前

>出力されたデータの中にint型(この環境では4バイト)の"2"という値は含まれていないので、
>「要素そのものは格納されていない」ということが予想できます。

そういう意味なんですね.
(…ということが単に知りたかっただけですので.
 内容の是非がどうのというよりも,何を示されているのか?という点がうまく読み取れなかった.)

閉鎖

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