• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:WindowsでEOF)

WindowsでEOF

このQ&Aのポイント
  • 現在、WindowsでVC++2010Expressを使用してコードを書いています。
  • Ctrl+Z(またはCtrl+D)を押してもプログラムが停止しない問題が発生しています。
  • 質問:Ctrl+Z(またはCtrl+D)を押しても、プログラムが停止しない問題の解決方法が知りたいです。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.7

>私もそれが気になって「BackSpace」や「Delete」も試してみましたが、カウントされずに表示通りの文字数が返って来ました。 >この辺の動作が不明なのですが、「getchar()がEOF以外の値を返却した回数のカウントとなっているハズ」ではないのでしょうか? 標準入力は、通常では「バッファリング」されているので、改行がストリームを通過しないとプログラムに制御が戻りません。 「A」「B」「C」「バックスペース」「バックスペース」「^Z」「^Z」「1」「2」「3」と押しても、プログラムに返ってきません。 最後に「Enter」を押した瞬間、バッファ内の文字が整理されてから、プログラムに返って来ます。 上記の場合では、バッファ内が「A」「^Z」「^Z」「1」「2」「3」「\n」に整理されてから、プログラムに制御が戻ります。 「B」「C」「バックスペース2個」は、バッファが整理された時に削除されてしまいます。 すると、最初のgetcharには「A」が返されます。 その「A」は「EOFではない」ので、ループを繰り返します。 次にあるのは「^Z」ですが、これは「テキストモードでのファイルの終わり」なので、getcharは「ストリームが尽きた」と処理して「EOF」を返します。 この「EOF」は、通常は「文字コードに無い値」に定義されています(通常は「-1」になっている筈) 文字コードは「0~255」の筈ですから、どんな文字を入れても「-1」とは一致しません。 getcharが「EOF」を返したので、貴方のプログラムはループを終了してしまいます。 結果、上記のように入力すると、結果は「1」になるでしょう。 これは、プログラムを以下のようにすると「実感」出来ます。 #include <stdio.h> int main() { int strText; int counter=0; while( (strText=getchar() ) != EOF){ ++counter; printf("L:%d\n",counter); } printf("E:%d\n",counter); return 0; } プログラムが起動したら ABC「Enter」DEF「Enter」123ABC「BS」「BS」「^Z」「Enter」と入力してみましょう。 結果は ABC L:1 L:2 L:3 L:4 DEF L:5 L:6 L:7 L:8 123A^Z L:9 L:10 L:11 L:12 E:12 となる筈です。 「Enter」を押さない限りはプログラムに戻って来ないので、「A」「B」「C」を入力した段階では、ループの中にある printf("L:%d\n",counter); は実行されません。 そして「Enter」を押した瞬間、それまでの間にバッファに溜まった文字が「改行も1文字」としてgetcharから返って来ます。 なので「Enter」を入力した瞬間、「A」「B」「C」「\n」が順に連続で返って来て、ループ内の表示が4回連続で一気に行われます。

codingbeginner
質問者

お礼

わざわざ懇切丁寧に解説して頂いてありがとうございます!すごくわかりやすかったです。 ところで、ご示し頂いたコードをそのまま試してみたのですが、 不思議なことに、 (前略) 123A^Z L:9 L:10 L:11 L:12 L:13 となり、もう一度「^Z」「Enter」を押さねば「E:13」という出力が現れません。 これは一体どういうことなんでしょうか??

すると、全ての回答が全文表示されます。

その他の回答 (13)

  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.14

>こういうことってなかなか入門書なんかには書いてないので非常にありがたいです! 入門書レベルではそこまで深い(環境依存度の高い)ネタはやらないんでしょう。 # たとえば質問でも書かれているCtrl+DでEOFはUNIX系の場合(というかシェル?)依存ですし。 >本にはこうなりますってものと同じもの書いてもならないと、本が間違ってるのか何のか分からなくなりますからね。 著者が前提としている(あるいは動作確認した)環境が明示されていないモノは…避けた方がいいかもしれませんね。 たいていはOSやコンパイラ、バージョンなんかが明記されているかと。 最初の方に書かれているか、後ろの方の索引近くに書かれているかという違いはありますが。 # 入門書なり購入するときは明記されているか確認・納得の上で購入した方がよいでしょう。

すると、全ての回答が全文表示されます。
回答No.13

>ところで、ご示し頂いたコードをそのまま試してみたのですが、 >不思議なことに、 >(略) >となり、もう一度「^Z」「Enter」を押さねば「E:13」という出力が現れません。 >これは一体どういうことなんでしょうか?? 「^Z」の扱いについては、一部「環境依存」の部分があって、他の回答にある通り 「行頭での^ZのみEOFが返り、行頭ではない^Zは\x1aが返る」 と言う処理系と 「行頭でも、行頭以外でも^Zが現れた時点でEOFが返る」 と言う処理系があります。 なので、Visual Studioのデバッグ画面で試さず、リリース版exeを作ってからコマンドプロンプトで実行して試すと、結果が変わる可能性があります。 因みに、当方が試した環境は、後者の「^Zが現れた時点でEOFが返る」のタイプでした。

codingbeginner
質問者

お礼

なるほど~。色々と環境の影響があるんですね。。 こういうことってなかなか入門書なんかには書いてないので非常にありがたいです! 本にはこうなりますってものと同じもの書いてもならないと、本が間違ってるのか何のか分からなくなりますからね。

すると、全ての回答が全文表示されます。
回答No.12

#7へのお礼の中の疑問 > もう一度「^Z」「Enter」を押さねば「E:13」という出力が現れません。 OSの仕様か、Visual Studioの仕様かわかりませんが、Ctrl+Zが入力行の先頭にないとEOF(値は-1)は返ってきません。行の途中に入れると値0x1aが返ってきます。また、Ctrl+Zに続けて文字を入力させようとしても、その行のCtrl+Zより後の文字は改行文字を含めて破棄されてしまいます。

すると、全ての回答が全文表示されます。
  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.11

>その辺を制御したいならOS依存になるはずですがWindowsだとどうするんだろ。 そこまで行くとWindowsAPIでしょうか……。 http://msdn.microsoft.com/ja-jp/library/cc429744.aspx なんての見つけましたけど……。 GetStdHandle()でハンドルを取得、GetConsoleMode()で現在のモードを取得して、 ENABLE_LINE_INPUTのフラグを落としてSetConsoleMode()で設定…でしょうか……。 APIで変更した内容がCランタイムライブラリの方に影響を与えるかどうか?に関しては疑問ですが。 # ランタイムの方の行バッファも無効にする必要がありますかねぇ…。 って、置いてけぼりとか言いつつ続けてしまう私。 # さすがに試してまではいない。 # コンソール上で動作するゲームでも作らないと行バッファとか問題にならない…でしょうし。

codingbeginner
質問者

補足

途中から全然付いて行けてない質問主ですけど、どうぞお気になさらずプロの方同士で心ゆくまでディスカッションして下さい!

すると、全ての回答が全文表示されます。
  • wormhole
  • ベストアンサー率28% (1626/5665)
回答No.10

バックスペースやデリートで編集できるのは、(Cライブラリの)標準入力の行バッファリングではなく、OS側の行バッファリングの話かと。 なので、その辺を制御したいならOS依存になるはずですがWindowsだとどうするんだろ。

すると、全ての回答が全文表示されます。
  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.9

>それとも, VisualStudio の統合環境から? でした。 というか面倒だったのでreturnにブレークポイント置いた。 まぁ本筋から逸れていってます……かね? コンソール(CUI)使うことはほとんど無いしなぁ。 # 最近はC#使うことが多いし。 なんか質問者さん置いてけぼりにしている感が……。

すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.8

OS レベルでバッファリングされると, そうなっちゃいますね>#6. もともとそこは C言語レベルではど~しよ~もないわけで, 実行環境に依存した方法を使わざるを得ない. 例えば, Windows 環境なら conio.h とか? あと, どうやってプログラムを実行していますか? コマンドプロンプトから実行してる? それとも, VisualStudio の統合環境から? はたまた, それら以外の何か?

すると、全ての回答が全文表示されます。
  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.6

どうやらそのようで…>#5 #include <stdio.h> int main() {  int strText;  int counter=0;  while( (strText=getchar() ) != EOF){   ++counter;  }  printf("\nCount=%d\n", counter);  setvbuf( stdin, NULL, _IONBF, BUFSIZ );  counter=0;  while( (strText=getchar() ) != EOF){   ++counter;  }  printf("\nCount=%d\n", counter);  return 0; } とか、書いて試してみましたが動作は変わらず。 http://support.microsoft.com/kb/45563/ja コンソール相手だと効かない…ってことですかねぇ。 # リダイレクトは試していない。 そんな訳で、#4はちょっと的外れな回答となってしまいました。

codingbeginner
質問者

お礼

いえいえ、とんでもない。試して頂いてありがとうございます!

すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

標準入力が行バッファリングになってると「バックスペース」とか「デリート」とかで修正できるので, 「押したキーの数」と「実際に読み込んだ『文字』の数」とは異なりますね. 標準入力が端末に割り当てられている場合は行バッファリングだったような気がする.

codingbeginner
質問者

お礼

ありがとうございます。 好奇心からの質問ですが、標準入力を行バッファリングから文字単位でバッファリングする方法もあるのでしょうか?

すると、全ての回答が全文表示されます。
  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.4

>ところで、(仕様にもよるでしょうが)何も言われていない場合であれば通常キャラクタのカウントにはスペースやタブ、改行は含めるのでしょうか? コード次第…でしょう。 なお、掲示されているコードは「入力した文字のカウント」ではなく「getchar()がEOF以外の値を返却した回数のカウント」となっているハズです。 # gets()やscanf()などとは違い、「BackSpace」や「Delete」も1文字としてカウントするでしょうし。 仕様と言っているのは「getchar()が戻ってくる際の仕様」かと。 たいていgetc(stdin)のマクロになっていると思われますので、そちらの仕様次第…と。

codingbeginner
質問者

補足

>「BackSpace」や「Delete」も1文字としてカウントするでしょうし。 私もそれが気になって「BackSpace」や「Delete」も試してみましたが、カウントされずに表示通りの文字数が返って来ました。 この辺の動作が不明なのですが、「getchar()がEOF以外の値を返却した回数のカウントとなっているハズ」ではないのでしょうか?

すると、全ての回答が全文表示されます。

関連するQ&A