スマートな読み込みプログラムの書き方

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Rittai_3D
記事: 525
登録日時: 7年前

スマートな読み込みプログラムの書き方

#1

投稿記事 by Rittai_3D » 6年前

こんばんわ。3Dです。今回はファイルの読み込みについて質問があります。

以前たてたトピック

コード:

void Music_Draw::Load_Script()
{
    char FileName[] = "dat/bgm/musiccmt.txt"; // ファイルの名前
    int i,num=0,n=0,line=0; // n曲目の判断やfor文関係 
    int  input[128];        // 一文字読み込むのに必要
    char inputc[128];   // 上に同じ
 
    FILE* fp = fopen( FileName , "r" ); // ファイルを開く
 
    if( fp == NULL ){ // ファイルが無い時の処理
        MSG( "No Script File !" );
        exit(1);
    }
 
    for(i=0 ; i<4 ; i++ ) // 最初の4行はコメントなので読み飛ばす
        while( fgetc( fp ) != '\n' );
 
    while( 1 ){
        for(i=0 ; i<128 ; i++ ){ // 横64文字まで読み込んで
            input[i] = inputc[i] = fgetc( fp );
 
            if( input[i] == '#' ){ // コメント記号ならば
                while( fgetc( fp ) != '\n' ); // その行の終わりまでループして
                i = -1; // カウンタを戻して
                continue;
            }
 
            if( input[i] == '\n' ){ // 改行記号なら(独自フォーマットのファイルだから改行で区切る)
                inputc[i] = '\0';   // そこまでを文字列にして
                break;
            }
 
            if( input[i] == EOF ){  // EOFなら(ここは、charで判断はしないほうが良い)
                goto EXFILE;        // ファイルクローズタグにジャンプ( でいいのかな? )
            }
        }
 
        switch( num ){ // 読み込んだファイルから構造体にコピーする
            case 0: strcpy( music[n].path   , inputc ); break; // 音楽再生の為のパス
            case 1: strcpy( music[n].name[0], inputc ); break; // 名前1 : No.~
            case 2: strcpy( music[n].name[1], inputc ); break; // 名前2 : ♪~
                // -----------------以下、コメント読み込み----------------- //
            case 3: strcpy( music[n].comme[ line ]    , inputc );break;
            case 4: strcpy( music[n].comme[ line + 1 ], inputc );break;
            case 5: strcpy( music[n].comme[ line + 2 ], inputc );break;
            case 6: strcpy( music[n].comme[ line + 3 ], inputc );break;
            case 7: strcpy( music[n].comme[ line + 4 ], inputc );break;
            case 8: strcpy( music[n].comme[ line + 5 ], inputc );break;
            case 9: strcpy( music[n].comme[ line + 6 ], inputc );break;
                // -------------------------------------------------------- //
        }
 
        num++; // num加算
 
        if( num == 10 ){ // numの値が9(1曲分のファイル読み込みが終わったら)なら
            num = 0;    // numを加算
            n++;        // nも加算
        }
    }
EXFILE: // ファイルクローズ
    fclose( fp );
}
のようなコードを書いておりました。しかし、これだとコードがごちゃごちゃして見づらいので新たにファイル読み込みプログラムを書きたいと思いました。

自分は上のようなコードしかかけないので、スマートな書き方を教えて下さい。お願いします。

[開発環境]
C言語

Windows7
VC2010

WindowsXP
VC2008
初心者です

jay
記事: 314
登録日時: 9年前
住所: 大阪市
連絡を取る:

Re: スマートな読み込みプログラムの書き方

#2

投稿記事 by jay » 6年前

コードをスマートにしたいだけなら

1、読み込む対象のデータを構造体に纏める

2、構造体のデータをバイナリファイルとしてそのまま書きだす

3、データはバイナリファイルとして読み込む
  中身は構造体として読み込まれるので、あとは構造体を格納して使うだけ

というやり方があります
まぁ、読み込む側のコードはスッキリするでしょうけど、
バイナリファイルを書きだす所は別のコード書かなきゃいけないので
成果が作業量の割に合わない気がしないでもないです
♪僕たちは まだ森の中 抜け出そう 陽のあたる場所へ

Poco
記事: 161
登録日時: 9年前

Re: スマートな読み込みプログラムの書き方

#3

投稿記事 by Poco » 6年前

コメント行にしろ、データ行にしろ1行の長さの最大値は決まっていますか?

Poco
記事: 161
登録日時: 9年前

Re: スマートな読み込みプログラムの書き方

#4

投稿記事 by Poco » 6年前

追加で質問させてください。

・ファイルのフォーマットは1行1データでしょうか?
・最初の4行は#(コメント記号)で始まるのしょうか?

beatle
記事: 1280
登録日時: 8年前
住所: 埼玉
連絡を取る:

Re: スマートな読み込みプログラムの書き方

#5

投稿記事 by beatle » 6年前

ファイルの内容に何らかの文法があるようですね。
文法があるということは、原理的にはそれを字句解析、構文解析をするということになります。
したがって、読込部分が複雑になるのは必然ですから、それほどシンプルなプログラムには成らないでしょう。(今のプログラムも構文解析してると思えばそれなりにすっきりしたコードだと思いますよ)

もっと楽ちんにしたいなら、普及している文法を使うのです。
例えばXMLやJSONにしておけば、構文解析は既成のライブラリを使えます。

Rittai_3D
記事: 525
登録日時: 7年前

Re: スマートな読み込みプログラムの書き方

#6

投稿記事 by Rittai_3D » 6年前

返信ありがとうございます。

>>jay様
jay さんが書きました:コードをスマートにしたいだけなら

1、読み込む対象のデータを構造体に纏める

2、構造体のデータをバイナリファイルとしてそのまま書きだす

3、データはバイナリファイルとして読み込む
  中身は構造体として読み込まれるので、あとは構造体を格納して使うだけ

というやり方があります
ありがとうございます。
>読み込む対象のデータを構造体に纏める
とは、

コード:

typedef struct
{
    int    nLoop;//ループ位置。この件には関係無いのでスルーして下さい。
    char* pcName[2]; //曲名2つ
    char* pcCmt[7];  //コメント7行
} Hoge_t;
とするのでしょうか?でしたら、もうすでにしております。
#既に書いたコードのコピーです。

2、3は簡単に言うとインタプリタのようにするのでしょうか?

>>Poco様
Poco さんが書きました:コメント行にしろ、データ行にしろ1行の長さの最大値は決まっていますか?
はい。一行は64字までです。
Poco さんが書きました:追加で質問させてください。

・ファイルのフォーマットは1行1データでしょうか?
・最初の4行は#(コメント記号)で始まるのしょうか?
すいません、載せるべき情報が少なくて…

ファイルのフォーマットは若干複雑で

コード:

#コメント行
bgm/◯.wav(曲のパス)
No.1 曲名1
曲名2
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
コメント7

#次の曲
のなっております。
つまり、曲のパス、曲名1、2は一行で、コメントは7行となっています。

また、空行は読み飛ばしです。その部分は実装できました。
最初の4行はコメントで始まります。
初心者です

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

Re: スマートな読み込みプログラムの書き方

#7

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

beatle さんが書きました:もっと楽ちんにしたいなら、普及している文法を使うのです。
例えばXMLやJSONにしておけば、構文解析は既成のライブラリを使えます。
個人の感想としては、XMLやJSONを読み込むライブラリの使い方を学び、
場合によってはそれらのライブラリをビルドしてリンクするよりも、
今の行単位で読み込むというような単純なファイルフォーマットにした方が実装が楽だと思います。

ただ、最初のプログラムだと、行の途中に#があった時の動作が気になります。(仕様でしょうか?)
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: スマートな読み込みプログラムの書き方

#8

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

3D_3D さんが書きました:>>jay様
jay さんが書きました:コードをスマートにしたいだけなら

1、読み込む対象のデータを構造体に纏める

2、構造体のデータをバイナリファイルとしてそのまま書きだす

3、データはバイナリファイルとして読み込む
  中身は構造体として読み込まれるので、あとは構造体を格納して使うだけ

というやり方があります
ありがとうございます。
>読み込む対象のデータを構造体に纏める
とは、

コード:

typedef struct
{
    int    nLoop;//ループ位置。この件には関係無いのでスルーして下さい。
    char* pcName[2]; //曲名2つ
    char* pcCmt[7];  //コメント7行
} Hoge_t;
とするのでしょうか?でしたら、もうすでにしております。
#既に書いたコードのコピーです。

2、3は簡単に言うとインタプリタのようにするのでしょうか?
念のため書いておきます。
提示された構造体にはポインタが含まれるため、そのままバイナリデータとしてファイルに書き出しても無効なデータになります。
注意してください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: スマートな読み込みプログラムの書き方

#9

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

とりあえずfgetsで1行ずつ読み込むようにし、使用していない/無駄な変数は消してみました。

コード:

void Music_Draw::Load_Script()
{
    char FileName[] = "dat/bgm/musiccmt.txt"; // ファイルの名前
    int num=0,n=0; // n曲目の判断やfor文関係 
    char inputc[256];   // 1行読み込むバッファ

    FILE* fp = fopen( FileName , "r" ); // ファイルを開く

    if( fp == NULL ){ // ファイルが無い時の処理
        MSG( "No Script File !" );
        exit(1);
    }

    for(i=0 ; i<4 ; i++ ) // 最初の4行はコメントなので読み飛ばす
        fgets(inputc,sizeof(inputc),fp);

    while( 1 ){
        char* lfPtr; // 改行コードの位置が入る
        if(!fgets(inputc,sizeof(inputc),fp))break; // 読み込むものがなければループを抜ける
#if 0
        if(inputc[0]=='#')continue; // 行の先頭が#の場合のみコメントとみなす
#else
        if(strchr(inputc,'#'))continue; // 行に#が含まれていればコメント行とみなす(現行仕様)
#endif
        if(lfPtr=strchr(inputc,'\n'))*lfPtr='\0'; // 改行記号があればそれを消す
        if(strlen(inputc)==0)continue; // 空行は読み飛ばす

        if(num==0) {
            strcpy( music[n].path   , inputc ); // 音楽再生の為のパス
        } else if(num<=2) {
            strcpy( music[n].name[num-1], inputc ); // 名前1/2
        } else if(num<=9) {
            strcpy( music[n].comme[num-3]    , inputc ); // コメント
        }

        num++; // num加算

        if( num == 10 ){ // numの値が9(1曲分のファイル読み込みが終わったら)なら
            num = 0;    // numを加算
            n++;        // nも加算
        }
    }
    fclose( fp ); // ファイルクローズ
}
【編集】空行を読み飛ばす処理を追加しました
最後に編集したユーザー みけCAT on 2013年11月16日(土) 11:16 [ 編集 1 回目 ]
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: スマートな読み込みプログラムの書き方

#10

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

最初のプログラムでは、1行に128バイトちょうど書かれている場合、誤動作する可能性があります。
そのようなテストケース(最大テストケース)でのテストはしていますか?
もちろん1行が64バイトまでという仕様なら大丈夫です。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
へろりくしょん
記事: 92
登録日時: 9年前
住所: 福岡

Re: スマートな読み込みプログラムの書き方

#11

投稿記事 by へろりくしょん » 6年前

コードの書き方という事でしたら、若干スパゲッティ化してますので、これを解決するのが第一の目標でしょう。
不要なカウンタが多いです。 そして原則としてカウンタを減らすのは軽く禁じ手です。

とりあえず、日本語でコードを書いてみるとすっきりします。


まず、構造化を意識します。
1関数は、1機能だと心がけてください。

読み込むファイルを関数内で、決め打ちしてますが、これは引数として渡すべき物です。
また、プログラムを殺してしまう関数はあまり好ましくありません。
戻り値を利用し、失敗時にはエラーを返すようにするべきです。
また、正否の判断は、呼び出し元に責任を負わせた方がいいです。

C言語との話ですが、変数 music は、クラスのメンバ変数でしょうか。 C言語的には、これも引数として与えた方がいいです。
あるいは、成功時には、関数内で動的に生成された music インスタンスのポインタを返し、失敗時には NULL を返すとか。


適当ですが、C言語的に書くと、こんな感じでしょうか。
コンパイルはしてません。

コード:

int loadScript(const char *fname, MUSIC *music, int max)
{
	FILE *fp;
	char buf[256], *tmp;
	int line, loadCount = 0;

	if(!(fp = fopen(fname, "r"))) return 0;

	while(!feof(fp)){
		for(line = 0; line < 10;){
			if(!fgets(buf, 256, fp)) break;	//1行読む

			if(*buf == '#' || !*buf) continue;	//空行:コメント行は読み飛ばし。
			if(tmp = strchr(buf, '#')) *tmp = '\0';		//# 以降は消す

			switch(line){
				case 0: strcpy(music[loadCount].path, buf); break;
				case 1: case 2: strcpy(music[loadCount].name[line - 1], buf); break;
				default: strcpy(music[loadCount].comme[line - 3], buf);
			}
			line++;
		}
		if(++loadCount >= max) break;
	}

    fclose(fp);

	return loadCount;	//読み込んだ件数を返す。
}

ところで、
3D_3D さんが書きました:

コード:

typedef struct
{
    int    nLoop;//ループ位置。この件には関係無いのでスルーして下さい。
    char* pcName[2]; //曲名2つ
    char* pcCmt[7];  //コメント7行
} Hoge_t;
ポインタの配列のようですが、件のコードの中に、これらのメンバを動的に確保していないようですが、よいのでしょうか。
前のスレッドを見てないから分かりませんが。

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

Re: スマートな読み込みプログラムの書き方

#12

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

あとは、エラー処理がどのくらい必要かですね。
読み込むファイルをこの処理の作者しか書かないのでしたら、エラー処理はほとんど省略でいいと思います。
逆に、読み込むファイルをユーザーが(普通の状況=チート/公式でない改造ではない状況で)書くことがあるのでしたら、
エラー処理をきちんと考えた方がいいと思います。
例えば、fgetcで読み込み、行の最大の長さを超えた部分はメモリに保存しないという処理方法が考えられます。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

jay
記事: 314
登録日時: 9年前
住所: 大阪市
連絡を取る:

Re: スマートな読み込みプログラムの書き方

#13

投稿記事 by jay » 6年前

3D_3D さんが書きました: >読み込む対象のデータを構造体に纏める
とは、

123456 typedef struct
{
int nLoop;//ループ位置。この件には関係無いのでスルーして下さい。
char* pcName[2]; //曲名2つ
char* pcCmt[7]; //コメント7行
} Hoge_t;

とするのでしょうか?でしたら、もうすでにしております。
#既に書いたコードのコピーです。
構造体に纏めるとはそういうことです
但しみけCATさんが言っているように、メンバにポインタ変数やポインタ配列があったらアウトですので
曲名やコメントは2次元配列にしておいてくださいね
(ポインタの参照先を書き出すようにすれば出来なくはないですけど、面倒なだけですからね)
3D_3D さんが書きました: 2、3は簡単に言うとインタプリタのようにするのでしょうか?
正直インタプリタと言うモノをあんまり理解できてないので、その質問には答えられませんが
もう少し具体的に書くと

ファイルを書きだす時に fopen 関数でバイナリ書き出しモードで構造体を出力する

読み込むときは fopen 関数でバイナリ読み込みモードでファイルを読み込む


というだけのことです。 あまり難しく考えず
構造体を中身のデータごとそのまま書きだして、そのまま読み込む
と考えてくださいね
オフトピック
もしかして適当なサンプルコードでも書いた方が手っ取り早かったかな?
♪僕たちは まだ森の中 抜け出そう 陽のあたる場所へ

Poco
記事: 161
登録日時: 9年前

Re: スマートな読み込みプログラムの書き方

#14

投稿記事 by Poco » 6年前

スマートな書き方に関して、殆どへろりんごさんが回答しちゃいましたが、
1点だけ。

変数名や関数名の命名規則は統一しましょう。
具体的に言えば、FileNameとその他です。
統一されてないと汚く見え、スマートにはまず見えません。

どのような命名規則でも良いですが、とにかく統一することは常に頭に入れておいてください。

jay
記事: 314
登録日時: 9年前
住所: 大阪市
連絡を取る:

Re: スマートな読み込みプログラムの書き方

#15

投稿記事 by jay » 6年前

非表示エリア
この非表示エリアを表示するには、登録し、ログインする必要があります。
♪僕たちは まだ森の中 抜け出そう 陽のあたる場所へ

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

Re: スマートな読み込みプログラムの書き方

#16

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

ごめんなさい、#があったときの挙動を勘違いしていました。
自分のコードでは「#があった行を無視する」と解釈していましたが、
もとのコードの動作は「#から改行コードまでを読み飛ばし、今の行の#の前までのデータを次の行のデータとくっつける」ですね。


ごめんなさい。こっちの解釈が誤解でした。
カウンタを戻しているので、次の行のデータは再びバッファの先頭から書き込まれるはずです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
へろりくしょん
記事: 92
登録日時: 9年前
住所: 福岡

Re: スマートな読み込みプログラムの書き方

#17

投稿記事 by へろりくしょん » 6年前

jay さんが書きました: もう少し具体的に書くと

ファイルを書きだす時に fopen 関数でバイナリ書き出しモードで構造体を出力する

読み込むときは fopen 関数でバイナリ読み込みモードでファイルを読み込む


というだけのことです。 あまり難しく考えず
構造体を中身のデータごとそのまま書きだして、そのまま読み込む
と考えてくださいね
これは、少々危険な気がしますね。
例えば、ある構造体があったとして、この構造体のサイズは処理系依存です。
一般に、構造体をそのままファイルへダンプするのはあまりよろしくありません。
ですから、結局のところ何らかの形で切り分けていく必要があると思います。

#どういうわけだか、ビットマップはこれを前提にしているような節がありますが。

また、有効なデータとしてではなく、ファイル内に注釈(#から始まる文字列)を記述できるという点で、
テキストとして読める事が前提になっているのでは。




ところで、ファイルフォーマットの仕様に触れるなら、そもそも件のフォーマットはあまりよろしくありません。
ファイル内のデータの整合性を保証する仕組みが一切備わっていませんね。

例えば、以下のような記述があった場合。

コード:

ファイルパス。
曲名1
曲名2
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
コメント7
コメント8
このコメント8が、無視するべき物なのか、次の曲のファイルパスなのか判断出来ません。
仕様上は、次の曲のファイルパスとして扱うべきのようですが。

プログラム内で、読み込んだデータの整合性を保証することが極めて困難です。

もうちょっと、フォーマットの仕様を考えなおした方がいい気がします。

Rittai_3D
記事: 525
登録日時: 7年前

Re: スマートな読み込みプログラムの書き方

#18

投稿記事 by Rittai_3D » 6年前

みなさん、返信ありがとうございます。

風邪を引いたみたいで昨日は返信が出来ませんでした。

>>beatle様
ファイルの内容に何らかの文法があるようですね。
文法があるということは、原理的にはそれを字句解析、構文解析をするということになります。
したがって、読込部分が複雑になるのは必然ですから、それほどシンプルなプログラムには成らないでしょう。
(今のプログラムも構文解析してると思えばそれなりにすっきりしたコードだと思いますよ)
ありがとうございます。自分としては、もっとすっきり書けるのではないだろうか、と考えていました。
読み込みと字句解析というかなんというか、同時にするのは如何なものかと考えましたが、自分の力ではどうすることも
できず...
もっと楽ちんにしたいなら、普及している文法を使うのです。
例えばXMLやJSONにしておけば、構文解析は既成のライブラリを使えます。
自分の考えているものはそこまで複雑な文法は使わないので、必要はないかなと考え、独自のフォーマットで
したいと思いました。

>>みけCAT様
ただ、最初のプログラムだと、行の途中に#があった時の動作が気になります。(仕様でしょうか?)
念のため書いておきます。
提示された構造体にはポインタが含まれるため、そのままバイナリデータとしてファイルに書き出しても無効なデータになります。
注意してください。
はい、仕様です。行の途中にコメントを入れる事は無いので。
また、ポインタは使用しておりません。あくまで、こんな感じですか?、と言う
サンプルを示す物ですので、現在書いているコードとは異なっております。
とりあえずfgetsで1行ずつ読み込むようにし、使用していない/無駄な変数は消してみました。
► スポイラーを表示
【編集】空行を読み飛ばす処理を追加しました
サンプルコードありがとうございます。自分の書いていたコードよりすっきりして見やすいです。
1行64バイトまでとなっておりますので仕様は変えないで行いたいと思います
最初のプログラムでは、1行に128バイトちょうど書かれている場合、誤動作する可能性があります。
そのようなテストケース(最大テストケース)でのテストはしていますか?
もちろん1行が64バイトまでという仕様なら大丈夫です。
エラー処理ですか...そうですね、ファイルが無い時だけエラーを出すような物でも良いかもしれません。
ユーザーは書く事がないのでごっそり減らします。
あとは、エラー処理がどのくらい必要かですね。
読み込むファイルをこの処理の作者しか書かないのでしたら、エラー処理はほとんど省略でいいと思います。
逆に、読み込むファイルをユーザーが(普通の状況=チート/公式でない改造ではない状況で)書くことがあるのでしたら、
エラー処理をきちんと考えた方がいいと思います。
例えば、fgetcで読み込み、行の最大の長さを超えた部分はメモリに保存しないという処理方法が考えられます。
fgetcでですか?fgetsでは無く?

>>へろりんご様
コードの書き方という事でしたら、若干スパゲッティ化してますので、これを解決するのが第一の目標でしょう。
不要なカウンタが多いです。 そして原則としてカウンタを減らすのは軽く禁じ手です。

とりあえず、日本語でコードを書いてみるとすっきりします。
日本語で書いてみる、とは
► スポイラーを表示
のようにするのですか?それとも、フローチャートの様にするのですか?
まず、構造化を意識します。
1関数は、1機能だと心がけてください。

読み込むファイルを関数内で、決め打ちしてますが、これは引数として渡すべき物です。
また、プログラムを殺してしまう関数はあまり好ましくありません。
戻り値を利用し、失敗時にはエラーを返すようにするべきです。
また、正否の判断は、呼び出し元に責任を負わせた方がいいです。
なるほど。構造化、一関数一機能を心がけてコーディングしていきます。
なかなか指摘されないと気がつかない物なんですね。
C言語との話ですが、変数 music は、クラスのメンバ変数でしょうか。 C言語的には、これも引数として与えた方がいいです。
あるいは、成功時には、関数内で動的に生成された music インスタンスのポインタを返し、失敗時には NULL を返すとか。


適当ですが、C言語的に書くと、こんな感じでしょうか。
コンパイルはしてません。
ポインタの配列のようですが、件のコードの中に、これらのメンバを動的に確保していないようですが、よいのでしょうか。
前のスレッドを見てないから分かりませんが。
musicは構造体配列です。Hoge_tの。また、Hoge_tの中にポインタがありますが本当は二次元配列です。
出来れば、Hoge_t構造体があるファイルの中だけで行いたいのですが、どうしても引数にしなければ
いけませんか?
ところで、ファイルフォーマットの仕様に触れるなら、そもそも件のフォーマットはあまりよろしくありません。
ファイル内のデータの整合性を保証する仕組みが一切備わっていませんね。

プログラム内で、読み込んだデータの整合性を保証することが極めて困難です。

もうちょっと、フォーマットの仕様を考えなおした方がいい気がします。
フォーマットを考え直してみました。
► スポイラーを表示
このようになりましたが、このような書き方はあまりしたくないので仕様の変更は後々します。
とりあえず、このようにすればへろりさんのいっていた判断出来ない問題は解決するのか?と考えました。
これよりも良い方法があれば教えていただきたいです。
オフトピック
本当にどうでも良い事なので気にしないでください。本件とは無関係です。
► スポイラーを表示
>>jay様
構造体に纏めるとはそういうことです
但しみけCATさんが言っているように、メンバにポインタ変数やポインタ配列があったらアウトですので
曲名やコメントは2次元配列にしておいてくださいね
(ポインタの参照先を書き出すようにすれば出来なくはないですけど、面倒なだけですからね)
みけCATさんへの返信の中にある通り、あくまでサンプルで書いた物ですので本当は
二次元配列にしてあります。
ファイルを書きだす時に fopen 関数でバイナリ書き出しモードで構造体を出力する

読み込むときは fopen 関数でバイナリ読み込みモードでファイルを読み込む


というだけのことです。 あまり難しく考えず
構造体を中身のデータごとそのまま書きだして、そのまま読み込む
と考えてくださいね
正直、自分もインタプリタは大雑把にしか分かりません...
ですが、少々行程が面倒かな...?と思いました。出力関数と読み込み関数を書かなくては行けないので...
また、へろりさんの返信にある通りテキストで読めた方が誤植の修正が楽にしたいかなと考えテキスト形式
にしました。
非表示エリア
この非表示エリアを表示するには、登録し、ログインする必要があります。
非表示エリア
この非表示エリアを表示するには、登録し、ログインする必要があります。
>>Poco様
変数名や関数名の命名規則は統一しましょう。
具体的に言えば、FileNameとその他です。
統一されてないと汚く見え、スマートにはまず見えません。

どのような命名規則でも良いですが、とにかく統一することは常に頭に入れておいてください。
変数名は一応ハンガリアン記法っぽくしていますが、即時に思いついた変数はそれに反しているかもしれません
俺的ハンガリアン記法なので読みづらいかもしれませんが...
上のコードは何度も言いますが、上のトピックから引っ張って来た物なので最新の物ではありません。
最近になって変数の命名規則を統一し始めたので、ご理解下さい。申し訳ありません。
初心者です

閉鎖

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