質問
私は、改行とその他のさまざまな文字を含むことができる2つの文字列を読み取ることになっているプログラムを書いています。そのため、EOF(Ctrl-ZまたはCtrl-D)を使用して文字列を終了しています。
これは最初の変数では問題なく動作しますが、2番目の変数では問題があるように見えます。入力バッファに何かが詰まっていて、ユーザーが何も入力できないためです。
while(getchar()!= '\ n');
およびいくつかの同様のバリエーションを使用してバッファーをクリーニングしようとしましたが、何も役に立たないようです。すべてのクリーニングの試みは無限ループに終わり、クリーニングなしでは2番目の変数の追加は不可能です。
両方の変数の文字は、次のようなループで読み取られます: while((c = getchar())!= EOF)
。私のバッファ。または、他の方法でプログラムの動作に影響しますか?私が使用しているロジックに何か問題がありますか?
これに何時間も苦労した後、少し必死になり始めています。
[編集:以下のコードを追加]
[編集2:clearerr()は結局このEOFソリューションを動作させるようです。
Linuxで意図したように、元の形式で実行されるようです。昨日はWindowsで試していました。]
コード:
#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);
}
[編集3:]
動的メモリの問題:
私のプログラムは、100文字を超える文字列も処理することになっています。元々は動的なメモリ割り当てによってそれを解決するつもりでしたが、上記の無限ループとメモリ関連のクラッシュで問題が発生した場合、それを取り除いてchar [100]に切り替えました。
私が試したのは一般に次のようなものだと思います:
while((c = getchar()) != EOF)
{
a = malloc(sizeof(char));
a[x] = c;
x++;
}
それは可能な(または賢明な)方法ですか?そこで処理されているすべての文字に対して、より多くのメモリを割り当てようとしています。個別に。そのようなコード(この例にはおそらく構文エラーが含まれています)でクラッシュが発生したため、mallocが適切な機能ではないように見えるか、間違っています。それも可能だと仮定します。
解決
端末からEOFを受信した後、追加データを受信しません。入力のEOFを解除する方法はありません-ファイルの終わりは、まあ、終わりです。
したがって、各変数は別々の行に入力し、ユーザーにEOFの代わりにEnterを押しさせるように定義する必要があります。 eofを受け取ったかどうかを確認する必要があります。これは、ユーザーが実際にEOFを入力したことを意味し、他には何も表示されないことを意味します。この場合、ループを抜けてエラーメッセージを出力する必要があります。
他のヒント
EOF
は文字ではありません。これは、入力関数が条件を示すために返す特別な値で、&quot; endファイルの&quot;その入力ストリームに到達しました。 Martin v。L&#246; wisが言うように、「ファイルの終わり」が条件が発生した場合、そのストリームで使用可能な入力がこれ以上ないことを意味します。
混乱の原因は次のとおりです。
- 多くの端末タイプは、特別なキーストロークを認識して「ファイルの終わり」を通知します。 &quot; file&quot;インタラクティブなターミナル(例:Ctrl-ZまたはCtrl-D);そして
-
EOF
値は、getchar()
ファミリーの関数によって返される可能性のある値の1つです。
実際の文字値を使用して入力を区切る必要があります-ASCIIヌル文字 '\ 0'
は、それが有効な値として表示されない場合、適切な選択である可能性があります入力自体。
Linuxボックスでコードを実行します。結果は次のとおりです。
Enter a: qwer
asdf<Ctrl-D><Ctrl-D>
Enter b: 123
456<Ctrl-D><Ctrl-D>
Results:
a: qwer
asdf
b: 123
456
端末入力バッファが空ではなかったため、2つのCtrl-Dが必要でした。
ヌル文字( '\ 0'
)を使用して変数を区切ることができます。さまざまなUNIXツール( find
など)は、この方法で出力項目を分離できます。これは、かなり標準的な方法であることを示唆しています。
これの別の利点は、ストリームを単一のバッファに読み込んでから、 char *
の配列を作成して個々の文字列を指すことができ、各文字列が正しく '\ 0'
-バッファ内の何かを手動で変更することなく終了しました。これは、メモリ割り当てのオーバーヘッドが少ないことを意味します。これにより、読み取り中の変数の数によっては、プログラムの実行速度が著しく速くなる場合があります。もちろん、これはすべての変数をメモリに同時に保持する必要がある場合にのみ必要です&#8212;それらを一度に1つずつ処理する場合、この特定の利点は得られません。
しようとしていることは、EOFでは基本的に不可能です。
何らかの方法で動作しますが、EOFはストリーム内の文字ではなく、ストリームの end を表す環境定義マクロです。あなたのコードを見たことはありませんが、あなたがしていることは次のようなものです。
while ((c=getchar()) != EOF) {
// do something
}
while ((c=getchar()) != EOF) {
// do something else
}
最初にEOF文字を入力すると、最初の文字列を終了するために、ストリームは完全に閉じられます。つまり、ストリームのステータスは閉じているということです。
したがって、2番目のwhileループの内容は実行されません。
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 Enter a: two lines (Ctrl+D right after the next ENTER) Enter b: three lines now (ENTER + Ctrl+D) a is [two lines (Ctrl+D right after the next ENTER) ]; b is [three lines now (ENTER + Ctrl+D) ] $
プログラムにnullを入力する方法
次を使用して-print0関数を実装できます。
putchar(0);
これにより、ASCIIヌル文字「\ 0」がsdtoutに出力されます。