`getchar()`はユーザー入力をどこに保存しますか?
-
05-07-2019 - |
質問
" Cプログラミング言語"を読み始めました。 (K& R)および getchar()
関数について疑問があります。
たとえば、次のコード:
#include <stdio.h>
main()
{
int c;
c = getchar();
putchar(c);
printf("\n");
}
toomanychars
+ CTRL + D (EOF)を入力すると、 t
だけが印刷されます。導入された最初のキャラクターなので、それが期待されていると思います。
しかし、次のコード:
#include <stdio.h>
main()
{
int c;
while((c = getchar()) != EOF)
putchar(c);
}
toomanychars
+ CTRL + D (EOF)を入力すると、 toomanychars
が印刷されます。
私の質問は、単一のchar変数しかない場合、なぜこれが起こるのですか?残りの文字はどこに保存されますか?
編集:
回答してくれたすべての人に感謝します。今すぐ入手し始めました...たった1つのキャッチ:
最初のプログラムは CTRL + D が与えられると終了しますが、2番目のプログラムは文字列全体を出力し、さらにユーザーの入力を待ちます。なぜ別の文字列を待機し、最初のように終了しないのですか?
解決
入力ストリームをファイルのように扱っています。 「toomanychars」というテキストを含むファイルを開いたかのようです。一度に1文字ずつ読み取りまたは出力します。
最初の例では、whileループがない場合、ファイルを開いて最初の文字を読み取ってから出力したようなものです。ただし、2番目の例では、ディスク上のファイルから読み取る場合と同様に、ファイルの終わり信号(この場合は ctrl + D
)を受け取るまで文字を読み取り続けます。
更新された質問への回答では、どのオペレーティングシステムを使用していますか? Windows XPラップトップで実行したところ、問題なく動作しました。 Enterキーを押すと、今までの内容が出力され、新しい行が作成されて続行されます。 ( getchar()
関数は、Enterキーを押すまで返されません。Enterキーを押すと、入力バッファーに何も呼び出されなくなります)。 CTRL + Z
(WindowsではEOF)を押すと、プログラムが終了します。 Windowsでは、コマンドプロンプトでEOFとしてカウントするために、EOFはそれ自身の行になければならないことに注意してください。この振る舞いがLinuxで模倣されているのか、実行中のシステムであるのかはわかりません。
他のヒント
getchar
は、標準入力(この場合はキーボードバッファー)から単一の文字を取得します。
2番目の例では、 getchar
関数は while
ループ内にあり、 EOF
に遭遇するまで継続するため、ループし続けます入力が空になるまで文字を取得(および画面に文字を印刷)します。
getchar
を連続して呼び出すと、入力から連続する文字が取得されます。
ああ、この質問をするのは気にしないでください-この問題に最初に出会ったときも困惑しました。
ここにあるものはバッファリングされています。例えばputcharが書き込むstdout FILE *は、line.bufferedである可能性があります。プログラムが終了(または改行に遭遇)すると、そのようなFILE *はfflush()され、出力が表示されます。
場合によっては、表示している実際の端末は、改行まで、または端末自体がバッファをフラッシュするように指示されるまで出力をバッファすることがあります。これは、現在のフォアグラウンドプログラムが終了するために終了する場合です新しいプロンプト。
今、ここで実際のケースになる可能性が高いのは、(出力に加えて)入力がバッファリングされることです:-))キーを押すと、ターミナルウィンドウに表示されます。ただし、端末はこれらの文字をアプリケーションに送信せず、Ctrl + Dで入力の終わりであるように指示するまでバッファし、場合によっては改行もバッファします。 いろいろと試して検討する別のバージョンを次に示します。
int main() {
int c;
while((c = getchar()) != EOF) {
if(c != '\n')
putchar(c);
}
return 0;
}
プログラムに文を入力して、Enterキーを押します。そしてコメントアウトした場合も同じことをします if(c!= '\ n')入力、出力、またはその両方が何らかの方法でバッファリングされているかどうかを判断できるかもしれません。 上記のように実行すると、これはさらに興味深いものになります。 ./mytest | ./mytest
(サイドコメントとして、CTRD + Dは文字ではなく、EOFでもないことに注意してください。ただし、一部のシステムでは入力ストリームが閉じられ、ストリームからの読み取りを試みるすべてのユーザーに対してEOFが発生します。)
最初のプログラムは1文字のみを読み取り、それを出力して終了します。 2番目のプログラムにはループがあります。文字を1つずつ読み取り、EOF文字を読み取るまで印刷し続けます。常に1文字のみが保存されます。
変数 c
を使用して、各文字を1つずつ含めるだけです。
putchar(c)
を使用して最初の文字( t
)を表示したら、割り当てて c
の値を忘れます次の文字( o
)を変数 c
に追加し、前の値( t
)を置き換えます。
コードは機能的に同等です
main(){
int c;
c = getchar();
while(c != EOF) {
putchar(c);
c = getchar();
}
}
このバージョンは理解しやすいかもしれません。条件に代入を配置する唯一の理由は、 'c = getchar()'を2回入力することを避けるためです。
更新された質問の最初の例では、1文字のみが読み取られます。 EOFに達することはありません。 printf命令を完了した後に実行することは何もないため、プログラムは終了します。それはただ1文字を読みます。印刷します。改行を入れます。そして、それ以上することはないので終了します。複数の文字を読み取ることはありません。
一方、2番目のコードでは、getcharとputcharがwhileループ内に存在します。この場合、プログラムは、reachがEOF文字(^ D)に到達するまで、文字を1つずつ(ループで読み取られるように)読み取り続けます。その時点で、c!= EOFと一致し、条件が満たされないため、ループから抜け出します。実行するステートメントはもうありません。したがって、プログラムはこの時点で終了します。
これがお役に立てば幸いです。