アプリ版:「スタンプのみでお礼する」機能のリリースについて

 ファイルaとファイルbから1行ずつ順にデータを読み込んでその行の大小関係を比較して、小さい方の行(同じ大きさなら両方)をファイルcに書き込むプログラムを作成したいと考えています。
 そこで、以下のようなソースコード(途中まで)を書いてみました。

#include <stdio.h>
main()
{ FILE *fpa,*fpb,*fpc;
char fpa_data[200],fpb_data[200];
fpa=fopen("filea.txt","r");
fpb=fopen("fileb.txt","r");
fpc=fopen("filec.txt","a");
fscanf(fpa,"%s\n",fpa_data);
fscanf(fpb,"%s\n",fpb_data);
x = strcmp( fpa_data,fpb_data);
if(x<0)
fprintf(fpc,"%s\n",fpa_data);
else if(x=0)
fprintf(fpc,"%s\n%s\n",fpa_data,fpb_data);
else
fprintf(fpc,"%s\n",fpb_data);
}

 このソースコードですと、最初の1行目のみが正しく実行されると思いますが、これを2行目以降の行に対しても行うようにするには、どのようにすればよいでしょうか?
 ご回答宜しくお願いします。

A 回答 (8件)

>if (fgets(buff_a, BUFFSIZE, fp_a) == NULL) break;


>ですと、行の終わりでwhileループから抜け出してしまい、
>1行目しかファイルcに書き込まれないような気がします。

いえいえ。
fgetsはファイルから1行読み込んで、その文字列を返します。
もしファイルの終端までいったら、NULLを返します。


>あと、ファイルの一方が先に終端までいった際には、もう一方の
>ファイルの残りの行全てをファイルcに書き出したいのですが、
>どのようにすればいいでしょうか?

各ファイルが終端にいったかどうかをあらわすフラグを
用意すればいいでしょう。
たとえばこのように(a_is_endとb_is_end)。

#include <stdio.h>
#include <string.h>

int main(void)
{
#define BUFFSIZE 256
  char buff_a[BUFFSIZE];
  char buff_b[BUFFSIZE];

  FILE *fp_a = fopen("a", "r");
  FILE *fp_b = fopen("b", "r");
  FILE *fp_c = fopen("c", "w");

  int a_is_end = 0;
  int b_is_end = 0;

  while (1) {
    if (!a_is_end && fgets(buff_a, BUFFSIZE, fp_a) == NULL)
      a_is_end = 1;
    if (!b_is_end && fgets(buff_b, BUFFSIZE, fp_b) == NULL)
      b_is_end = 1;

    if (a_is_end && b_is_end) break;
    if (!a_is_end && !b_is_end) {
      switch (strcmp(buff_a, buff_b)) {
      case -1:
        fprintf(fp_c, "%s", buff_a);
        break;
      case 0:
        fprintf(fp_c, "%s%s", buff_a, buff_b);
        break;
      case 1:
        fprintf(fp_c, "%s", buff_b);
        break;
      }
    }
    if (b_is_end) fprintf(fp_c, "%s", buff_a);
    if (a_is_end) fprintf(fp_c, "%s", buff_b);
  }
  fclose(fp_a);
  fclose(fp_b);
  fclose(fp_c);

  return 0;
}

この回答への補足

ご回答ありがとうございます。

>いえいえ。 fgetsはファイルから1行読み込んで、その文>字列を返します。 もしファイルの終端までいったら、N
>ULLを返します。

なるほど、fgetsは文末まで順に読み込んでくれるのですね。fscanfは1行読み込んだら終わってしまいますので、私が最初に考えたプログラムではどうすることもできませんね。(笑)

>各ファイルが終端にいったかどうかをあらわすフラグを
>用意すればいいでしょう。
>たとえばこのように(a_is_endとb_is_end)。

そう考えたらよかったんですね。恐らく自分ひとりで考えていたら、そういう発想はできなかったと思います。

 プログラムの方も先ほど実行したところ、きちんと動作しました。どうもありがとうございました。
 
 Cをはじめて1ヶ月の初心者ですので、これからもお世話になることがあるかもしれませんが、その時には、宜しくお願い致します。(m_m)

補足日時:2004/01/20 18:23
    • good
    • 0
この回答へのお礼

お礼の内容を回答に対する補足のところに書いてしまいました。申し訳ございませんでした。

お礼日時:2004/01/20 19:12

> case文中で不等号を含む条件分岐は書けるのでしょうか?(多分無理だと思いますが・・・)



おっしゃるとおり、無理です。
if文を使うのが普通の方法でしょう。
    • good
    • 0
この回答へのお礼

何度もありがとうございました。

お礼日時:2004/01/21 00:08

> >> result = stata ? 1 : -1;


>の文はどういったことをしているのでしょうか?

まず、この if文(else)に入る条件は ファイルAまたは ファイルBのいずれかが既にファイルの終端まで達している場合です。
stata 及び statbは fgetsの戻り値を格納する変数で、ファイルが終端に達していれば NULLが入ってますよね。
result = stata ? 1 : -1 はご存じかもしれませんが、三項演算子で、stataが 0(NULL)ではないとき、resultに 1を格納、0以外の時は -1を格納します。つまり、stata (ファイルA)にデータが残っている場合は 1を入れ、stataが空の時(ファイルBにデータが残っているとき)は -1を入れます。

...とここまで書いて、バグに気が付きました^^;)。
---
 int stata = 1, statb = 1;
 while (1) {
  if (stata) stata = fgets (fpa_data, 200, fpa);
  if (statb) statb = fgets (fpb_data, 200, fpb);
  if (stata && statb) {
   result = strcmp (fpa_data, fpb_data);
  } else if (stata || statb) {
   result = stata ? 1 : -1;
  } else {
   break;
  }

  if (result <= 0) fprint (fpc, "%s\n", fpa_data);
  if (result >= 0) fprint (fpc, "%s\n", fpb_data);
 }
---
#はづかしい...
    • good
    • 0
この回答へのお礼

 なるほど、そういうことだったんですね。
 何度もありがとうございました。

お礼日時:2004/01/21 00:08

ちょっと注意。



strcmp(a, b)の戻り値は、
・a < b のとき ゼロより小さいint (-1とは限らない)
・a > b のとき ゼロより大きいint(1とは限らない)
・a == b のとき 0
ですので、No.4のように-1、1と比較するのは
よくないでしょう。
(自分で書いといてなんなんですが)

この回答への補足

度々ありがとうございます。
私の処理系では-1,0,1でも問題ありませんでしたが、念のために変えといた方がいいですね。
if文を使ってなら、
int x;
x=strcmp(buff_a,buff_b);
if(x<0);
・・・
 と書けますが、
 case文中で不等号を含む条件分岐は書けるのでしょうか?(多分無理だと思いますが・・・)

補足日時:2004/01/20 19:49
    • good
    • 0

締め切られていないようなので、参考までに自分のソースを改造して要求仕様に合わせてみました。


---
 int stata = 1, statb = 1;
 while (stata || statb) {
  if (stata) stata = fgets (fpa_data, 200, fpa);
  if (statb) statb = fgets (fpb_data, 200, fpb);
  if (stata && statb) {
   result = strcmp (fpa_data, fpb_data);
  } else {
   result = stata ? 1 : -1;
  }

  if (result <= 0) fprint (fpc, "%s\n", fpa_data);
  if (result >= 0) fprint (fpc, "%s\n", fpb_data);
 }
---

この回答への補足

 度々ありがとうございます。
 早速、質問させていただきたいのですが、
 stataは普通の変数と考えれば宜しいのでしょうか?
 それとも、何か特別な意味があるのでしょうか?
 また、
 >> result = stata ? 1 : -1;
の文はどういったことをしているのでしょうか?
 いままで、こういった文を見たことがないもので・・
 低レベルな質問と思いますが、宜しければご回答をお願いします。

補足日時:2004/01/20 19:33
    • good
    • 0

あ、いきなり間違いに気が付きました^^;)。



 while (stata && statb) {
->
 while (stata || statb) {

でした。
    • good
    • 0

若干条件があいまいなので、いくつか仮定して書いてみました。



ファイルA, ファイルBは昇順にソート済である。
同じ行同士を比較するのではなく、AとBのファイルをマージしながら昇順に書き込む。

fopen以降の例
---
 stata = fgets (fpa_data, 200, fpa);
 statb = fgets (fpb_data, 200, fpb);
 while (stata && statb) {
  if (stata && statb) {
   result = strcmp (fpa_data, fpb_data);
  } else {
   result = stata ? 1 : -1;
  }

  if (result <= 0) {
   fprint (fpc, "%s\n", fpa_data);
   stata = fgets (fpa_data, 200, fpa);
  } else {
   fprint (fpc, "%s\n", fpb_data);
   statb = fgets (fpb_data, 200, fpb);
  }
 }
---
#未検証です。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

>ファイルA, ファイルBは昇順にソート済である。
>同じ行同士を比較するのではなく、AとBのファイルをマー>ジしながら昇順に書き込む。

 せっかく回答して頂いて申し訳ないのですが、ファイルA
とファイルBは昇順にソート済みではないのです。私としましては、1行1行の大きさを調べながらファイルに書き込んでいくといったプログラムを作成したいと考えておりました。
 誤解を与える表現で申し訳ございませんでした。

お礼日時:2004/01/20 19:10

とりあえずどっちかのファイルの終端までいったら


そこでおしまいってことにするとこんな感じでしょうか。

#include <stdio.h>
#include <string.h>

int main(void)
{
#define BUFFSIZE 256
  char buff_a[BUFFSIZE];
  char buff_b[BUFFSIZE];

  FILE *fp_a = fopen("a", "r");
  FILE *fp_b = fopen("b", "r");
  FILE *fp_c = fopen("c", "w");
  while (1) {
    if (fgets(buff_a, BUFFSIZE, fp_a) == NULL) break;
    if (fgets(buff_b, BUFFSIZE, fp_b) == NULL) break;
    switch (strcmp(buff_a, buff_b)) {
    case -1:
      fprintf(fp_c, "%s", buff_a);
      break;
    case 0:
      fprintf(fp_c, "%s%s", buff_a, buff_b);
      break;
    case 1:
      fprintf(fp_c, "%s", buff_b);
      break;
    }
  }
  fclose(fp_a);
  fclose(fp_b);
  fclose(fp_c);

  return 0;
}

この回答への補足

 レスありがとうございます。
少し、分からないことがありますので、質問させていただきたいのですが、
if (fgets(buff_a, BUFFSIZE, fp_a) == NULL) break;
ですと、行の終わりでwhileループから抜け出してしまい、
1行目しかファイルcに書き込まれないような気がします。
 あと、ファイルの一方が先に終端までいった際には、もう一方のファイルの残りの行全てをファイルcに書き出したいのですが、どのようにすればいいでしょうか?
 ご回答宜しくお願い致します。

補足日時:2004/01/19 00:56
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!