ページ 11

ファイル操作についての御質問です。

Posted: 2008年12月14日(日) 15:25
by BEMANI
はじめまして。
趣味でプログラムをやっている者です。
ファイル操作に関してうまくいかなかったので御質問させて頂きます。

やりたいことは、コンストラクタで Score.txt という名前のファイルにスコアが書き出されていて
それを読み込み下の配列に格納するというものです。
int RScore[10];   // スコア保存用



これがコンストラクタでファイルから書き出したスコアを格納しようと試みているところで、
FileScoe がFILEポインタです。

// コンストラクタ*************************************************
for ( int i=0; i<10; i++ )
 RScore = i*100;  // ランキングデータ初期化

// ファイル読み込み
if( !(FileScore = fopen("Score.txt", "wb")) == NULL )
{
 fseek(FileScore, NULL, SEEK_SET);    // ファイルの先頭に移動
 fread(RScore, sizeof(RScore), 10, FileScore); // スコアデータ読み込み
}
// ここまで*****************************************************




書き出しは今のところデストラクタに書いています。

// デストラクタ*************************************************
// ファイルにスコアを保存
for ( int i=0; i<10; i++ )
 fprintf(FileScore, "%d,", RScore);  // ランキングスコアをファイルに出力

fclose(FileScore);

// ここまで*****************************************************

となっております、書き出したテキストには
0,100,200,・・・900,
となっており、書き出しは大丈夫なのですが、

書き出した後に
ランキングデータ初期化の場所をコメントアウトして実行すると
RScoreには初期化されていない値が格納されています。
テキストを読み込んでRScoreには 0,100・・・900が入るようにしたいのですが
どの辺りが間違っているのでしょうか。


読み込みに関して、惜しいのか全く見当はずれなのかも解らないです。
自分ではもう少しだと思ってるのですが;


開発はXP、Visual C++ 2008 ExpressEdition、言語はC/C++です。
宜しくお願いします。

Re:ファイル操作についての御質問です。

Posted: 2008年12月14日(日) 15:47
by Mist
> fopen("Score.txt", "wb")

wb : 書き込みでオープンしているから。
書き込みでオープンするとファイル内容はすべてクリアされます。
読み込むときは"rb"だよ。

Re:ファイル操作についての御質問です。

Posted: 2008年12月14日(日) 15:54
by Mist
追記

一度のfopenで読み書き両用でオープンするのであれば"r+b"ってのもあるけどあまりお勧めはしません。
コンストラクタで読み込み、デストラクタで書き込みしかしないのであれば、
・コンストラクタではリードオープンしてデータを読み込みクローズ
・デストラクタではライトオープンしてデータを書き込んでクローズ
がいいと思う。

Re:ファイル操作についての御質問です。

Posted: 2008年12月14日(日) 16:13
by Justy
 Mistさんの指摘に加えて。

 デストラクタでは fprintf()でテキストで数値を書き出していますが、
コンストラクタでは freadで構造体をバイナリとして丸ごと読みだそうとしています。

 テキストで扱うのかバイナリで扱うのかを統一しないと正しく読み込めません。

Re:御回答ありがとうございます!

Posted: 2008年12月14日(日) 18:06
by BEMANI
Mistさん・Justyさんありがとうございます。
非常に助かりました!


>>Mistさん
御指摘の通り、読み込みたいのに書き込みで開いてるはおかしかったです;;
やりたかったことは出来ました!
上のソースコードでは開けなかった場合のエラー処理などは何もなく、
関数化してなかったのでそれぞれ実装してみました。
ファイルオープン・クローズは各々関数でやるように変更しました。

r+bは初めて聞きましたが、読み書き両用なのならば使わないと思います;
そういうのもあるんだな~ということで覚えておきます。

Mistさんお力になって頂き感謝しています!
ありがとうございます!



>>Justyさん
fprintfはテキスト書き込みなるんですね・・・

変更点は、fprintfをfwriteで書き込み文字化けのような感じで出力されてきました。
それをfreedで読み込み、デバッグで調べてみたところきちんとRScoreにそれぞれ格納されました。

Justyさんの解答にも非常に助けられました!
ありがとうございます!



変更した後のソースを載せておきます。
もし、なにか変な所が御座いましたらご指摘お願い致します。


//*****************************************************************************************
// ランキングスコアをファイルに書き出す
// 引数   : なし
// 戻り値  : なし
//*****************************************************************************************

void CWriteScore(void)
{
 // ファイルを書き込みモードで開く
 FileScore = fopen("Score.txt", "wb");

 // ファイルに書き出し
 fwrite(RScore, sizeof(RScore), 10, FileScore);

 // 使用したファイルを閉じる
 fclose(FileScore);
}





//*****************************************************************************************
// ランキングスコアをファイルから読み取る
// 引数   : なし
// 戻り値  : なし
//*****************************************************************************************

void CReadScore(void)
{
 // ファイルオープン:ファイルがないなら0点を入れて初期化する
 if( (FileScore = fopen("Score.txt", "rb")) == NULL )
 {
  for ( int i=0; i<10; i++)
  RScore = i*100;  // ランキングデータ初期化

  return;
 }
 else
 {
  fseek(FileScore, NULL, SEEK_SET);  // ファイルの先頭に移動
  fread(RScore, sizeof(RScore), 10, FileScore); // スコアデータ読み込み
 }

 fclose(FileScore);  // 使用したファイルを閉じる
}




以上二つの関数に分けました。
スペースを空けるなどして見やすくしてるつもりなのですが如何でしょうか?
またここで御質問することがあった場合見にくいソースだとさすがに自分も嫌なので
もし宜しければ御意見いただけると嬉しいです。

Re:御回答ありがとうございます!

Posted: 2008年12月14日(日) 18:35
by box
>  FileScore = fopen("Score.txt", "wb");

fopenに失敗したときのことを考慮する必要があります。


>   fseek(FileScore, NULL, SEEK_SET);  // ファイルの先頭に移動

fopen直後はファイルの先頭を指しているはずです。
ここでのfseekは特にいらないと思います。書いてあっても間違いではないと思いますけれど。

Re:御回答ありがとうございます!

Posted: 2008年12月14日(日) 19:34
by BEMANI
>>boxさん
fopen に失敗した際の処理を考慮に入れておきました。
確かに抜けていました;
ありがとうございます!

fseekに関してですが、
個人的に、一番最後を指しているような感じがしたのでつけてみたのですが
必要でないみたいなので削除しました。

boxさん。
御指摘ありがとうございます。

Re:御回答ありがとうございます!

Posted: 2008年12月15日(月) 03:52
by Dixq (管理人)
全角スペースなどを使って見やすくしてくださっているようですが、
プレタグを使っていただくと、半角やタブスペースもそのまま表現出来て便利なので、
よければお使い下さい。
詳しくは規約をご覧下さいm(_ _)m

予約語をこうやって色分けするのいいですね。自動的にそういう色分けできる機能があったらいいですね・・。

Re:御回答ありがとうございます!

Posted: 2008年12月15日(月) 09:58
by Mist
> 個人的に、一番最後を指しているような感じがしたのでつけてみたのですが

開いた時点でどこを指すかはファイルの開き方によって変わります。
"w"を指定した場合は上書きになるので現在のファイル内容は破棄され、ファイルポインタは先頭を指します。
"a"を指定した場合は追記になるので現在のファイル内容は保持され、ファイルポインタは末尾を指します。
以下のページに詳しく載っていますので参考にしてください。

http://www9.plala.or.jp/sgwr-t/c/sec17.html

Re:御回答ありがとうございます!

Posted: 2008年12月15日(月) 21:42
by BEMANI
>>Dixq(管理人)さん
次回ソースコードを載せるときに preタグを使ってみたいと思います。

予約語に色が付くと確かにいいですね~。
明るい色を使ったので目が痛くなったかもしれません;

C言語の質問では無いのですが、龍神録の画像や音楽などは管理人様が作成したものなのでしょうか?
操作キャラはドット絵でしょうか?


>>Mistさん
このサイトいいですね!
とても解りやすいです~。
困ったら活用してみます><





自分も縦シューを作ろうと、少しずつ形にしていってます。
ウインドウを作成する所から始まって、DirectXの力を借り、
new delete を使って弾をリスト構造にしてみたりと、ようやく色々出来るようになりました。

ファイル読み込みが出来なかったので、本当に感謝しています。
これでスコアに関してなんとか出来そうです。
ありがとうございます!


この質問はちょっと恥ずかしいのですが、凄く素朴な疑問です。

if(条件文){
 処理;
}



if(条件文)
{
 処理;
}

この二つ、括弧を下げるのと下げないのとで何か違いってあるのでしょうか・・・
プログラムに慣れている人は括弧を下げていない事が多いので何かあるのかな~と思ったりしました。
ただ見易いかどうかだけならソレはソレでいいのですが;

Re:御回答ありがとうございます!

Posted: 2008年12月15日(月) 21:54
by box
> この二つ、括弧を下げるのと下げないのとで何か違いってあるのでしょうか・・・

コーディングの流儀の違いです。
どちらでもコンピュータにとっては同じです。
お好きな方を選べばよいです。ただ、1つのプログラムの中で
別々の流儀が混ざっているのは美しくないと思います。
美しいと感じるかたもいらっしゃるかもしれませんけれど。

Re:御回答ありがとうございます!

Posted: 2008年12月15日(月) 22:04
by BEMANI
>>boxさん
そうなのですか・・・
特に違いがないのであれば今まで通り行きたいと思います。
回答ありがとうございます!

Re:御回答ありがとうございます!

Posted: 2008年12月16日(火) 09:52
by toyo
>予約語をこうやって色分けするのいいですね。自動的にそういう色分けできる機能があったらいいですね・・。

ソースコードをHTML化するツールならあります

HTML昆布
http://www9.plala.or.jp/sgwr-t/c_sub/ConvHTML.html

C/C++ Source Converter
http://www.atmark.gr.jp/~s2000/r/rtl/CSrcConv.html