4

改行やその他のさまざまな文字を含むことができる2つの文字列を読み取ることになっているプログラムを書いています。したがって、EOF(Ctrl-ZまたはCtrl-D)を使用して文字列を終了しています。

これは最初の変数では問題なく機能しますが、2番目の変数では、明らかに何かが入力バッファーにスタックしていて、ユーザーが何も入力できないため、これは問題があるようです。

while (getchar() != '\n');いくつかの同様のバリエーションでバッファをクリーンアップしようとしましたが、何も役に立たないようです。すべてのクリーニングの試行は無限ループになり、クリーニングなしでは、2番目の変数を追加することは不可能です。

両方の変数の文字は、次のようなループで読み取られます。while((c = getchar()) != EOF)これは、バッファーに残っているのがEOFであることを示しています。それとも、他の方法でプログラムの動作に影響を与えますか?私が使用しているロジックに何か問題がありますか?

これに何時間も苦労した後、私は少し必死になり始めています。

コード:

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

int main(void)
{
    int x = 0;
    int c;
    char a[100];
    char b[100];

    printf("Enter a: ");
    while((c = getchar()) != EOF)
    {
        a[x] = c;
        x++;
    }
    a[x] = '\0';
    x = 0;

    /*while (getchar() != '\n'); - the non-working loop*/

    printf("\nEnter b: ");
    while((c = getchar()) != EOF)
    {
        b[x] = c;
        x++;
    }
    b[x] = '\0';

    printf("\n\nResults:\na: %s\n", a);
    printf("b: %s\n", b);

    return(0);
}
4

7 に答える 7

12

端末からEOFを受信した後は、追加のデータを受信することはありません。入力のEOFを解除する方法はありません。ファイルの終わりは、まあ、終わりです。

したがって、各変数が別々の行に入力されるように定義し、ユーザーにEOFの代わりにEnterキーを押してもらう必要があります。eofを受信したかどうかを確認する必要があります。これは、ユーザーが実際にEOFを入力したことを意味し、他には何も表示されないためです。この場合、ループから抜け出し、エラーメッセージを出力する必要があります。

于 2009-10-25T21:20:25.960 に答える
2

EOF文字ではありません。これは、入力関数が条件を示すために返す特別な値であり、その入力ストリームの「ファイルの終わり」に到達したことを示します。Martinv.Löwisが言うように、「ファイルの終わり」状態が発生すると、そのストリームで利用できる入力がなくなることを意味します。

混乱が生じる理由は次のとおりです。

  • 多くの端末タイプは、「ファイル」が対話型端末である場合に「ファイルの終わり」を通知するための特別なキーストロークを認識します(例:Ctrl-ZまたはCtrl-D)。と
  • EOF値はgetchar()、関数ファミリーによって返される値の1つです。

入力を区切るには、実際の文字値を使用する必要があります'\0'。入力自体に有効な値として表示できない場合は、ASCIIヌル文字を選択することをお勧めします。

于 2009-10-25T21:32:51.473 に答える
1

Linuxボックスでコードを実行すると、結果は次のとおりです。

Enter a: qwer
asdf<Ctrl-D><Ctrl-D>
Enter b: 123
456<Ctrl-D><Ctrl-D>

Results:
a: qwer
asdf
b: 123
456

端末の入力バッファーが空ではないため、Ctrl-D が 2 回必要でした。

于 2009-10-25T22:26:59.437 に答える
0

あなたが試みていることは、EOFでは基本的に不可能です。

いくつかの点で1つのように動作しますが、EOFはストリーム内の文字ではなく、ストリームの終わりを表す環境定義のマクロです。私はあなたのコードを見ていませんが、あなたがやっているのは次のようなものだと思います。

while ((c=getchar()) != EOF) {
    // do something
}
while ((c=getchar()) != EOF) {
    // do something else
}

EOF文字を最初に入力するとき、最初の文字列を終了するために、ストリームは取り返しのつかないほど閉じられます。つまり、ストリームのステータスは閉じられています。

したがって、2番目のwhileループの内容は実行されません。

于 2009-10-25T21:30:43.910 に答える
0

ヌル文字('\0')を使用して変数を区切ることができます。さまざまなUNIXツール(たとえばfind)は、この方法で出力項目を分離することができます。これは、それがかなり標準的な方法であることを示唆しています。

これのもう1つの利点は、ストリームを単一のバッファーに読み込んでchar*から、個々の文字列を指すsの配列を作成でき'\0'、バッファー内の何も手動で変更しなくても、各文字列が正しく終了することです。これは、メモリ割り当てのオーバーヘッドが少ないことを意味し、読み取る変数の数によっては、プログラムの実行が著しく速くなる可能性があります。もちろん、これは、すべての変数を同時にメモリに保持する必要がある場合にのみ必要です。一度に1つずつ変数を処理する場合、この特別な利点は得られません。

于 2009-10-25T21:30:51.820 に答える
0

文字ではないEOF で入力の読み取りを停止するのではなく、 ENTER で停止します。

while((c = getchar()) != '\n')
{
    if (c == EOF) /* oops, something wrong, input terminated too soon! */;
    a[x] = c;
    x++;
}

EOF は、入力が終了したことを示すシグナルです。ユーザーからのすべての入力が '\n' で終わることがほぼ保証されます。これは、ユーザーが入力する最後のキーです!!!


編集: Ctrl-D を使用clearerr()して入力ストリームをリセットすることもできます。

#include <stdio.h>

int main(void) {
  char a[100], b[100];
  int c, k;

  printf("Enter a: "); fflush(stdout);
  k = 0;
  while ((k < 100) && ((c = getchar()) != EOF)) {
    a[k++] = c;
  }
  a[k] = 0;

  clearerr(stdin);

  printf("Enter b: "); fflush(stdout);
  k = 0;
  while ((k < 100) && ((c = getchar()) != EOF)) {
    b[k++] = c;
  }
  b[k] = 0;

  printf("a is [%s]; b is [%s]\n", a, b);
  return 0;
}
$ ./a.out
a: 2 を入力してください
行 (次の ENTER の直後に Ctrl+D)
b: 3 を入力してください
行
今すぐ (ENTER + Ctrl+D)
a は [2
行 (次の ENTER の直後に Ctrl+D)
]; b は [3
行
今すぐ (ENTER + Ctrl+D)
]
$
于 2009-10-25T21:50:39.300 に答える
0

プログラムで null をどのように入力しますか?

以下を使用して -print0 関数を実装できます。

putchar(0);

これにより、ASCII ヌル文字 '\0' が sdtout に出力されます。

于 2009-10-26T07:01:01.197 に答える