• ベストアンサー

iostreamの挙動について

//save.h class c_save{  ofstream ostrm;  ifstream istrm; public:  void read(int *point);  void write(int *point); }; //save.cpp void c_save::read(int *point){  istrm.open("savedata.sav",ios::in | ios::binary);  if(!istrm){   MessageBox(NULL,L"セーブデータが読み込めませんでした。\n新規セーブデータを作成します。",L"セーブデータの作成",MB_OK);   ostrm.open("savedata.sav",ios::out | ios::trunc | ios::binary);   if(!ostrm){    MessageBox(NULL,L"新規セーブデータの作成に失敗しました。",L"セーブデータの作成",MB_OK);   }   else{    *point = 0;    ostrm.write((char *)point,sizeof(int));   }   ostrm.close();  }  else{  istrm.read((char *)point,sizeof(int));  }  istrm.close(); } void c_save::write(int *point){  ostrm.open("savedata.sav",ios::out | ios::trunc | ios::binary);  if(!ostrm){   MessageBox(NULL,L"セーブデータの書き込みに失敗しました。",L"セーブデータの書き込み",MB_OK);  }  else{   ostrm.write((char *)point,sizeof(int));  }  ostrm.close(); } ゲーム用に、ポイントを記録するために上記のようなクラスを作成したのですが、read関数を呼び出し、その後write関数を呼び出し、その次にまたread関数を呼び出すと、read関数で2回ともセーブデータが読み込めませんというメッセージがでてしまいます。 一度目のread関数でsavedata.savは作成されているのにもかかわらず、二度目でも読み込めないのはなぜでしょうか? ちなみに、アプリケーションを再起動させるとsavedata.savは認識されます。

  • ahys
  • お礼率61% (8/13)

質問者が選んだベストアンサー

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「セーブデータが読み込めなかったとき」にオープンした ifstream をそのままにして同じファイルを ofstream でオープンしてるってのが気になる. ostrm をオープンする前に istrm をクローズするのが普通じゃないかな.

ahys
質問者

お礼

回答ありがとうございました。 以下のコードに直すことで、正常な動作になりました。 void c_save::read(int *point){  istrm.open("savedata.sav",ios::in | ios::binary);  if(!istrm){   istrm.close();   MessageBox(NULL,L"セーブデータが読み込めませんでした。\n新規セーブデータを作成します。",L"セーブデータの作成",MB_OK);   ostrm.open("savedata.sav",ios::out | ios::trunc | ios::binary);   if(!ostrm){    MessageBox(NULL,L"新規セーブデータの作成に失敗しました。",L"セーブデータの作成",MB_OK);   }   else{    *point = 0;    ostrm.write((char *)point,sizeof(int));    ostrm.flush();   }   ostrm.close();  }  else{   istrm.read((char *)point,sizeof(int));   istrm.close();  } } 本当にありがとうございました!

その他の回答 (1)

  • buriburi3
  • ベストアンサー率44% (353/792)
回答No.1

flushしてやれば良い、つーかflushされてないからWriteデータがデバイスに書き込まれてないんだと思いますが。

ahys
質問者

お礼

上の回答者の指摘で正常な動作になりましたので、締め切らせていただきます。

ahys
質問者

補足

回答ありがとうございます。 2か所の ostrm.write((char *)point,sizeof(int)); のコードの下に ostrm.flush(); を追加したのですが、効果がありませんでした。 実際にフォルダ内にsavedata.savがwriteのタイミングで作成されるので、書き込まれていると思うのですがどうでしょうか? また、flushを調べてみましたがあまり使い方がわからず、誤った使い方になっているかもしれません。 どうか、詳しい回答をいただけないでしょうか?

関連するQ&A

  • C キャスト方法を教えてください

    C言語の初心者なのですが、 int abc(int(*read)(void*, int, int), int size, char* data); ような関数で第1引数の値をキャストするときどうすればよいですか。   int read = (????)NULL; そもそもint(*read)(void*, int, int)ってどういう意味ですか?

  • こんにちわ。

    こんにちわ。 .sav(セーブデータ)について質問です OS=Windows7 僕は最近、レフト4デット(以下L4D2)と言うPCゲームをインストールして遊んでいます。 そしてそのゲームのセーブデータも作りました。 それからと言うものの、他のセーブデータまでL4D2のアイコンに変わり それをクリックすると、拡張子は.savなのに、L4D2が起動しますw 変だなーと思いつつ、そのセーブデータのプロパティを見てみると、 ファイルの種類:SAVファイル プログラム:left4dead     [変更] に成っていたんです、え?と思いながら変更を押してみると 推奨されたプログラムのところにL4D2だけが有ったんです。 何に変更して良いかも解らないし、もし何かに変えたとしても そのセーブデータだけが大丈夫なだけで他のセーブデータはそのままなので どうにも成らないと思うんです。 と言うより どれにすれば良いの???って感じです こう言う事って有り得るんですかね?・・・今実際有り得てますけどw どう言う操作をすればこう言う事に成るのか、また これの対処法が有るのならば 教えてください。 お願いします

  • ポインタ参照すると変数が正しく見れない

    なぜdata = &array;がNGなのかがわかりません。 NGの場合、read関数コール前後でdataのアドレスは変更されないようです。 #include <stdio.h> int array = 100; void read( int* data ){   data = &array; // NG   *data = array; // OK } int main(){   int data;   read( &data );   printf(" d : %d\n",data);   return 0; } * 再現環境を簡易化したためこのプログラム自体の有効性はありません

  • C++関数の仮引数について

    関数の引数に配列を指定したいのですが たとえば、 double* point[4]; void setPoint(double _point[]) { for(int i = 0; i < 4; i++){ point[i] = (_point + i); } } int main(void) { setPoint((double[])(1.0, 2.0, 3.0, 4.0)); } '型キャスト' : 'double' から 'double []' に変換できません。 とエラーが出てしまいます。 どのようにすればよいでしょうか?

  • 並べ替え

    次のようなプログラムを作れ。 1.数値を次々に読み込んで配列に1番目から順に格納する。 2.配列に格納されている数値を逆の順番に並べ換える (最後に読み込んだ数値が配列の1番目に入る)。 3.その配列の内容を1番目から順番に画面に出力する。読み込み、逆転、出力の部分はそれぞれ関数にすること。 という課題をやっています。下のように作ってみたんですが 上手くいかなくて・・・ 何処が悪いか教えて下さい。 #include <stdio.h> #define MAX 100 void reve(int *, int *); void read(int *, int *); void write(int *,int *); int main () { int x[MAX]; int n=0; read(&n, x); reve(&n, x); write(&n, x); return; } void read(int *n, int x[]) { while(scanf("%d", &x[n]) == 1 ) { n += 1; } return; } void reve(int *n, int x[]) { int i, j, y; for(i = 0, j = n-1; i <j; i++, j--) { y = x[j]; x[j] = x[i]; x[i] = y; } return; } void write(int *n, int x) { int i; for(i = n; i = 0; i--) { printf("x[%d] = %d\n", i, x[i]); } return; }

  • C++におけるバイナリファイルの入出力について

    VisualStudioExpress2015のC++にて、次のような記述をし、二回目に実行したところアクセス違反が発生してしましました。 内容としてはセーブデータが見つからない場合はセーブデータにクラスの情報を書き込み、セーブデータがあった場合はセーブデータからクラスの情報を読み込むというものです。 #include <stdio.h> #include <stdlib.h> #include <string> #include <map> using namespace std; class MyClass { public: MyClass(); ~MyClass(); //private: int x, y; char *str; map<int,string> mMap; }; MyClass::MyClass() { } MyClass::~MyClass() { } void write() { MyClass *myclass = new MyClass; myclass->x = 10; myclass->y = 100; myclass->str = "aaaa"; myclass->mMap[10] = "bbbb"; FILE *fp1; if (fopen_s(&fp1,"セーブデータ.dat", "wb") != 0) {//エラーが起きたらNULLを返す return; } fwrite(&myclass, sizeof(myclass), 1, fp1); // SaveData_t構造体の中身を出力 fclose(fp1);//ファイルを閉じる } void read() { MyClass *myclass2 = new MyClass; FILE *fp2; if (fopen_s(&fp2,"セーブデータ.dat", "rb") != 0) { return; } fread(&myclass2, sizeof(myclass2), 1, fp2); fclose(fp2); printf("x=%d\ny=%d\nstr=%s\nmMap[10]=%s\n", myclass2->x, myclass2->y,myclass2->str,myclass2->mMap[10].c_str()); } int main() { FILE *fp; if (fopen_s(&fp, "セーブデータ.dat", "rb") != 0) { write(); } else { read(); } system("pause"); return 0; } どこをどう記述し直したら上手く動作するのでしょうか。 これを応用して、バイナリファイルの入出力を使ってゲームのセーブデータのようなものを実現しようと考えています。 そちらの方では多くの量のデータがあるので、できるだけクラスごとバイナリファイル等に保存するようにしたいのですが、もし上記の方法が無理な場合他にどのような方法があるか教えていただきたいです。

  • Cのローカル変数でstatic以外の使い方?

    C言語の課題について教えてください [課題] 以下の関数がある。各関数の引数、変数は自由に設定していい ・int main() ・void func() ・Point *get() { /* 構造体のアドレスを返す */ } ・構造体 typedef struct { int x; int y; int h; int w; }Point; 問題 main関数から、func関数を経由して、get関数を経由し値を取得し、表示する 以下が考えたソースになりますが、これだと、 ローカル変数でstaticを使っているので、get関数が固定値ではなく、 取得のたびに値が変わるような場合には、だめだといわれました。 考えたのですがよくわからないので、どういう場合に駄目なのかと、 どのように修正すればいいのか教えてください。 #include <stdio.h> typedef struct { int x; int y; int h; int w; }Point; void func(Point **); Point *get(); int main(void){ Point *get; func(&get); printf("get.x:[%d]\n",get->x); printf("get.y:[%d]\n",get->y); printf("get.h:[%d]\n",get->h); printf("get.w:[%d]\n",get->w); return 0; } void func(Point **pw){ *pw = get(); printf("Wrapper: pw==%p\n",pw); } Point *get(void) { static Point pget; pget.x = 2; pget.y = 2; pget.h = 30; pget.w = 40; return &pget; }

  • ifstreamについて

    ifstream でファイルを読み込もうとしているのですが、上手くいきません。 ソース A.cpp #include"A.h" void Broker::read_file(ifstream in) { in >> shikin; } int main(void) { ifstream in; in.open("hoge.txt"); Broker b; b.read_file(in); b.show(); } A.h #include<fstream.h> #include<iostream.h> class Broker{ int shikin; int nensu; double nenri; int tesuryo; public: Broker() { shikin = 0; nensu = 0; nenri = 0.0; tesuryo = 0; } void read_file(ifstream in); void show() {cout << shikin << endl;} }; 以上のようなプログラムなのですが、 コンパイルすると エラー E2247 'ios::basic_ios(const ios &)' はアクセスできない(関数 ifstream::basic_ifstream(ifstream &) ) エラー E2125  コンパイラは 'copy constructor' クラスの istream を作成できない(関数 ifstream::basic_ifstream(ifstream &) ) とのエラーが出てきて実行できません。 コンパイラ C++Builder OS XP なにが原因なのかが分かりません。 本当に初心者な質問ですが、よろしくお願いします。 (何か足りない情報などがありましたら、お手数ですがその掲示板にお願いします)

  • javaのカウントアップについて

    javaのEclipseを使っています。 カウントアップ後、表示する度に、 1, 2, 3, …と表示するプログラムを作りたいです。 プログラム例を教えて下さい。 public class Test { public static void main(String[] args) { Count count = new Count(); int scount = count.read(); count.write(scount); } } class Count { int count = 1; int read() { return count++; } void write(int scount) { System.out.println(scount); } }

  • C++でのマージソートの実現方法について

    C++でのマージソートの実現方法について、以下のコードを書いたのですが、どうしてもうまくソートできませんでした。 marge関数がおかしいと思うのですが、自分で確かめてみても、どこがおかしいのか分かりませんでした。 どなたか、どうすればソートされた結果がメイン関数で表示されるようにできるのか教えていただけないでしょうか? #include <iostream> #include <vector> using namespace std; class Array { private: vector<int> array; public: void insert( int value ){ array.push_back( value ); } int getSize( ){ return (int)array.size( ); } void marge_sort( ){ marge_sort( 0, (int)array.size( ) - 1 ); } void marge_sort( int left, int right ); void marge( int left, int middle, int right ); void print( ); }; // マージソートにより配列の添字 left ~ right の部分を整列する関数 void Array::marge_sort( int left, int right ){ if( left >= right ) { return; } int middle = (left + right) / 2; //中央の添字を求める marge_sort( left, middle ); //左の要素が全てバラバラになるまで marge_sort( middle + 1 , right ); //右の要素が全てバラバラになるまで marge( left, middle, right ); //バラバラの要素をソートして併合 } // 個別にソートされた2つの配列(添字 left ~ middle と添字 middle+1 ~ right)を作業用配列を使ってマージする関数 void Array::marge( int left, int middle, int right ) { int num=right-left; int *tmp=new int[num]; int t=0,l=left,r=middle; while(l<middle&&r<right){ if(array[l]<=array[r]){ tmp[t++]=array[l++]; } else { tmp[t++]=array[r++]; } } while(l<middle){ tmp[t++]=array[l++]; } while(r<right){ tmp[t++]=array[r++]; } for(int i=0;i<num;i++){ array[left+i]=tmp[i]; } delete tmp; } // 配列の内容を表示する関数 void Array::print( ) { for ( int i = 0; i < (int)array.size( ); i++ ) { cout << array[i] << " "; } cout << endl; } int main( ) { Array a1; a1.insert( 56 ); a1.insert( 34 ); a1.insert( 57 ); a1.insert( 64 ); a1.insert( 3 ); a1.insert( 87 ); a1.insert( 85 ); a1.insert( 37 ); a1.insert( 21 ); a1.insert( 4 ); a1.insert( 68 ); a1.insert( 62 ); a1.insert( 42 ); a1.insert( 55 ); a1.insert( 63 ); a1.insert( 95 ); a1.insert( 7 ); a1.insert( 32 ); a1.insert( 78 ); a1.insert( 11 ); cout << "要素数: " << a1.getSize( ) << endl; cout << "ソート前: "; a1.print( ); a1.marge_sort(); // ここで,ソートを行う関数を呼び出す cout << "ソート後: "; a1.print( ); return 0; } // 実行結果 要素数: 20 ソート前: 56 34 57 64 3 87 85 37 21 4 68 62 42 55 63 95 7 32 78 11 ソート後: 3 4 34 37 21 42 55 56 57 62 63 7 32 64 68 78 85 87 95 11 ↑のソート後の表示が、昇順にソートされるようにしたいのです。

専門家に質問してみよう