
http://oshiete1.goo.ne.jp/qa3853689.htmlにて質問した内容ですが、
想定していたソースの範囲内では解決しないことが分かりましたので、新規に立てさせていただきます。
下記でfgetsを使って入力した後についてですが、*2のgetcharを無視して、*1のscanfで入力を受け付けなくなります。
*2のgetscharについては、その個数を増やしても同様に無視されます。
これを解消する方法はないでしょうか?
ちなみにコンパイラはBBC、開発環境はVistaです。
なお、簡略のため#includeなどは省略しています。
#define SIZE 16384
void main(void){
int mode,r;
while(1){
do{
r = scanf("%d", &mode); //*1 return後に停止
while(getchar() != '\n'){ };
}while(r == 0)
switch(mode){ //その他選択肢あり
case 1:
execute();
break;
}
}
return;
}
void execute(void){
char moji[SIZE];
char buf[SIZE];
while(fgets(buf, sizeof(buf), stdin) != NULL){
if(sizeof(moji) < strlen(moji) + strlen(buf))
break;
strcat(moji, buf);
}
while(getchar() != EOF){ }
getchar(); //*2 これを無視して動作(scanfでも同様)
return;
}
No.4ベストアンサー
- 回答日時:
★フィルタ・コマンドですか。
・標準入力(stdin)でキーボードからの入力では必ず『改行』を含むように
注意するしかないような気がします。
・過去に MS-DOS 用のフィルタコマンドをよく作成しましたが fgets で
『改行』コードが最終行に追加されない場合を入力の終わりと判定する
スマートな方法はないです。低水準の関数を使って直接読み取るように
すれば可能ですが移植性も考え高水準の関数を使うべきです。
元々低水準関数は処理系が高水準を実現するために用意されているだけで
プログラマに利用するようには考えられていません。
・私の対策方法
最終行に改行コードがなくて『^Z』+『Enter』を押すとまだ入力待ちに
なるのためもう一度『^Z』+『Enter』を押して終わりと判定させるように
入力側(人間)が気をつけるようにしています。
※ほかにもっと良い方法があれば私も乗り換えたいです。
・OS(Windowsなど)限定で利用するならAPI関数を直接呼び出して fgets と
ほぼ同じ処理をする関数を自作すれば要求通りの動作が可能です。
あまりお勧めではありませんが方法としてはあります。
また conio.h の kbhit()、getch()関数を使って fgets 同等の関数を
作り出す方法もあります。こちらも処理系や OS によって conio.h が
用意されていない場合もありますので注意すべきです。
・さて、どうしますか?
暫定的には、入力画面やreadmeなどで注意を喚起し、あとは使用者に任せるしかありません。
ファイル入力への対応へ踏み切れれば、標準入力による入力方法を止め、ファイル入力のみに絞ることでエラーの発生を回避する方法を取りたいと思います。
まだ先の話ではありますが、将来的にはWin32 APIへ移行したいと思っているので、それまでは使用者に不便を強いるしかないかと。
長々と、ありがとうございました。
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で標準入力から改行なしで入力の終わりと判定するのは難しそうです。
ファイルやリダイレクション入力なら正しく終わりを判定してくれますが、
標準入力(=キーボード)からは難しいので最終的に何を行いたいのかを補足して下さい。
もしかしたら別の解決策が見つかるかもしれません。
この回答への補足
最終的には、読み込んだ文字列を元に、禁則処理を適用して原稿用紙として換算することが目的です。
読み込む文字列は、基本的にHTMLファイルのソースで、設定次第では一般的なテキスト文章も利用可能な状態です。
前者の場合、入力後にタグを除去する操作を行っております。
現段階では非対応な状況ではありますが、将来的には標準入力(stdin)とファイル入力の両方に対応できればと考えております。
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文のブロック後には『;』文字は記述できません。基本でしょ。
最後に:
締め切りが早すぎます。
再回答しようとしたら書き込めなかった。
締め切りについては、申し訳ありませんでした。
サンプルで頂いたソースをC&Pの後、コンパイル、実行しましたが、
やはり*2のgetcharを無視して*1のscanfの場所で入力できなくなります。
「getcharの無視」については、「あるのにも関わらず、ない状況と同じ動作をする」という状況です。
while(~){~};については、do{~}while(~);と勘違いしていたようです。
しかしながら、while(~){~};でもコンパイルエラーは表示されなかったことを併記しておきます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# C言語で再起関数とポインタを用いて文字列反転をする方法がわかりません。 4 2023/04/29 20:32
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# #include <stdio.h>int main(void) { int buf[100] = 6 2022/11/01 22:45
- C言語・C++・C# leetcode 155 minstack 1 2022/05/07 16:43
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Eclipseコンソール表示を、リセ...
-
数字以外が入力されたらエラー...
-
java初心者です。入力されたの...
-
scanfが2回使えない・・・?;
-
C言語・YesNo入力のループで解...
-
正負を反転させて出力するプロ...
-
getchar()について 教えてくだ...
-
"scanf"でエンターで改行させな...
-
コマンドプロンプトからのEOFの...
-
至急教えてください!プログラ...
-
*をユーザーが入力した数字の数...
-
scanf関数 バッファに残ったエ...
-
入力候補を表示させるには・・・?
-
EDITコントロールで入力できる...
-
Excel VBAで、Application.Inpu...
-
入力値が1以下、かつ数字以外の...
-
WindowsでEOF
-
電卓の小数点
-
getcharをしながらwhile文で出...
-
ワードで文字を入力する時の変...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
正負を反転させて出力するプロ...
-
プログラミング初心者です。 Py...
-
数字以外が入力されたらエラー...
-
Excel VBAで、Application.Inpu...
-
EDITコントロールで入力できる...
-
*をユーザーが入力した数字の数...
-
Linuxプログラミングで、キーボ...
-
Eclipseコンソール表示を、リセ...
-
入力候補を表示させるには・・・?
-
batプログラム上で文字列を入力...
-
UWSCで変数をキー入力
-
VisualStudio2019のコードアナ...
-
小数か整数かを判定する方法
-
scanfが2回使えない・・・?;
-
Linuxで入力待ちなしkeyread関...
-
java初心者です。入力されたの...
-
Delphi初心者 ボタン操作につ...
-
コマンドプロンプトからのEOFの...
-
Eclipseでコマンドラインを入力...
-
Userformの入力順序をタブオー...
おすすめ情報