• ベストアンサー

fgetsなどのときのstdinのバッファを消すには?

こんにちは,今C(C++でない)を使用しています。 たとえば, char str[20] fgets(str,sizeof(str),stdin) としたときに20字以上を打つと,stdinのバッファに20字以上の分が残ったままになります。 C++などでは fflush(stdin)で,うまくいきますが,普通のCでは対応がされていないみたいでうまくいきません。 よろしくお願いします。

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

  • ベストアンサー
  • Fooky
  • ベストアンサー率71% (59/82)
回答No.4

あ,テキスト入力だからこんな大掛かりなことしなくてもいいんだ. 末尾に'\n'が出るまで掃出せばいいんですよね. fgets(str, sizeof(str), stdin); if ( str[strlen(str)-1] != '\n' ){ while( getchar() != '\n' ); } でいいんだ.失礼しました.

yu393939
質問者

補足

ありがとうございます。かなりのヒントになりました。 お礼のついでに完成したのを載せておきます。 #include <stdio.h> #include <string.h> int main() { char str[20]; int chk_digit; while(1) { chk_digit=0; puts("入力"); fgets(str, sizeof(str), stdin); if ( str[strlen(str)-1] != '\n' ) { while( getchar() != '\n' ); chk_digit=1; } if (chk_digit == 1 || str[0] == '\n' ) { break; } } printf("出力:%s\n",str); return 0; }

その他の回答 (3)

  • Fooky
  • ベストアンサー率71% (59/82)
回答No.3

システムは何ですか?fseek(stdin, 0, SEEK_END, 0)はLinuxでは効かないという話を読んだことがあります.SEEK_ENDをEOFと考えれば当然ですが.fseekでいけるシステムではSEEK_ENDを現状でのバッファエンドと捉えているんでしょうか. で,おおがかりになってきますが,pollまたはselectを使って全部掃出すのはどうでしょう? #include <stdio.h> #include <sys/poll.h> int main(int argc, char **argv) { char s[11], ss[11]; struct pollfd fdlst = {0, POLLIN, 0}; int l; l = read(0, s, 10); /* sに文字列読込み*/ s[l] = 0; /* 掃出し */ do { fdlst.revents = 0; poll( &fdlst, 1, 1 ); } while ( (fdlst.revents&POLLIN) != 0 && read(0,s,10) > 0 ); /* ssに文字列読込み*/ l = read(0, ss, 10); ss[l] = 0; printf("%s", ss); } こうするとうちでは,sに何文字打とうと,それ以降に打った文字がssに入りました.ただし,pollはファイルポインタ(stdin)ではなくファイルディスクリプタ(0 = stdin)を使うので,読込みもそれに合わせてreadなどのシステムコールでやる必要があるようです. #しかし私はfflush(stdin)に驚きでした.それでいけるシステムもあるんですね.

参考URL:
http://www.linux.or.jp/JM/html/LDP_man-pages/man2/poll.2.html
yu393939
質問者

お礼

早速のお答えありがとうございます。 ただ,これを私のPCでコンパイルしようとすると, (#include <unistd.h>を加えて・・) [XXXXXXXX]$ gcc -g -Wall -o test test.c [XXXXXXXX]$ ./test abcdefghijk      (←1回目に打った内容) abcdefghijk      (←2回目に打った内容) abcdefghij[XXXXXXXXX]$ k -bash: k: command not found [XXXXXXXX]$ となり,1回目の入力は11文字以上がうけつけなく,サイドの入力の際は10文字だけが出力され後の一文字(k)がこのプログラムが終了したシステムのコマンドとして認識されるようになりました。 どうしたらいいでしょうか。

noname#4252
noname#4252
回答No.2

fseek(stdin, 0, SEEK_END); 試してませんが。 他には、バッファが空になるまで読み捨てるとか。

yu393939
質問者

お礼

こんにちわ, それも,fssekも無理だったんですよ。 char str[20]; fseek(stdin, 0, SEEK_END); if ((*fgets(sk,sizeof(sk),stdin) < 0x21) || strlen(sk) >= 21 ) { puts("error"); goto start1; } のようにしたんですけど,むりでした。

  • 100Gold
  • ベストアンサー率27% (284/1018)
回答No.1

fflushはCの標準関数のはずです。 上手く行かないのには別の原因があるのではないでしょうか?

yu393939
質問者

お礼

いや,ANSI C規格では、 「fflush関数は出力ストリーム(stdoutとかstderr)にしか使えないように定義されている」 参照:http://www.peke.jp/archive/fmc/article/dev/dev001b.html らしいんですよ。ですから, fflush(stdout) はできても, fflush(stdin) はできないみたいなんです。

関連するQ&A

  • 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を混同して使用すると、どこかの入力時に改行がバッファに残ってしまい、入力処理が飛ばされてしまいますか? 以上、よろしくお願いいたします。

  • 入力されたとき,何も入力しない,もしくは20字以上だと再入力のプログラム??

    こんにちわ, 今Cの勉強をしているんですが,入力をして,何も入力しないもしくは20字以上だと再入力させるのプログラムを作りたいんですけどどうしたらよろしいでしょうか。 char sk[21]; start1: while(stdin = " puts("入力"); if ((*fgets(sk,sizeof(sk),stdin) < 0x21) || strlen(sk) >= 21 ) {   puts("error");   goto start1; } だと,20字以上のときにstdinのバッファに残ってしまってエラー表示が2度出ます。 ちなみにfflush(stdin)は使用できないANSI C規格です。 よろしくお願いします。

  • 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 fi[50]; int r; fgets( fi, 50, stdin ); r = atoi( fi ); ################################ fgets( fi, 50, stdin );のとこで 50とstdinはどういう意味ですか? 50は50バイト以上でなくてはいけません、という意味ですか? よろしくお願いします。

  • fgetsで配列に数字を入れる。

    C言語についての質問です。 配列の中にひとつずつ数字を入れたいと思っています。 char suuzi[16]; fgets(suuzi, sizeof(suuzi), stdin); のような感じで読み込ませてるのですが、数字で読み込まれず文字として読み込まれてるみたいです。 数字として配列にひとつずついれるにはどのようにしたらよいかどなたか教えてください。

  • fgetsでバッファ残留文字列を無視して読み込む

    お世話になります。 早速質問させていただきます。 言語はC++です。 ファイルに、以下の文字列があったとします。 ============================ 123456789012 12345678901 1234567890 123456789 ============================ この時、 fgets( str, 10, fp); printf("str (%2d)= %s\n", strlen(str), str); を、EOFになるまで繰り返します。 すると、実施結果は ============================ 123456789 012 123456789 01 123456789 0 123456789 ============================ となります。 これは、fgetsで10というレングスを指定しているために、1行読み込んで、10文字以降の文字列はバッファに残ってしまっているため、 2度目のfgetsで、10文字以降の文字列が読み込まれ、書き出されているものと思われます。 この時、fgetsで1行読み込んだ後、バッファに残った文字列を無視し、2度目のfgetsで、2行目を読み込むにはどうしたらよいでしょうか? 有識者の方、ご教授ください。よろしくお願いします。

  • 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; }

  • fgets

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

  • 端末ドライバのバッファやstdinバッファの中身を覗くには?

    select関数についての振舞いについて調べています。 (Win2k+Cygwin) #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <sys/types.h> #include <curses.h> #include <signal.h> #include <unistd.h> //=================== void session_loop(){ fd_set mask; FD_ZERO(&mask); FD_SET(0,&mask); fd_set readOK; int width=1; char c; printf("う\n"); while(1){ printf("あ\n"); readOK=mask; printf("こwidth=%d\n",width); select(width,(fd_set *)&readOK,NULL,NULL,NULL); printf("け\n"); if ( FD_ISSET(0, &readOK ) ){ printf("い\n"); c=getchar(); //getcharはバッファリングあり関数 printf("c=%c\n",c); printf("さ\n"); } } } //================= int main(void){ session_loop(); return 0; } というリストで 端末ドライババッファやstdinバッファの振舞いについて学習しています。 端末ドライバにバッファリングされた文字群がgetchar関数のread要求とかでstdinバッファに排出される様子や stdinバッファの文字群がgetchar関数の読込み毎に減っていく様子を垣間見たく思っています。 端末ドライバのバッファやstdinバッファの中身を覗くにはどうすればいいのでしょうか?

専門家に質問してみよう