- ベストアンサー
gets fgetsについて
対話式のプログラムを作成したのですが、fgetsのところで勝手に文字が入力されてるような処理になってしまい、こちら側から入力できません。 fgetsのところで通常通り入力できるようにするにはどうしたら良いのでしょうか? コードは以下のとおりです。 #include <stdio.h> #include <string.h> main() { int kazu; char sentaku[1]; char string[10]; printf("文字を入力してください\n"); /*文字入力要求のメッセージ*/ fgets(sentaku,1,stdin); /*確認時にenterを読み込まないようにfgetsで文字取得*/ sscanf(sentaku,"%d",&kazu); putchar(sentaku[1]); /*putcharを使ってmojiを画面出力*/ putchar('\n'); /*改行コードを出力*/ printf("ここから先に進みますか?-Y/N->\n"); fgets(sentaku,1,stdin); /*確認時にenterを読み込まないようにfgetsで対話する*/ sscanf(sentaku,"%d%",&kazu); if(sentaku[0]==121) /*入力した文字がyだった場合*/ { strcpy(string,"spring\n"); /*strcpyを使って変数に代入*/ putchar(string[0]); /*putcharを使って画面出力*/ putchar(string[1]); putchar(string[2]); putchar(string[3]); putchar(string[4]); putchar(string[5]); } }
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
fgets() は、「第2引数で指定した文字数-1」分だけ入力ストリームから読み込んで、その後ろに '\0' を付加します。 ですので、第2引数に 1 と指定した場合には、1-1=0 文字分、つまり一文字も読み込まずに処理をすり抜けることになります。 たとえば、以下のようなコードを書いたとしましょう。 -------------------------------------------------------- char hoge[256]; fgets( hoge, 5, stdin ); -------------------------------------------------------- ここで標準入力から「abcdefg[ENTER]」と入力した場合、hoge[] には { 'a', 'b', 'c', 'd', '\0' } が設定されます。 また、標準入力から「hij[ENTER]」と入力した場合、hoge[] には { 'h', 'i', 'j', '\r', '\0' } が設定されます。 # どうしてこのようになるのかは、ご説明するまでもありませんよね? ですので、「/*確認時にenterを読み込まないようにfgetsで文字取得*/」というコメントから判断すると、この場合には入力文字数を 1 から 2 にすれば良いことになります。 # 変数 sentaku[] の配列要素数も増やすことをお忘れなく。。。 あと、一つ気になったのが「121」という数字です。 この場合、小文字の 'y' を意味しているのであれば、 if(sentaku[0]=='y') …… としたほうが良いです。 ま、今回のご質問とは関係ない話ですけど。。。
その他の回答 (5)
- KAZUMI2003
- ベストアンサー率37% (77/208)
No3のものです。何度もすみません。 >また、私の書いたinput関数は、戻り値がintにもかかわらず、charを返しています。本当は0か1を返すようにするつもりでした。 は、さらに私の勘違いでした。 ごめんなさい。
- KAZUMI2003
- ベストアンサー率37% (77/208)
すみません、No3の者です。 みっとも恥ずかしいことにいくつか間違ってしまいました。 fgetsに渡す引数としての文字数は、\0の分はいらないし、'\n'の分も勿論入れなくてもOKです。 また、私の書いたinput関数は、戻り値がintにもかかわらず、charを返しています。本当は0か1を返すようにするつもりでした。 混乱させてしまったら、すみません。
- KAZUMI2003
- ベストアンサー率37% (77/208)
私の環境の解説によると、fgets関数は以下のように動作します。 /* char *fgets(char *s, int n, FILE *stream); 解説 ストリームから文字列を取得します。 fgets は,stream から文字を読み込んで文字列 s に格納します。読み込みは n-1 個の文字を読み込むか,または改行文字を読み込んだときに終了します。改行文字で終了した場合には fgets は,s の最後に改行文字を格納します。s に読み込まれた文字の最後にはヌルターミネータが付加されます。 */ ですから、\0の分の+1に加え、改行文字の分を指定するのが正しいと思います。もちろんメモリもそれだけ確保する必要があります。また、改行文字を除去するのには、処理系依存にしなくても、fgetcあたりを使って、別関数にするのかよいと思います。 たとえば、 int input(char *buffer,int n , FILE *stream){ int i,c; for( i=0; i<n; i++){ c=fgetc(stream); if((c=='\n') || (c=='\0')){ *buffer='\0'; return 1; } *buffer++=c; } *buffer='\0'; return 1; } こんな感じでしょうか? 前述したように、 >char sentaku[1]; は、一文字分じゃ少なすぎで、リターンを打った時点でメモリをはみ出してしまいますし、 >putchar(sentaku[1]); /*putcharを使ってmojiを画面出力*/ は,sentaku[0]じゃないかと思います。 がんばって、C言語における文字列の扱いを習得してください。
たしかfgetsは文字列の最後に\0を付ける とかいうことをしてたはずです。 ですので\0を含めた2を指定したらいけるのでは?
- TT414
- ベストアンサー率18% (72/384)
>fgets(sentaku,1,stdin); は意味がありません、1から1を引いた0文字しか読みません、1文字も読まずに処理を続けます。 enterを読まずに処理をするには、処理系依存の関数で入力するしか方法はありません。 OS名、コンパイラー名を詳細に記述してください。