2016-04-19 48 views
8

私は約5-10の異なるアドバイスを読んでいますが、標準入力をクリアする方法はありませんが、私のニーズに合ったものはありません。私のコンピュータではfflush(stdin)が完璧に機能していましたが、残念ながらどこでも動作しているようには見えないので、同じ機能を持つものが必要です。それ以外の方法で私はそれが空ではないときに標準入力をクリアするが、標準入力が空のときはユーザ入力が必要である。新しい入力を取得する前にstdinをクリアするには?

質問は次のとおりです。ユーザー入力を要求する前に、なんとかstdinが空白になっていることを確認できますか? (とない、THENとそれだけ、クリア何とかならば?)のような 何か:

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

EDIT:事は、私は、1により、いくつかの点でstdin 1からの入力の一部からの文字を読み込むことです以前の反復は破棄されることもあれば、破棄されないこともあります。いずれにしても、処理する別の入力をユーザに依頼する前に、私は明確なstdinを持っている必要があります。バッファ自体をクリアすることはそれほど重要ではありません。問題は、プログラムがクリアポイントに達すると入力が空になったときに何が起きるかです。なぜなら、その時点では、プログラムはクリアすることによって食べられる別の入力を必要とするからです関数。それは私が取り除きたいものです。

+2

'fflush(stdin)'はUBです。 –

+1

空の入出力ストリーム*はありません**ストリーム**です。次のことを考慮してください。 './myprog joop

+0

これをWindows上でプログラミングするには、Linuxで動かす必要があります... – Tom

答えて

1

TL(私はfflush(stdin);を使用することができたとき、私はちょうど...私のプログラムの次の行のためにstdinは関係なく、何の質問が尋ねたものを、空でもないことを、知っていた); DRfflush(stdin)は標準どおりundefined behaviorを呼び出しますそれを決して使用しないでください。


代わりに改行を探しているの、あなたのコード(ロジック)に来て、あなたはEOFを探すことができます。このループを実行する前に、stdinにはの一部がと入力されている必要があります。

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

よう

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

+0

while(getchar()!= EOF);別の入力と別の入力を必要とする無限ループで私を設定します。私もif(!feof(stdin))などを試みましたが、そのどれもうまくいきませんでした。 stdinにEOFセットがないように見えますが、終わりに達すると別の入力が必要になります。 – Tom

+1

少なくともウィンドウでは、Ctrl + ZでstdioのEOFを明示的に生成する必要があります。 – HolyBlackCat

+1

Er、no。あなたのループは、ユーザーがEOF( '^ D'または'^Z')を生成するまで待つが、OPは入力バッファをフラッシュする方法を求めている。 – jch

1

fgets()を使用すると、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

'if(tmp [strlen(tmp)-1]!= '\ n')'は、 'tmp [0] == 0'ならばUBです。 'fgets()'によって読み込まれた最初の文字をヌル文字にするほど簡単です。 – chux

+0

@chux:そうですが、** text **ファイルではありません。 **テキスト**ファイル( 'stdin'、キーボード、...)には埋め込まれたNULはありません。とにかくこれに対処するコードが変更されました。ありがとう – pmg

+0

真、最初の文字がヌル文字であることは一般的ではありません。 _textファイルの定義は正式ではなく、 ''\ 0' 'を明示的に排除するものではありません。それでも簡単に先頭のヌル文字を持つことができるBOM(シンプルなASCIIファイルだと思う)ファイルがないUTF-16BE ** text **ファイルを読むのはまれではありません。キーボードがヌル文字を生成できるかどうかは、プログラムの制御を超えて、プラットフォームレベルの問題です。 IMOは、ハッカーの悪用と強力なコードの対処です。改善された回答のために投票しました。 – chux

0

selectモジュールは、あなたが探している正確に何を達成しselectと呼ばれる機能を提供しています。 select.selectは3つの引数を取る:

select.select(rlist, wlist, xlist) 

各引数は、(例えば[sys.sdtin]など)、ファイル記述子のリストであるべきであり、特定のIO操作が使用可能になるまで、それは次に待ち。IO操作は、r ead、w riteまたはその他の特定のファイル記述子のx ceptionです。これは、対応するリストのtupleを、準備ができているファイル記述子で埋めて戻します。 sys.stdinで待っている入力がある場合

ので、その関数はそうと同じように動作します:IO操作があるまでは、デフォルトで機能がお待ちしておりますので、

>>> import select 
>>> import sys 
>>> 
>>> select.select([sys.stdin], [], []) 
([sys.stdin], [], []) 
>>> 

は、それ自体では、これはあなたの問題を解決していません利用可能です。しかし、重要なことに、select.selectにはオプションのtimeoutという引数があり、これは放棄するまでの待機時間を示します。タイムアウトをゼロに設定するだけで、プログラムフローをブロックせずに入力を確認できます。

のは、sys.stdinで待っている入力がない例を見てみましょう:

>>> import select 
>>> import sys 
>>> 
>>> timeout = 0 
>>> select.select([sys.stdin], [], [], timeout) 
([], [], []) 
>>> 

我々は唯一のそのタプルの最初の要素をしたいことを知っての我々は、if文有用なものにする準備が整いました(入力ストリーム)

while sys.stdin in select.select([sys.stdin], [], [], 0)[0]: 
    sys.stdin.readline() 
::入力ストリームをクリアするだけで、いくつかの反復を必要とする意味

if sys.stdin in select.select([sys.stdin], [], [], 0)[0]: 
    print('Input is waiting to be read.') 

それでは、あなたがあなたの問題のために頼むものを達成するために私達の機能を発揮させ

def clear_input(stream, timeout=0): 
    '''Takes an input stream and discards each line in the buffer. 
    The given timeout denotes how long in seconds to wait for 
    further input when none is available. 
    ''' 
    while stream in select.select([stream], [], [], timeout)[0]: 
     stream.readline() 

を::

そして、私たちはもちろん、任意の入力ストリームでこれを使用することができますが、その機能にそれを置くことができます

import select 
import sys 
import time 

def clear_input(stream, timeout=0): 
    while stream in select.select([stream], [], [], timeout)[0]: 
     stream.readline() 

if __name__ == '__main__': 
    print('Type some lines now. They will be ignored.') 
    time.sleep(5) 

    print('Clearing input.') 
    clear_input(sys.stdin) 

    user_input = raw_input('Please give some fresh input: ') 
    print(user_input) 

clear_input関数は、入力ストリームを消去するための非ブロッキング方法として使用でき、Python2とPython3で動作するはずです。

+3

しかし、これはCの質問であり、Pythonの質問ではないことに気付きましたか? – Jens

+0

@jens/facepalm :-) – dsclose

+0

偉大な答えです。ちょっと別の質問が必要です。 –

2

新しい入力を取得する前に標準入力をクリアするにはどうすればよいですか?
..私は同じ機能を持つものが必要です。

携帯Cではこれはできません。


は、代わりに、異なる(より通常C)パラダイムを提案する:前の入力機能は全て以前入力消費を確認してください。

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) { 
    if (i + 1 < size) { 
     buf[i++] = ch; 
    } 
    if (ch == '\n') { 
     break; 
    } 
    } 
    buf[i] = '\0'; 
    if (i == 0) { 
    return EOF; 
    } 
    return i; 
} 
関連する問題