frontriver さんが書きました: ↑5年前
こちらで大学に提出しました。
提出してしまったんですね。
不具合がいくつかあると思うんですが。
・Enter だけを入力すると、終了してしまう。
・79文字入力してから Enter を入力すると、終了してしまう。
・78文字や、80文字、81文字だと Enter を入力しても終了せずに次の入力を待つ。
frontriver さんが書きました: ↑5年前
実行結果は文字列を81個入れてenterを押し79個の文字列と改行されて2個の文字列が出ました。その後ctrl+Dを押すと綺麗に終了できます。
Ctrl+D の代わりに Enter でも終了してしまいますよね。
いいんでしょうか?
#2 にも書きましたが、mygets の return sp; の前に
if (i == 0 && c == EOF) return NULL; を追加し、main で、
while (mygets(buf, 80)) puts(buf); とすれば
main で、Enter と Ctrl+D の区別ができるでしょう。
ここまでいいですか? 理解できますか?
frontriver さんが書きました: ↑5年前
一方で、このソースの中には記録されていませんが文字列を81個入れてenterではなく、ctrl+Dを入力すると行替されずに79個の文字列が出てしまい、あたかも160個の文字列のようになってしまいます。その後改行されて2個の文字列が出ました。
これは'\n'があるのでenterでも実行できると言うことなのでしょうか?
正確な情報をお願いします。
81文字と Ctrl+D の入力で、入力の 81文字と出力の79文字が連続して
表示されて改行もされますが、2個の文字はこの時点では表示されません。
次に、Enter を入力すると、2個の文字が表示され改行します。
それでは、行頭ではない Ctrl+D について詳しく説明します。
Enterキーは通常 0x0d ('\r') のコードですが、
どこかで 0x0a ('\n') に変換されて getchar がそれを返します。
Ctrl+D のコードは通常 0x04 ですが、
これが EOF に変換されるのではありません。
EOF は 1バイトの値ではなく、int の -1 です。
getchar() は getc(stdin) または fgetc(stdin) と同じです。
stdin は標準入力であり、FILE構造体へのポインタです。
FILE構造体の中には入出力をバッファリングするバッファがあります。
標準入力バッファが空の時に getchar が呼ばれると、
まずそのバッファに文字を入力するために
システムコールの read を呼び出します。
標準入力は端末ドライバに接続されていて、
OS内のキーボード入力バッファが使用されます。
「標準入力バッファ」と「キーボード入力バッファ」の
2個所でバッファリングが行われているのです。
キー入力は、まずキーボード入力バッファにため込まれます。
だから、Backspace で入力文字の削除もできるのです。
キー入力がすぐに getchar に反映されるのではありません。
Enterか、Ctrl+D が入力されたときに、キーボード入力バッファの
文字列が標準入力バッファに転送されて、read の処理が完了します。
Enter は '\n' の文字としてそこに入っていますが、Ctrl+D は
文字としては入っていません。
行頭での Enter入力は、'\n' 1文字が転送され、read は 1 を返します。
行頭での Ctrl+D入力は、読み込み文字数 0 が read の返す値となります。
getchar は、read による読み込み文字数が 0 の場合に EOF を返すのです。
行頭ではない Enter入力は '\n' も含めた 1行分の文字列が転送されます。
行頭ではない Ctrl+D入力は '\n' を含まない 1行分の文字列が転送されます。
いずれも場合もバッファには文字があるので、getchar はそれを返し、
EOF を返すことはありません。
標準入力バッファが空でない時に getchar が呼ばれると、
バッファ内の文字列の先頭の文字が返されるだけです。
何度も getchar が呼ばれて、バッファが空になると、
次の getchar では、readシステムコールを呼び出し、
キー入力待ちになるのです。
さて、81文字と Ctrl+D を入力すると、81文字が標準入力バッファに
転送されます。getchar は 81回実行されますが、
79回実行したところで、mygets は i が size-1 になるので
while ループを break し、main に返って、puts(buf) で
その 79文字と改行が出力されるのです。
また mygets が呼ばれて、getchar を 2回実行したところで
buf[0] と buf[1] にその文字が入ります。
次の getchar は標準入力バッファが空なので、read を呼び出し、
キーボード入力バッファに文字をため込むためにキー入力待ちになります。
ここで Enter を入力すると、それはキーボード入力バッファに入り、
標準入力バッファに転送され、getchar が '\n' を返し、
mygets は終了し、main で 2文字を改行を出力します。
ちょっとややこしいですが、理解していただけますか?