テキストデータに名前、スコアを書き込む方法

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

テキストデータに名前、スコアを書き込む方法

#1

投稿記事 by あんちはんぐ » 14年前

こんちわ、
今学祭向け(2010/11/4~)のクイズゲームを作っており、
そのランキングの実装がうまくいかず頓挫しています。
DXライブラリを使用しているのですが、ライブラリではファイルの読み込みはサポートされているのですが、
書き込みはサポートされておらず、ある程度検索しつつ見よう見まねで取り組んでみたものの、
ランキングを保存するテキストがうまく更新できません。
fopen、fwriteの使い方をおそらく間違っていると思うのですが、正しい使い方をご教示願います

ランキングのテキストデータの一部です
サンプルネーム0
10000
サンプルネーム1
9000
サンプルネーム2
8000
サンプルネーム3
7000
サンプルネーム4
6000
サンプルネーム5
5000

次にソースコードの一部です
/*
DXライブラリでファイルの読み込みは出来るので、
プレイ前のランキングをテキストから読み込んで、変数に入れています
具体的には、
char RankName[20] にランキングに入っているプレイした人の名前(iは順位)
int  RankScore にランキングには言っているプレイした人のスコア(iは順位)

また、今回プレイした人の情報も事前に変数に格納しています
char PlayName[20] に現在プレイしてる人の名前
double Score_Num に現在プレイしてる人のスコア(int型にキャストして表示、記録予定)
int  RankNum に現在プレイしてる人の順位(ランキングを読み込むことは出来るので、順位を出すところまでは実装しています)
*/

//ランキングテキストに記録
FILE *ranktext;
char s[256];
sprintf_s(s, 256 , "Rank%d.txt", mode_p );
if((ranktext = fopen( s , "w" )) == NULL ){
    fprintf(stderr, "ランクテキストオープンエラー\n");
}
int line = FileLine( Ranking_text[mode_p] );//ランキングテキストの行数を返す関数です
    for(int i=0;i< line ; i++){
        char score[21];
        char Name[21];
        if(i < RankNum){//順位がi未満なら、元のデータのスコア、名前を記述
            sprintf_s(Name , 21 , "%s\0" , RankName);
            fwrite( Name , sizeof(char) , 21, ranktext);
            sprintf_s(score,21,"\n%d",RankScore);
            fwrite(score  , sizeof(char) , 21 , ranktext);
        }else if(RankNum == i){//順位がiと同じなら、現在プレイしてる人の名前とスコアを記述してから、元のデータのスコアをその下に書き込み
            sprintf_s(Name , 21 , "%s\0" , PlayName);
            fwrite( Name , sizeof(char) , 21 , ranktext );
            sprintf_s(score,21,"\n%d",(int)Score_Num);
            fwrite( score , sizeof(char) , 21 , ranktext );
            sprintf_s(Name , 21 , "%s\0" , RankName);
            fwrite( Name , sizeof(char), 21 , ranktext );
            sprintf_s(score,21,"\n%d",RankScore);
            fwrite( score, sizeof(char) , 21 , ranktext );
        }else{//順位がi以上なら、元のデータのスコア、名前を記述
            sprintf_s(Name , 21 , "%s\0" , RankName);
            fwrite( RankName , sizeof(char), 21 , ranktext );
            sprintf_s(score,21,"\n%d",RankScore);
            fwrite( score , sizeof(char) , 21 , ranktext );
        }
    }
fclose(ranktext);

求めている処理は、ランキングのテキストデータが以下のようになることです
サンプルネーム0
10000
サンプルネーム1
9000
サンプルネーム2
8000
サンプルネーム3
7000
プレイした人1
6500
サンプルネーム4
6000
サンプルネーム5
5000

なお、現在のソースコードの状態でビルドして起動すると以下のようになります
サンプルネーム0
10000

出来ればランキングは実装したいのでよろしくお願いします。

環境
Windows7 64bit  
VisualStudio2010
ライブラリ:DXライブラリ

さかまき

Re:テキストデータに名前、スコアを書き込む方法

#2

投稿記事 by さかまき » 14年前

スコアも名前も21バイトすべて書き出していますが
意図してすべてを書き出ししていますか?

あんちはんぐ

Re:テキストデータに名前、スコアを書き込む方法

#3

投稿記事 by あんちはんぐ » 14年前

21バイトなのは、格納している名前やスコアの後に、\0や\nを入れるために1バイト余分に出しているのですが、
そもそも\0や\nを入れるのが正しいのかどうか、わかっていません…
はじめは入れずに処理していたのですが、
記録後のテキストデータが書き込めていなかったので、
上記のものに変えたのですがうまくいかず、
質問に至った次第です

さかまき

Re:テキストデータに名前、スコアを書き込む方法

#4

投稿記事 by さかまき » 14年前

「サンプルネーム0」「10000」と出力したいのですよね?
それぞれ21バイトですか? プログラムでは21バイト書き出していませんか?

みけCAT

Re:テキストデータに名前、スコアを書き込む方法

#5

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

素直にfprintfを使ったらどうですか?

あんちはんぐ

Re:テキストデータに名前、スコアを書き込む方法

#6

投稿記事 by あんちはんぐ » 14年前

>さかまきさん
ごめんなさいfwriteの使い方などがわからず、検索してなんとなくこんな感じかなと打ってみてうまくいかなかったため、
ここで質問しました。
fwriteでの入力したい引数は、必ずその長さにあったものにならなければいけないということでしょうか
どうもfwriteの引数のそれぞれの意味を良く分かっていないので、良ければご教示下さい

>みけCATさん
ネットで検索してなんとなくfwriteを使うのかな、という程度の認識で使っていましたので、
fprintfも調べて今から作ってみます

みけCAT

Re:テキストデータに名前、スコアを書き込む方法

#7

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

苦しんで覚えるC言語(苦C)で勉強するといいと思います。
「苦C」で検索してみてください。

あんちはんぐ

Re:テキストデータに名前、スコアを書き込む方法

#8

投稿記事 by あんちはんぐ » 14年前

>みけCATさん
不勉強での質問スミマセンでした。
苦Cも調べる際には読んではいたのですが、fprintfだけじゃなく、
SEEK位置とかが良く分かっておらず(実際はあまり気にする必要は無かった?)、
いろいろゴチャゴチャ調べていたら
fwriteを見つけてそれで書き始めてしまった次第です。

確かにfprintfを使うと実装できました。 ありがとうございます。
fwrite関数はバイト単位でもっと厳密な処理?を行うときに用いるものなのでしょうか。
…イマイチよくわかりませんが、fprintfは文字情報として書き込むにはベストな関数なのかなと理解しました。(sprintfなども用いる必要が無いので)

書き込み後のテキストが2行しか出力されていなかったのは、
ランキングの行を調べて出力する関数に不備があり、
ループがうまく出来ていなかったのが原因でした。

需要あるかどうかわかりませんが、以下、訂正後のソースコードです
FILE *ranktext;
            char s[256];
            sprintf_s(s, 256 , "Rank%d.txt", mode_p );
            if((ranktext = fopen( s , "w" )) == NULL ){
                fprintf(stderr, "ランクテキストオープンエラー\n");
            }
            int line;
            line = FileLine( Ranking_text[mode_p] );    //行数は、プレイヤー名+スコアの2行ずつの構成なので、ループするときは/2する
            for(int i=0;i< line/2 ; i++){
                if(i < RankNum -1){                //プレイヤーの順位が来るまで
                    //既存のランキングを書き込む
                    fprintf_s(ranktext,"%s\n" , RankName);
                    fprintf_s(ranktext,"%d\n" , RankScore);
                    if( i == line/2 -1 ){        //プレイヤーの順位が最下位だったなら、最終行に改行をつけない
                        fprintf_s(ranktext,"%s\n" , PlayName);
                        fprintf_s(ranktext,"%d" , (int)Score_Num);
                    }
                }else if(RankNum -1 == i){        //プレイヤーの順位がきたとき
                    //プレイヤーの情報を書き込む
                    fprintf_s(ranktext,"%s\n" , PlayName);
                    fprintf_s(ranktext,"%d\n" , (int)Score_Num);
                    //プレイヤーの次の順位を書き込む
                    //ただし、プレイヤーの次の順位が最下位なら、最終行に改行をつけない
                    if(i != line/2 -1){            
                        fprintf_s(ranktext,"%s\n" , RankName);
                        fprintf_s(ranktext,"%d\n" , RankScore);                    
                    }else{                        
                        fprintf_s(ranktext , "%s\n" , RankName);
                        fprintf_s(ranktext , "%d" , RankScore);
                    }
                }else if(i != line/2 -1){        //プレイヤーの順位が過ぎたとき
                    //既存のランキングを書き込む
                    //ただし、それが最終行なら、改行をつけない
                    fprintf_s(ranktext,"%s\n" , RankName);
                    fprintf_s(ranktext,"%d\n" , RankScore);
                }else{
                    fprintf_s(ranktext , "%s\n" , RankName);
                    fprintf_s(ranktext , "%d" , RankScore);
                }

            }
            fclose(ranktext);
ご回答下さったさかまきさん、みけCATさんありがとうございました。

みけCAT

Re:テキストデータに名前、スコアを書き込む方法

#9

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

fprintfは主にテキストデータを書き込む時に使います。
fwriteは主にバイナリデータを書き込む時に使います。
この場合、テキストで保存したいということなので、fprintfを使うのがいいと思います。

閉鎖

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