• ベストアンサー

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]); } }

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

  • ベストアンサー
  • ency
  • ベストアンサー率39% (93/238)
回答No.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)

回答No.5

No3のものです。何度もすみません。 >また、私の書いたinput関数は、戻り値がintにもかかわらず、charを返しています。本当は0か1を返すようにするつもりでした。 は、さらに私の勘違いでした。 ごめんなさい。

回答No.4

すみません、No3の者です。 みっとも恥ずかしいことにいくつか間違ってしまいました。 fgetsに渡す引数としての文字数は、\0の分はいらないし、'\n'の分も勿論入れなくてもOKです。 また、私の書いたinput関数は、戻り値がintにもかかわらず、charを返しています。本当は0か1を返すようにするつもりでした。 混乱させてしまったら、すみません。

回答No.3

私の環境の解説によると、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言語における文字列の扱いを習得してください。

noname#16765
noname#16765
回答No.2

たしかfgetsは文字列の最後に\0を付ける とかいうことをしてたはずです。 ですので\0を含めた2を指定したらいけるのでは?

  • TT414
  • ベストアンサー率18% (72/384)
回答No.1

>fgets(sentaku,1,stdin); は意味がありません、1から1を引いた0文字しか読みません、1文字も読まずに処理を続けます。 enterを読まずに処理をするには、処理系依存の関数で入力するしか方法はありません。 OS名、コンパイラー名を詳細に記述してください。

関連するQ&A

  • fgetsについて

    いつも大変お世話になっております。 またしても基本的なことで恐縮ですが、教えてください。 『fgets()』を使って、標準入力ファイル(stdin)からの情報を読み込む場合、指定されたサイズ以上を入力すると、サイズを超えた部分が切捨てられて最後に'\n'が自動的に付加されると学習しました。 しかし、切り捨てられた部分はまだstdinに残るため、次回の利用でおかしな結果を招くようです。 そこで、stdinのバッファをクリアたほうが良いと思ったのですが、方法が分かりません。 どのようにすればよいでしょうか? 【例】 #include<stdio.h> #include<string.h>     char name[5]; printf("文字列を入力して下さい。>>"); fgets(name,sizeof(name)-1,stdin); printf("読み込み文字列:%s\n",name); このとき、キーボードから4文字入力するとstdinのバッファに'\n'が残ってしまい、5文字以上だと4文字目以降の文字と'\n'が残ってしまうようです。 また、最後に'\0'が付与されるなら、サイズ以上が切捨てられた際もname[4]に'\0'を代入しなくてもいいということでよいのでしょうか? 乱文になってしまい、申し訳ありません。 どうぞ教えてください。

  • fgets

    c言語初心者です。 char s[20]; fgets(s,20,stdin); printf("%s",s); のようなプログラムで、 20以上の入力をしたらエラーしますよね? それをもし入力したとしてもエラーしないで、20文字出力させるようにしたいのですが何か方法はありますか? いろんなサイトを見たり本を読んでもわかりません。 ちなみにlinuxで使いたいです。

  • fgetsとsscanf

    C言語の勉強をしております。 初歩的な質問なのかもしれないですが、 char buf[80]; char data[32]; fgets(buf,sizeof(buf),stdin); sscanf(data, "%s", buf); と、 fgets(data, sizeof(buf), stdin); は何が違うのでしょう? 他の質問内容やネットで探してみたんですが、基本的には組み合わせて使用されているみたいなんですが、必要性がわかりません・・・。 例えば、fgetsで構造体のメンバ(文字配列)へキーボードからデータを入力したい場合は、どちらで行うのが良いのでしょう? また、入力データが未入力かどうか判断させるには、 fgets(buf,sizeof(buf),stdin); if(buffer[0] == '\n'){   /* ループを抜ける */   break; } で良いですよね? ※関連している質問 http://oshiete1.goo.ne.jp/qa4438371.html あと、同じ処理内で、getsやscanfを混同して使用すると、どこかの入力時に改行がバッファに残ってしまい、入力処理が飛ばされてしまいますか? 以上、よろしくお願いいたします。

  • scanfの後のfgetsについて

    #include <stdio.h> int main(void) { char name[10]; int no; printf("ナンバーを入力してください: "); scanf("%d",&no); /* 35を入力 */ printf("文字列を入力してください: "); fgets(name,10,stdin); /*入力できない*/ return 0; } この例文だと、fgets関数が改行コードを読み取って、終了してしまい文字列入力が出来ないみたいなんですが、scanfの後にfgetsを使うような(scanfとfgetsの間にscanfの残した?改行コードを取り除く方法)処理はどのような方法があるのでしょうか? 試しにfgets文を2度書いたら思っていた動作をしてくれたのですが、はたしてfgets文を2度書くというような事をしていいものなのでしょうか?見た目もなんだか変な感じですし。。↓ #include <stdio.h> int main(void) { char name[10]; int no; printf("ナンバーを入力してください: "); scanf("%d",&no); /* 35を入力 */ printf("文字列を入力してください: "); fgets(name,10,stdin); fgets(name,10,stdin);  /*入力できる*/ return 0; }

  • fgetsとsscanfの使い方

    初歩的な質問で申し訳ないのですが、fgetsとsscanfの使い方が合っているか確認願います fgets(char *s , int n ,FILE *fp); -> fpから1行(nで指定した文字数)読み込み、sに格納する sscanf(char buf, "%s", char string); -> bufから%sを読み込み、stringに格納する まだ使い慣れていないのでどっちから読み込むのかこんがらがってます 上記の解釈でよろしいのでしょうか?

  • 助けてください。

    C言語の勉強をしているのですがうまくいきません。 助けてください。 氏名、誕生日、血液型を入力し表示する関数を作りたいです。 形としては、氏名を入力し、誕生日を入力したあとに血液型を入力する関数ですが、血液型入力を下の表を表示して選択式にしたいのです。 --------------------------- 番号を入力してください 1;A 2;B 3;O 4;AB 5;? --------------------------- ここで仮に1を入力します。 最終的に入力したものが -------------------- 名前:taro 誕生日:19830917 血液型:A -------------------- と表示されるようにしたいです。 そのための関数を作ったのですが、うまく作動しません。 どこがおかしいか教えてください。 関数はこれです。 #include<stdio.h> #include<string.h> #include<stdlib.h> int main(void) { char Buff[20]; char Buff2[9]; char Buff3[5]; char Buff4[5]; int i; char BLOODNAME[5][4] = {"A","B","O","AB","?"}; printf("名前:"); fgets(Buff,20,stdin); printf("生年月日:"); fgets(Buff2,9,stdin); i = atoi(Buff2); printf("血液型を選べ\n"); printf("------------------------------------\n"); printf("1;A 2;B 3;O 4:AB 5;?\n"); printf("------------------------------------\n"); fgets(Buff3,5,stdin); if(strlen(Buff3) == 1) { switch(Buff3[0]) { case 1: strcpy(Buff4,BLOODNAME[0]); break; case 2: strcpy(Buff4,BLOODNAME[1]); break; case 3: strcpy(Buff4,BLOODNAME[2]); break; case 4: strcpy(Buff4,BLOODNAME[3]); break; case 5: strcpy(Buff4,BLOODNAME[4]); break; default: printf("強制終了ver1\n"); return 0; } } else { printf("強制終了ver2\n"); return 0; } printf("----------------------------------------\n"); printf("名前:%s\n",Buff); printf("生年月日:%d\n",i); printf("血液型:%s\n",Buff4); printf("----------------------------------------\n"); return 0; } あと誕生日なのですが今は入力したものがそのまま出力されますが、最終的には○○○○年○○月○○日と表示されるようにしたいのですが、上の関数にどう追加すればいいのかも教えてください。 お願いいたします・

  • fgets関数を使用したときの文字あふれについて

    fgets関数を用いて文字列を入力し、その長さを測るプログラムを作っています。 #include <stdio.h> #include <string.h> #define MAX 256 int main ( int, char *[] ); int main ( argc, argv ) int argc; char *argv[]; { char buf[( MAX )]; while ( 1 ){ memset ( buf, 0, sizeof( buf )); fgets ( buf, MAX, stdin ); if( fgets == NULL ){ break; } printf("入力した文字列の長さは%dです\n" ,strlen( buf )); } return 0; } このプログラムでは、256までしか文字列の長さを測ることができません。 もしこのプログラムで256を超える文字列を入力してしまうと、文字のあふれが発生し、 「入力した文字列の長さは256です」 「入力した文字列の長さは(あふれた文字列の長さ)です」 とこのようになってしまいます。 このプログラムで256以上の文字を読み捨てて、 「入力した文字列の長さは(あふれた文字列の長さ)です」 を表示しないようにできるのでしょうか? また読み捨てた文字列の長さを知ることはできるのでしょうか? もしかしたらfgets関数を使用すると不可能なのではないか?と思っています。 分かる方が居ましたらどうか教えて下さい。 よろしくお願いします。

  • fgets, sscanf, バッファ、ストリーム について

    ファイルからデータを入力するのに、fscanf の代わりに fgets と sscanf を用いようと考えています。 そこで、sscanf に与えるバッファ文字列を、ファイルストリームのように扱う方法は無いものでしょうか。 例えば以下のデータファイルに対して、以下のプログラムをうまく動作させるには、どのようにすればよいでしょうか。 どうぞ、よろしくお願いします。 (データファイル test.dat) n_data 4 1 3 8 4 (プログラム) #include <stdio.h> main() { int i, n_data, *data; char buf[100]; FILE *fp; fp = fopen ( "test.dat", "r" ); fgets(buf, 100, fp); sscanf( buf, "n_data %d\n", &n_data ); data = (int *)malloc( n_data * sizeof(int) ); for( i=0; i<n_data; i++ ){ fgets(buf, 100, fp); sscanf( buf, "%d", &(data[i]) ); } sscanf( buf, "\n" ); close( fp ); printf( "n_data %d\n", n_data ); for( i=0; i<n_data; i++ ) printf( " %d", data[i] ); printf( "\n" ); } ちなみに、2行の fgets(buf, 100, fp); をコメントアウトして、 "sscanf( buf," を "fscanf( fp," に変更するとうまく動作します。

  • C++におけるfgets??

    文字列を入力するときに用いるfgets関数ですが、 C++において fgets(char *,n,stdin) と同等の動作をする関数を教えてください。 よろしくお願いします。

  • c言語のscanfとfgetsについて

    2つの単語A, Bを入力して、AがBに含まれるか否かというプログラムで 以下のようなものを作成しました。 そこで質問なのですがscanf()をfgets()に変えるとうまく動作しません どこが間違ってますか? 変更したいfgets fgets(key, sizeof(key), stdin); fgets(word, sizeof(word), stdin); ------------------------------------------------- int main(void) { char key[101], word[101]; scanf("%s", key); scanf("%*c%s", word); if (strstr(word, key) != NULL) { printf("Find %s In %s\n", key, word); } else { printf("Not Find\n"); } return 0; }

専門家に質問してみよう