2011-10-17 95 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:如果你想讓空白變得很重要,那麼標準I/O流不適合這項工作。給[Boost.Spirit](http://www.boost.org/libs/spirit/)的'auto_'分析器一個鏡頭。 – ildjarn

+0

所有格式化的輸入都會跳過空格。如果你不想讓空格,你必須使用無格式輸入編寫自己的例程。 –