2010-12-27 6 views
2

を停止し、私はアプリの整数を渡すことだし、それは[OK]を動作しますが、私は手紙を渡した場合、それは狂気、C++番号を検証し、私はコンソールアプリをやっている無限ループ

int opt=0; 
std::cout<<"Pick lang:"<<'\n'; 
std::cout<<"1.[es-ES]:"<<'\n'; 
std::cout<<"2.[en-US]:"<<'\n'; 
std::cin >> opt; 

while(opt<1 || opt>2) 
{ 
    std::cout<<"\nERROR!"<<'\n'; 
    std::cout<<"Pick lang again:"<<'\n'; 
    std::cout<<"1.[es-ES]:"<<'\n'; 
    std::cout<<"2.[en-US]:"<<'\n'; 
    std::cin >> opt; 
} 

私はisdigit()を使用しようとしましたが、私は同じ結果を得ます。ありがとう

+0

あなたは「手紙を渡す」と言うとき、あなたは 'char'を読んでいる意味ですか?または、上記のコードを実行するときに文字を入力することを意味しますか? – marcog

+1

これが役立つかどうかを確認してください。 http://stackoverflow.com/questions/4342068/c-infinite-loop-with-a-simple-menu-selection/4342247#4342247 –

+0

はい、私はcharを読んでいますが、cinはintを待っています –

答えて

7

cin >>抽出を実行した後、cinストリームがまだ良いかどうかを確認する必要があります。 cinが数字を抽出すると思ったら、代わりに何か他のものが得られるならば、例えば。手紙のように、ストリームは悪い状態に設定され、それはあなたがそれが狂っているのを見る理由です。

あなたがしなければならないことは、入力後、cinがまだ良いかどうかを確認することです。状態が悪い場合は、フラグをクリアしてストリーム内の迷惑メールデータをすべて削除する必要があります。そうしないと、その後のcinの使用は単に機能しなくなります。例えば、あなたのコードスニペットを取る

、あなたはこのような何かにそれを変更することができます。

int opt = 0; 
bool inputGood = false; 

do 
{ 
    std::cout << "Pick lang again:" << '\n'; 
    std::cout << "1.[es-ES]:" << '\n'; 
    std::cout << "2.[en-US]:" << '\n'; 
    inputGood = std::cin >> opt; 
    if(!inputGood) 
    { 
     std::cout << "\nERROR! Invalid choice." << '\n'; 
     cin.clear(); 
     while(cin.get() != '\n'); 
    } 
}while(!inputGood || opt < 1 || opt > 2); 

編集:CINのエラー処理でおっとマイナーエラー。訂正され、現在作業しているはずです。 :)あなたはこの問題が発生した文字を挿入

1

:ストリームから

  1. operator>>抽出文字をその数に変換してみてください。
  2. 変換に失敗するため、ストリームの状態をios::failbitに設定して返します。 optはおそらく触れられていないでしょう(私は決して本当に理解していないC++のゾーンであるロケールライブラリに標準を委譲しています - 十分な勇気があれば、22.2.2.1.2にあります)。
  3. 返されているので(おそらく)optがそのまま残っていますが、ループは続行されます。
  4. 実行がstd::cin >> opt;に戻ると、operator>>は状態がまだios::failbitであると判断し、何も抽出しようとしません。
  5. 後藤3.

問題を修正するには、エラー状態をきれいにし、入力バッファから「間違った」の文字を削除してください。おそらく、すべてのコードをすべてcin>>に追加したくないので、この共通の問題に対処する関数を作成すると便利です。個人的に、私は便利な何度も証明しているこの小さなヘッダ(AcquireInput.hpp)作成:問題はコールstd::cin >> optは、(バッファを消費することなく)すぐ文字とリターンを解析するために失敗しているということです

#ifndef ACQUIREINPUT_HPP_INCLUDED 
#define ACQUIREINPUT_HPP_INCLUDED 

#include <iosfwd> 
#include <limits> 
#include <string> 

    template<typename InType> void AcquireInput(std::ostream & Os, std::istream & Is, const std::string & Prompt, const std::string & FailString, InType & Result) 
    { 
     do 
     { 
      Os<<Prompt.c_str(); 
      if(Is.fail()) 
      { 
       Is.clear(); 
       Is.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
      } 
      Is>>Result; 
      if(Is.fail()) 
       Os<<FailString.c_str(); 
     } while(Is.fail()); 
    } 

    template<typename InType> InType AcquireInput(std::ostream & Os, std::istream & Is, const std::string & Prompt, const std::string & FailString) 
    { 
     InType temp; 
     AcquireInput(Os,Is,Prompt,FailString,temp); 
     return temp; 
    } 

    /* Usage example: 

     //1st overload 
     int AnInteger; 
     AcquireInput(cout,cin,"Please insert an integer: ","Invalid value.\n",AnInteger); 

     //2nd overload (more convenient, in this case) 
     int AnInteger=AcquireInput(cout,cin, "Please insert an integer: ","Invalid value.\n"); 
    */ 

#endif 
2

を、それが見つかりました同じ内容で失敗します。

操作の結果を確認し、それに反応する必要があります。 1つの可能性は、フェイルビット(std::cin.fail())をチェックして、バッファ全体を操作することなく失敗させることです(おそらくアプリケーションの振る舞いに応じて、おそらく単一の文字になるかもしれません)。

最も簡単な方法は、おそらく数に読んでいないことではなく、文字を、次に予想される文字との比較になります。数字で

char opt = 0; 
do { 
    // prompt user for input 
    if (! (std::cin >> opt)) { 
     // io error, report and bail out 
     break; 
    } 
} while (opt != '0' && opt != '1'); 
+0

'opt!= '1' ||を意味すると思いますopt!= '2' '。 optは同時に '0'と '1'の両方になることはできません。 ':P' – Muggen

+0

@Muggen: 'opt!= '0' || opt!= '1' 'は 'true'と等価です。なぜなら' '0 ''なら' '1 ''とかviceversa(' '1' 'と区別するか' '' 0 '')。 'opt'が' '0 ''または' '1''のとき、ループ条件は' false'でなければなりません...あるいは多分私は混乱していますか? –

+0

@David、私の間違いを心配しないでください。私はあなたが今行ったことを見る。 – Muggen

1

読書が直接 問題

た場合でありますstd :: cinが入力されているので、 は処理できません。std :: cinは に入ります。「失敗」状態 入力が入力ストリームに残っていません。

すべての入力はSTDによって無視されます:: cinを "失敗" 状態が解除されるまで: のstd :: cin.clearを()

数直接はず読み込みルーチン:

数の
  1. 読む

  2. チェックは入力 ストリームがまだ有効であることを確認し

  3. 入力 ストリームが良くない(!STD :: CIN)

    1. コール のstd :: cin.clear()状態を "不合格" のうち、ストリーム を取る場合。
    2. ストリームに から 問題の原因となった入力を削除します。適切か 場合はstd :: cin.ignore(...)
    3. は再び 入力しますそう
エラーを処理ここ

詳細:http://www.augustcouncil.com/~tgibson/tutorial/iotips.html