
c言語 2つのファイルを行ごとに読み込むプログラミング
0.txt と 1.txt という2つのテキストフォルダがあり
0.txt の中身は
a a
b b
1.txt の中身は
c c
d d
というものとします。
これら2つのフォルダを読み込むとき
まず1つのフォルダの1行目(a a)を表示し
他方の1行目(c c) 2行目(d d)を表示させて
続いて1つのフォルダの2行目(b b)を表示し
他方の1行目(c c) 2行目(d d)を表示させたいのです。
つまり実行結果が
a a
c c
a a
d d
b b ←理想の実行結果です
c c
b b
d d
となるようにしたいのですが
#include <stdio.h>
#include <stdlib.h>
#define STR_MAX 256
int main(void)
{
FILE *fp, *fp2;
int i, j, k;
char buf[STR_MAX];
char buf2[STR_MAX];
fp = fopen("0.txt", "r");
fp2 = fopen("1.txt", "r");
if (fp == NULL && fp2 == NULL){
printf("\n");
}
while(fgets(buf, STR_MAX, fp) != NULL){
while(fgets(buf2, STR_MAX, fp2) != NULL){
printf("%s%s", buf,buf2);
}
printf("\n");
}
fclose(fp);
fclose(fp2);
return 0;
}
このプログラミングの実行結果は
a a
c c
a a
d d
となり、0.txtの2行目(b b)は表示されません。
おそらく while 文 を2重にすることで
不具合が起きているのだと思うのですが
色々と調べた結果、これ以外に
プログラミングが思いつきません。
私の理想の実行結果にするためには
どこを訂正させると良いのでしょうか?
恐れ入りますが ご回答 どうかよろしくお願いいたします。
No.3ベストアンサー
- 回答日時:
単純に 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);
ありがとうございます。
実行結果は見事
私の理想通りになりました。
おっしゃる通りで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)
は使えないのでしょうか?
No.4
- 回答日時:
すみません。
仕様を勘違いしていました。ファイルは基本的に、読み書きしたら、その位置のままです。
なので、最初から読み直す、といった、位置を変更したい場合はfseek関数やrewind関数を使います。
今回は先頭に戻すので、rewind関数が楽でしょう。
while(fgets(buf, STR_MAX, fp) != NULL){
rewind(fp2); /* 追加 */
while(fgets(buf2, STR_MAX, fp2) != NULL){
ただ、この方法は毎回ファイルを読み込むので(キャッシュで多少早くなる可能性はありますが)効率は悪いです。
ファイルサイズが小さく、メモリに余裕があるのなら、予め全部読み込んでおいて、対応する行だけ表示する、というのがいいのですが。
# 例によって、 Perlとかだと簡単だよなぁ、と思います。
No.1
- 回答日時:
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言語はまだかなりの初心者でして
質問するのも難しかったのですが
私の誤りのあった質問の意図を理解していただき
ありがとうございます。
ご回答の内容を参考に
いろいろな方法を考えてみたいと思います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# プログラミングのペーパーテスト 実行結果を表示せよ #include <stdio.h> int h 1 2022/07/09 15:27
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- PHP PHPでテキストファイルに保存した時の改行問題 1 2022/11/19 15:07
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# プログラミングのペーパーテスト 実行結果がどのように表示されるか答えよ #include <stdi 1 2022/07/09 14:27
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
テキストファイルの行数を取得...
-
fprintfで出力するファイルのパ...
-
バイナリファイルをテキストフ...
-
EOF判定されない
-
ファイル内のデータを1行削除...
-
fgetsで2行目から文字化け
-
0バイトファイルの作成
-
VS2010 MFC CStdioFileについて
-
文字化けを直したい
-
freadでファイルを読み込んだ際...
-
VBSで指定行に挿入
-
どんなプログラムを書いても指...
-
FTPでputすると空ファイルが出...
-
Access クエリ実行が急に非常に...
-
フルパスから最後のディレクト...
-
セルに入力されたパスでフォル...
-
バッファとは何ですか
-
C言語初心者の質問失礼します。
-
VB.NETで他のプロジェクトで作...
-
「UNCパスはサポートされません...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
バイナリファイルをテキストフ...
-
テキストファイルの行数を取得...
-
ファイル内のデータを1行削除...
-
巨大なテキストファイル(可変...
-
複数テキストファイルを読み込...
-
fgetsで2行目から文字化け
-
【VB.Net】バイト型配列に読み...
-
改行までの一文字ずつのファイ...
-
C言語での改行コードの扱いにつ...
-
InternetReadFileで大きいファ...
-
C/C++ ファイル入出力操作 (長...
-
fopenで開いたファイルのサイズ...
-
fopen(書き込みモード)でファイ...
-
テキストファイルの文字列の削除
-
ファイル読み込みについて
-
C言語のローカル変数の使い方に...
-
freadとfwrite
-
EOF判定されない
-
続・EOF判定されない
-
fortranで文字列を読み込む際の...
おすすめ情報