みなさん、返信ありがとうございます。
風邪を引いたみたいで昨日は返信が出来ませんでした。
>>beatle様
ファイルの内容に何らかの文法があるようですね。
文法があるということは、原理的にはそれを字句解析、構文解析をするということになります。
したがって、読込部分が複雑になるのは必然ですから、それほどシンプルなプログラムには成らないでしょう。
(今のプログラムも構文解析してると思えばそれなりにすっきりしたコードだと思いますよ)
ありがとうございます。自分としては、もっとすっきり書けるのではないだろうか、と考えていました。
読み込みと字句解析というかなんというか、同時にするのは如何なものかと考えましたが、自分の力ではどうすることも
できず...
もっと楽ちんにしたいなら、普及している文法を使うのです。
例えばXMLやJSONにしておけば、構文解析は既成のライブラリを使えます。
自分の考えているものはそこまで複雑な文法は使わないので、必要はないかなと考え、独自のフォーマットで
したいと思いました。
>>みけCAT様
ただ、最初のプログラムだと、行の途中に#があった時の動作が気になります。(仕様でしょうか?)
念のため書いておきます。
提示された構造体にはポインタが含まれるため、そのままバイナリデータとしてファイルに書き出しても無効なデータになります。
注意してください。
はい、仕様です。行の途中にコメントを入れる事は無いので。
また、ポインタは使用しておりません。あくまで、こんな感じですか?、と言う
サンプルを示す物ですので、現在書いているコードとは異なっております。
とりあえず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 ); // ファイルクローズ
}
【編集】空行を読み飛ばす処理を追加しました
サンプルコードありがとうございます。自分の書いていたコードよりすっきりして見やすいです。
1行64バイトまでとなっておりますので仕様は変えないで行いたいと思います
最初のプログラムでは、1行に128バイトちょうど書かれている場合、誤動作する可能性があります。
そのようなテストケース(最大テストケース)でのテストはしていますか?
もちろん1行が64バイトまでという仕様なら大丈夫です。
エラー処理ですか...そうですね、ファイルが無い時だけエラーを出すような物でも良いかもしれません。
ユーザーは書く事がないのでごっそり減らします。
あとは、エラー処理がどのくらい必要かですね。
読み込むファイルをこの処理の作者しか書かないのでしたら、エラー処理はほとんど省略でいいと思います。
逆に、読み込むファイルをユーザーが(普通の状況=チート/公式でない改造ではない状況で)書くことがあるのでしたら、
エラー処理をきちんと考えた方がいいと思います。
例えば、fgetcで読み込み、行の最大の長さを超えた部分はメモリに保存しないという処理方法が考えられます。
fgetcでですか?fgetsでは無く?
>>へろりんご様
コードの書き方という事でしたら、若干スパゲッティ化してますので、これを解決するのが第一の目標でしょう。
不要なカウンタが多いです。 そして原則としてカウンタを減らすのは軽く禁じ手です。
とりあえず、日本語でコードを書いてみるとすっきりします。
日本語で書いてみる、とは
► スポイラーを表示
コード:
int ScriptReader( ファイル名 )
{
ファイルを読み込む
ファイルが無ければエラー終了
ファイルから読み込んだデータを変数にコピー
ファイル閉じる
正常終了
}
のようにするのですか?それとも、フローチャートの様にするのですか?
まず、構造化を意識します。
1関数は、1機能だと心がけてください。
読み込むファイルを関数内で、決め打ちしてますが、これは引数として渡すべき物です。
また、プログラムを殺してしまう関数はあまり好ましくありません。
戻り値を利用し、失敗時にはエラーを返すようにするべきです。
また、正否の判断は、呼び出し元に責任を負わせた方がいいです。
なるほど。構造化、一関数一機能を心がけてコーディングしていきます。
なかなか指摘されないと気がつかない物なんですね。
C言語との話ですが、変数 music は、クラスのメンバ変数でしょうか。 C言語的には、これも引数として与えた方がいいです。
あるいは、成功時には、関数内で動的に生成された music インスタンスのポインタを返し、失敗時には NULL を返すとか。
適当ですが、C言語的に書くと、こんな感じでしょうか。
コンパイルはしてません。
ポインタの配列のようですが、件のコードの中に、これらのメンバを動的に確保していないようですが、よいのでしょうか。
前のスレッドを見てないから分かりませんが。
musicは構造体配列です。Hoge_tの。また、Hoge_tの中にポインタがありますが本当は二次元配列です。
出来れば、Hoge_t構造体があるファイルの中だけで行いたいのですが、どうしても引数にしなければ
いけませんか?
ところで、ファイルフォーマットの仕様に触れるなら、そもそも件のフォーマットはあまりよろしくありません。
ファイル内のデータの整合性を保証する仕組みが一切備わっていませんね。
プログラム内で、読み込んだデータの整合性を保証することが極めて困難です。
もうちょっと、フォーマットの仕様を考えなおした方がいい気がします。
フォーマットを考え直してみました。
► スポイラーを表示
コード:
# =========================================================
# @bgm : BGMのパス
# @name : 曲名
# @cmt : コメント開始 // このあたりの仕様は変更します。
# @cmtend : コメント終了 // 何となく気持ち悪いので。
# =========================================================
# =========================================================
@bgm bgm/○○.wav
@name テスト1.~test
@cmt
コメント1
コメント2
コメント3
コメント4
コメント5
コメント6
コメント7
@cmtend
# =========================================================
このようになりましたが、このような書き方はあまりしたくないので仕様の変更は後々します。
とりあえず、このようにすればへろりさんのいっていた判断出来ない問題は解決するのか?と考えました。
これよりも良い方法があれば教えていただきたいです。
オフトピック
本当にどうでも良い事なので気にしないでください。本件とは無関係です。
► スポイラーを表示
へろりさんのポイントが2013/11/17 14:00 現在 69669 となっていておおwとなっただけです。
本件と関係無い事書いてしまい、申し訳ありません。
>>jay様
構造体に纏めるとはそういうことです
但しみけCATさんが言っているように、メンバにポインタ変数やポインタ配列があったらアウトですので
曲名やコメントは2次元配列にしておいてくださいね
(ポインタの参照先を書き出すようにすれば出来なくはないですけど、面倒なだけですからね)
みけCATさんへの返信の中にある通り、あくまでサンプルで書いた物ですので本当は
二次元配列にしてあります。
ファイルを書きだす時に fopen 関数でバイナリ書き出しモードで構造体を出力する
読み込むときは fopen 関数でバイナリ読み込みモードでファイルを読み込む
というだけのことです。 あまり難しく考えず
構造体を中身のデータごとそのまま書きだして、そのまま読み込む
と考えてくださいね
正直、自分もインタプリタは大雑把にしか分かりません...
ですが、少々行程が面倒かな...?と思いました。出力関数と読み込み関数を書かなくては行けないので...
また、へろりさんの返信にある通りテキストで読めた方が誤植の修正が楽にしたいかなと考えテキスト形式
にしました。
非表示エリア
この非表示エリアを表示するには、登録し、ログインする必要があります。
非表示エリア
この非表示エリアを表示するには、登録し、ログインする必要があります。
>>Poco様
変数名や関数名の命名規則は統一しましょう。
具体的に言えば、FileNameとその他です。
統一されてないと汚く見え、スマートにはまず見えません。
どのような命名規則でも良いですが、とにかく統一することは常に頭に入れておいてください。
変数名は一応ハンガリアン記法っぽくしていますが、即時に思いついた変数はそれに反しているかもしれません
俺的ハンガリアン記法なので読みづらいかもしれませんが...
上のコードは何度も言いますが、上のトピックから引っ張って来た物なので最新の物ではありません。
最近になって変数の命名規則を統一し始めたので、ご理解下さい。申し訳ありません。