2011-10-17 22 views
0

入力を簡単に抽出し、正しいタイプを検証するために、次のものを使用しています。ただし、ファイルEOFの終了は起動されていません。C++テンプレートの入力検証

template< typename T > 
std::istream& read(std::istream &istr, T &val) 
{ 
    std::string s; 
    std::getline(istr, s); 

    if (istr.good()) 
    { 
     s.erase(s.find_last_not_of(" \n") + 1); 

     std::stringstream iss(s); 

     iss >> val; 

     if (! iss.good()) 
      istr.setstate(std::ios::failbit); 

     char c; 
     if (iss.get(c)) 
      istr.setstate(std::ios::failbit); 
    } 

    return istr; 
} 
int main(int argc, char **argv) 
{ 
    int input = 0; 

    std::cout << "Please enter an integer>" << std::flush; 

    for (;;) 
    { 
     if (read(std::cin, input)) 
      break; 

     std::cin.clear(); 
     std::cout << "Please, enter only an INTEGER>" << std::flush; 
    } 

    std::cout << "Press <enter> to quit>"; 
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
    return 0; 
} 

「111」を入力するときは、それが必要整数として検証しません。

+0

これは、単一の文字を取得する際にも失敗します。 – rem45acp

答えて

1

iss >> valはすべての文字を読み込み、ストリームの最後に「触れる」ので、毎回EOFをオフにします。

template< typename T > 
std::istream& read(std::istream &istr, T &val) 
{ 
    std::string s; 
    std::getline(istr, s); 

    if (istr.good()) { 
     std::istringstream iss(s); //leave the '\n' 

     if (! (iss >> val)) 
      istr.setstate(std::ios::failbit); 

     //if it gets another character that isn't a newline 
     char a=0; 
     if (iss.get(a) && a!='\n') 
      istr.setstate(std::ios::failbit); 
    } 

    return istr; 
} 
+0

入力タイプをintに変更し、 "1"(スペースに気付く)を入力すると、入力タイプは受け入れられません。 – rem45acp

+0

@ rem45acp:空白を有効にしたい場合、標準の入出力ストリームはジョブの正しいツールではありません。 [Boost.Spirit](http://www.boost.org/libs/spirit/)の 'auto_'パーサにショットを与えます。 – ildjarn

+0

すべての書式付き入力は空白をスキップします。スペースを許さない場合は、書式なしの入力を使用して独自のルーチンを作成する必要があります。 –