• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:fgetsを用いたループ処理後の入力について)

fgetsを用いたループ処理後の入力について

このQ&Aのポイント
  • fgetsを用いたループ処理後の入力についての質問です。scanfでの入力が無視され、getscharの個数増加も無視される現象が起きます。解消方法を教えてください。
  • C言語のfgetsを用いたループ処理後の入力についての問題です。scanfでの入力が無視され、getscharの個数増加も無視されるという現象が起きます。解決方法を教えてください。
  • C言語でfgetsを使ったループ処理後の入力についての質問です。scanfでの入力が受け付けられず、getscharの個数増加も無視される現象が起きます。どうすれば解決できるでしょうか?

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

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★フィルタ・コマンドですか。 ・標準入力(stdin)でキーボードからの入力では必ず『改行』を含むように  注意するしかないような気がします。 ・過去に MS-DOS 用のフィルタコマンドをよく作成しましたが fgets で  『改行』コードが最終行に追加されない場合を入力の終わりと判定する  スマートな方法はないです。低水準の関数を使って直接読み取るように  すれば可能ですが移植性も考え高水準の関数を使うべきです。  元々低水準関数は処理系が高水準を実現するために用意されているだけで  プログラマに利用するようには考えられていません。 ・私の対策方法  最終行に改行コードがなくて『^Z』+『Enter』を押すとまだ入力待ちに  なるのためもう一度『^Z』+『Enter』を押して終わりと判定させるように  入力側(人間)が気をつけるようにしています。  ※ほかにもっと良い方法があれば私も乗り換えたいです。 ・OS(Windowsなど)限定で利用するならAPI関数を直接呼び出して fgets と  ほぼ同じ処理をする関数を自作すれば要求通りの動作が可能です。  あまりお勧めではありませんが方法としてはあります。  また conio.h の kbhit()、getch()関数を使って fgets 同等の関数を  作り出す方法もあります。こちらも処理系や OS によって conio.h が  用意されていない場合もありますので注意すべきです。 ・さて、どうしますか?

vtr9
質問者

お礼

暫定的には、入力画面やreadmeなどで注意を喚起し、あとは使用者に任せるしかありません。 ファイル入力への対応へ踏み切れれば、標準入力による入力方法を止め、ファイル入力のみに絞ることでエラーの発生を回避する方法を取りたいと思います。 まだ先の話ではありますが、将来的にはWin32 APIへ移行したいと思っているので、それまでは使用者に不便を強いるしかないかと。 長々と、ありがとうございました。

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

その他の回答 (3)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.3

★難しそう。 >できればこの状態でも正常に動作するようにしたいのですが、可能でしょうか?  ↑  feof()を使えば少しはマシになります。 // 実行 void execute( void ) {  char moji[ SIZE ] = { 0 };  char buff[ SIZE ] = { 0 };    //EOF(^Z)になるまで、文字列を受け取る  puts( "EOF(^Z)まで入力" );  while ( !feof(stdin) && (fgets(buff,sizeof(buff),stdin) != NULL) ){   if ( sizeof(moji) < (strlen(moji) + strlen(buff)) ) break;   strcat( moji, buff );  }  puts( "フラッシュ" );  while ( !feof(stdin) && (getchar() != EOF) ){   ;  }  puts( "一時停止" );  getchar(); //*2 これを無視して動作  puts( "抜ける" ); } これでも改行がない状態で^Zを入力するとwhile文を抜けませんが、 もう一度^Z+Enterキーを入力すると抜けるようにはなります。 feof()を使っているので『フラッシュ』のwhile文でループしません。 fgetsで標準入力から改行なしで入力の終わりと判定するのは難しそうです。 ファイルやリダイレクション入力なら正しく終わりを判定してくれますが、 標準入力(=キーボード)からは難しいので最終的に何を行いたいのかを補足して下さい。 もしかしたら別の解決策が見つかるかもしれません。

vtr9
質問者

補足

最終的には、読み込んだ文字列を元に、禁則処理を適用して原稿用紙として換算することが目的です。 読み込む文字列は、基本的にHTMLファイルのソースで、設定次第では一般的なテキスト文章も利用可能な状態です。 前者の場合、入力後にタグを除去する操作を行っております。 現段階では非対応な状況ではありますが、将来的には標準入力(stdin)とファイル入力の両方に対応できればと考えております。

すると、全ての回答が全文表示されます。
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.2

★補足 >※while文のブロック後には『;』文字は記述できません。基本でしょ。  ↑  記述は出来ますが、意図しない動作をすることがあるので注意。  『;』文字だけだとを空文として処理されます。  エラーが出ないためバグを見つけにくくなります。

vtr9
質問者

お礼

原因が分かりました。 fgetsで入力する際に、下記のように^Zの前に改行がない状態で入力していたようです。 fasdfasdfasdfas fasdfasdf^Z できればこの状態でも正常に動作するようにしたいのですが、可能でしょうか?

すると、全ての回答が全文表示されます。
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.1

★些細な記述ミスが数箇所発見。 >*2のgetscharについては、その個数を増やしても同様に無視されるようです。  ↑  無視されるとはどういう事ですか?  一時停止しないでexecute()関数を抜けるのですか? ・『お礼』『補足』に些細なミスが数箇所あります。  コンパイル時にエラーが出ませんか?  下に私がデバッグしたソースを載せておきます。 サンプル: #include <stdio.h> #include <string.h> #define SIZE 100 char moji[ SIZE ] = { 0 }; char buff[ SIZE ]; // 実行 void execute( void ) {  //EOF(^Z)になるまで、文字列を受け取る  while ( fgets(buff,sizeof(buff),stdin) != NULL ){   if ( sizeof(moji) < (strlen(moji) + strlen(buff)) ) break;   strcat( moji, buff );  }  puts( "フラッシュ" );  while ( getchar() != EOF ){   ;  }  puts( "一時停止" );  getchar(); //*2 これを無視して動作  puts( "抜ける" ); } // メイン関数 void main( void ) {  int mode, r;    for ( ; ; ){   do {    puts( "入力:" );    r = scanf( "%d", &mode );  //*1 1度目は「1」を入力    while ( getchar() != '\n' ){;}   } while ( r == 0 );      puts( "選択枠" );      switch ( mode ){  //その他選択肢あり    case 1:     execute();     break;   }  } } ※こちらでは一時停止しますけど。 原因: >*2のgetcharを無視して、*1のscanfで入力を受け付けなくなります。 これは些細な記述ミスによると思います。  間違い⇒『while(getchar() != '\n'){ };』  正しい⇒『while(getchar() != '\n'){;}』  ※セミコロンをブロック内に記述します。  ※while文のブロック後には『;』文字は記述できません。基本でしょ。 最後に:  締め切りが早すぎます。  再回答しようとしたら書き込めなかった。

vtr9
質問者

お礼

締め切りについては、申し訳ありませんでした。 サンプルで頂いたソースをC&Pの後、コンパイル、実行しましたが、 やはり*2のgetcharを無視して*1のscanfの場所で入力できなくなります。 「getcharの無視」については、「あるのにも関わらず、ない状況と同じ動作をする」という状況です。 while(~){~};については、do{~}while(~);と勘違いしていたようです。 しかしながら、while(~){~};でもコンパイルエラーは表示されなかったことを併記しておきます。

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

関連するQ&A