web-dev-qa-db-ja.com

新しい入力を取得する前にstdinをクリアする方法は?

Stdinをクリアする方法について5〜10種類のアドバイスを読みましたが、どれも私のニーズに合いません。問題は、fflush(stdin)が私のコンピューターで完全に機能したことですが、残念ながらすべての場所で機能するわけではないため、同じ機能を持つものが必要です。私が試した他のすべての方法は、空ではないstdinをクリアしますが、stdin IS emptyの場合、ユーザー入力が必要です。つまり、何も取得したくない瞬間に入力が必要です(+とにかくそれを破棄します)。

問題は、ユーザー入力が必要になる前にstdin IS空であることをどういうわけか確認できますか?(そうでない場合は、THENし、それを何らかの方法でクリアするだけですか?) :

_if (stdin is NOT empty) 
    while (getchar() != '\n')
        continue;
_

編集:問題は、stdinから文字を1つずつロードし、ある時点で、前の反復からの入力の一部が破棄される場合とされない場合があることです。いずれにしても、ユーザーに別の入力の処理を要求する前に、クリアstdinを用意する必要があります。バッファ自体をクリアすることはそれほど大したことではありません。プログラムがstdinをクリアするポイントに到達したときに入力が空の場合に問題が発生します。クリア機能で食べられます。それは私が取り除きたいものです。 (私がfflush(stdin);を使用できたとき、私は知っていました。私のプログラムの次の行では、stdinは何であっても空であり、質問はされません...)

13
Tom

新しい入力を取得する前にstdinをクリアする方法は?
..したがって、同じ機能を持つものが必要です。

ポータブルCでは、これは不可能です。


代わりに、別の(そして通常のCの)パラダイムを提案します。
以前の入力関数が以前の入力をall消費するようにします。

fgets()(または* nix getline() )は典型的なアプローチであり、ほとんどの状況を解決します。

またはあなた自身を転がします。以下は、行全体を読み取りますが、余分な入力を保存しません。

int mygetline(char *buf, size_t size) {
  assert(size > 0 && size <= INT_MAX);
  size_t i = 0;
  int ch;
  while ((ch = fgetc(stdin)) != EOF) {  // Read until EOF ...
    if (i + 1 < size) {
      buf[i++] = ch;
    }
    if (ch == '\n') {  // ... or end of line
      break;  
    }
  } 
  buf[i] = '\0';
  if (i == 0) { 
    return EOF;
  }
  return i;
}
5
chux

onlyfgets()を使用してstdinを読み取ります。

十分な大きさのバッファを使用するか、回線全体をテストします。

fgets()を使用すると、stdinの余分な文字について心配する必要はありません。

// read characters until 'X'
while (((ch = getchar()) != EOF) && (ch != 'X')) putchar(ch);
// discard X and the rest of the line
fflush(stdin); // UB except for Windows

// read full line
char tmp[1000], *p;
if (!fgets(tmp, sizeof tmp, stdin)) /* deal with error */;
if (!*tmp) /* embedded NUL detected: input is not a text file */;
if (tmp[strlen(tmp) - 1] != '\n') /* partial line */;
p = tmp;
while (*p && *p != 'X') putchar(*p++);
// ignore the X and all the subsequent characters
0
pmg

TL; DRfflush(stdin)は、標準に従って ndefined behavior を呼び出します。使用しないでください。


コード(ロジック)にアクセスすると、改行を探す代わりに、EOFを探すことができます。このループを実行する前に、stdinsome入力が必要であるという前提条件はありません。

何かのようなもの

 while (getchar() != EOF);   //; is not a mistake

あなたのニーズを満たす必要があります。

0
Sourav Ghosh