- ベストアンサー
C言語で2つのファイルを行ごとに読み込むプログラミング
- C言語で2つのファイルを行ごとに読み込むプログラムを作成したい場合、以下のような方法が考えられます。
- まず、2つのファイルをそれぞれ別々の変数で開きます。次に、1つ目のファイルから1行ずつ読み込み、2つ目のファイルからも1行ずつ読み込みます。
- 読み込んだ行を順番に表示し、1つ目のファイルの行を全て表示したら、2つ目のファイルの行を再び順番に表示します。これを繰り返すことで、2つのファイルを行ごとに交互に表示することができます。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
単純に 0.txt を一行読んで 1.txt を全て書き出すと考えます。 内側の while は一回働けば 1.txt をすべて読み込んでいますから、外側の while の二回目以降は EOF で働きません。 fgets関数をもう一度考え直してください。 内側の while でファイルの先頭から読み込ませる一番簡単な方法は、オープン/クローズを繰り返す方法です。 骨格だけですが。 fp = fopen("0.txt", "r"); while(fgets(buf, STR_MAX, fp) != NULL){ fp2 = fopen("1.txt", "r"); while(fgets(buf2, STR_MAX, fp2) != NULL){ printf("%s%s", buf,buf2); } fclose(fp2); } fclose(fp);
その他の回答 (4)
- samtomsan
- ベストアンサー率55% (1060/1897)
すみません。 > fgets関数をもう一度考え直してください これは「考え直す」でなく「調べなおす」でしたね。 charの比較はstrcmp関数を使います。 strcmp関数を調べてみてください。 if(strcmp(buf,buf2)) かな
お礼
strcmp を調べた結果 if(strcmp(buf , buf2) == 0) でできる事がわかりました。 応用も何とか出来そうな気がします。 初心者の私でも分かりやすく理解出来るような解答を 本当にありがとうございます。
- kmee
- ベストアンサー率55% (1857/3366)
すみません。仕様を勘違いしていました。 ファイルは基本的に、読み書きしたら、その位置のままです。 なので、最初から読み直す、といった、位置を変更したい場合はfseek関数やrewind関数を使います。 今回は先頭に戻すので、rewind関数が楽でしょう。 while(fgets(buf, STR_MAX, fp) != NULL){ rewind(fp2); /* 追加 */ while(fgets(buf2, STR_MAX, fp2) != NULL){ ただ、この方法は毎回ファイルを読み込むので(キャッシュで多少早くなる可能性はありますが)効率は悪いです。 ファイルサイズが小さく、メモリに余裕があるのなら、予め全部読み込んでおいて、対応する行だけ表示する、というのがいいのですが。 # 例によって、 Perlとかだと簡単だよなぁ、と思います。
- asuncion
- ベストアンサー率33% (2127/6289)
2つのテキスト「ファイル」の中身は、 各々2行ずつで固定ですか? 2以外の行数の場合も考える必要がありますか?
補足
質問に出したテキストファイルは あくまで例でして 本来 私がやろうとしているものは ファイルの中の行数は未知数という状況で そのファイルを最後の行まで表示させたいというものです。 しかもファイルによって行数が異ってもできるような プログラミングを考えています。 なので2以外の行数の場合も考える必要があります。
- kmee
- ベストアンサー率55% (1857/3366)
whileに限らず、二重ループというのは、 外側1回目 内側1回目 内側2回目 内側3回目 ... 内側最後 外側2回目 内側2-1回目 内側2-2回目 内側2-3回目 ... 内側2-最後 外側3回目 ... というようにループするものです。 考え方ですが。 まず、「1回」で行う処理は何かを考えましょう。 今回のなら { 0.txtを1行読み込んで、(読み込めたなら)表示する 1.txtを1行読み込んで、(読み込めたなら)表示する } というもののはずです。 次に、どんな風に繰り返すのかを考えます。 今回は「先頭行から最終行まで」ですよね。 順番に並んでいて、しかも1方向だけです。ということは、ループも1重で済むということです。 あとは、実装方法はいろいろあります。 ・無限ループを作って、終了条件になったらbreakで抜ける。 ・終了するかどうかのフラグ用の変数でループを制御する。 等々. 両ファイルの行数が違う場合とかエラーがあったときとかを考えると、ちょっと複雑になります。 両ファイルの行数が同じ場合で、エラー処理とか考えなければ > while(fgets(buf2, STR_MAX, fp2) != NULL){ これを > if(fgets(buf2, STR_MAX, fp2) != NULL){ こうすると、とりあえずは動作します。どうしてそうなるかは、よく考えてみてください。 あとは別件ですが。 > 0.txt と 1.txt という2つのテキストフォルダがあり 用語を誤解されています。 こういうものは「ファイル」といいます。 「フォルダ」というのは複数のファイルをまとめておける「ファイルの入れ物」です。 ファイルとフォルダとでは、プログラムの方法も変わってきます。今回は例があったので「ファイル」の誤用だとわかりましたが、単独でフォルダ/ファイルと言われると、相手に正しく伝わりません。 > if (fp == NULL && fp2 == NULL){ and条件とor条件は理解していますか? && は 両方成立つときに真となる「and条件」です。 fopenで失敗したときの戻り値がNULLなので、このif文は「 0.txtも1.txtもfopenに失敗したとき」と言う意味になります。 「0.txtだけ失敗した」や「1.txtだけ失敗した」場合にはこのif文は成り立ちません。 また、エラー処理をしているのかと思えば > printf("\n"); と、改行文字を表示しているだけです。何を意図しているのでしょうか? > } > printf("\n"); > } > fclose(fp); > fclose(fp2); ここのprintfは期待しているものですか? 元の例では、1.txtが終ったときに、私のwhile→ifの変更では2行置きに改行が表示されます。 1.txtには行末の改行文字があるので、ただ継げるだけなら必要無いのではないでしょうか。
お礼
c言語はまだかなりの初心者でして 質問するのも難しかったのですが 私の誤りのあった質問の意図を理解していただき ありがとうございます。 ご回答の内容を参考に いろいろな方法を考えてみたいと思います。
お礼
ありがとうございます。 実行結果は見事 私の理想通りになりました。 おっしゃる通りでfgets関数を考え直すべきだと思いました。 更に質問なのですが たとえば 先ほどの例として出したテキストファイル 1.txt の中身を a a d d としておなじ動作をおこなうとき buf,buf2 が等しい時が(buf,buf2=a a)存在するので if(buf == buf2){ printf("%s%s", buf,buf2); } とすれば、 実行結果が a a a a と表示されると思ったのですが 何も表示されません。 buf = a a buf2 = a a だとしても if(buf == buf2) は使えないのでしょうか?