2012-04-16 5 views
1

Я очень новичок в этом мире C++ и пытаюсь написать функцию проверки ввода для числового пароля. Это то, что я до сих пор:проверка ввода для числового ввода

#include <iostream> 
#include <limits> 
using namespace std; 

void isNumeric(int &iN) 
{ 
    while (1) { 
     cin >> iN; 

     if (cin.fail()) { 
      cin.clear(); 
      cin.ignore(numeric_limits<streamsize>::max(), '\n'); 
      cout << "Only 'numeric' value(s) are allowed: "; 
      continue; 
     } 

     // alpha-numeric entry also not allowed 
     cin.ignore(numeric_limits<streamsize>::max(), '\n'); 
     if (cin.gcount() > 1) continue; 

     // check against the -ve value 
     if (iN <= 0) continue; 

    break; 
    } 
} 

int main() 
{ 
    int x; 

    cout << "Enter your number: "; 
    isNumeric(x); 
    cout << "You've entered: " << x << endl; 

    return 0; 
} 

Это работает очень хорошо для некорректного значения (ов), но не вырваться из петли на действительной записи. Любая идея, что мне здесь не хватает? Ура !!


ERRor из сценария Джеймса Kanze в:

test.cpp: In function ‘bool parseNumber(const string&, int&)’: 
test.cpp:11:20: error: no match for ‘operator>>’ in ‘text >> results’ 
test.cpp:11:20: note: candidates are: 
/usr/include/c++/4.6/bits/basic_string.tcc:998:5: note: template<class _CharT, class _Traits, class _Alloc> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::basic_string<_CharT, _Traits, _Alloc>&) 
/usr/include/c++/4.6/bits/istream.tcc:957:5: note: template<class _CharT2, class _Traits2> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, _CharT2*) 
/usr/include/c++/4.6/bits/istream.tcc:925:5: note: template<class _CharT, class _Traits> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, _CharT&) 
/usr/include/c++/4.6/istream:709:5: note: template<class _Traits> std::basic_istream<char, _Traits>& std::operator>>(std::basic_istream<char, _Traits>&, unsigned char&) 
/usr/include/c++/4.6/istream:714:5: note: template<class _Traits> std::basic_istream<char, _Traits>& std::operator>>(std::basic_istream<char, _Traits>&, signed char&) 
/usr/include/c++/4.6/istream:756:5: note: template<class _Traits> std::basic_istream<char, _Traits>& std::operator>>(std::basic_istream<char, _Traits>&, unsigned char*) 
/usr/include/c++/4.6/istream:761:5: note: template<class _Traits> std::basic_istream<char, _Traits>& std::operator>>(std::basic_istream<char, _Traits>&, signed char*) 
test.cpp:11:42: error: ‘const string’ has no member named ‘peek’ 
test.cpp:11:52: error: ‘EOF’ was not declared in this scope 


Новый код: используя getline() и проверки в виде строки Спасибо всем (особенно Джеймс Kanze) за помощь мне вне. Эта вещь в значительной степени работает здесь.

void isNumeric(int &iN) 
{ 
    string sN; 

    while (1) { 
     getline(cin, sN); 

     bool valNum = true; 
     for (unsigned iDx=0; iDx < sN.length(); iDx++) 
      if (!isdigit(sN[iDx])) { 
       valNum = false; 
       break; 
      } 

     if (!valNum) { 
      cout << "Wrong entry; Try again: "; 
      continue; 
     } 

     stringstream sStream (sN); 
     sStream >> iN; 

     if (iN<=0) { 
      cout << "Cannot be 0; Try again: "; 
      continue; 
     }  
    break; 
    } 
} 

Есть ли там какое-нибудь место для улучшения? Ура !!

+0

@Shahbaz Я всегда знал, что мой C++ безнадежна, но не знал, что пошел так далеко! – MacUsers

+0

Речь идет не о вашем коде, а о вашем названии вопроса как-то напомнил мне об этом смешном, что я видел однажды! – Shahbaz

ответ

2

Это выглядит как линия ориентированного ввод. В этом случае, обычное решение является использование getline:

bool parseNumber(std::string const& text, int& results) 
{ 
    std::istringstream parser(text); 
    return parser >> results >> std::ws && parser.peek() == EOF; 
} 

int getNumber() 
{ 
    int results; 
    std::string line; 
    while (! std::getline(std::cin, line) || ! parseNumber(line, results)) 
    { 
     std::cin.clear(); 
     std::cout << "Only 'numeric' value(s) allowed:"; 
    } 
    return results; 
} 
+0

Не 'getline()' отсутствует второй параметр? – jrok

+0

@James Kanze: он возвращает эту ошибку: 'error: variable 'std :: istringstream parser' имеет инициализатор, но неполный тип' - что это значит? ура !! – MacUsers

+0

@jrok Да. это должно быть 'std :: getline (std :: cin, line)'. –

2

Если происходит сбой, чтобы преобразовать затем поток сами оценивает ложь, так что вы можете сделать это:

int get_int() { 
    int i; 
    std::cout << "Please enter a number: " << std::endl; 
    while(!(std::cin >> i)) { 
     std::cin.clear(); //clear flags 
     //discard bad input 
     std::cin.ignore(std::numeric_limits<std::streamsize>::max()); 
     std::cout << "Incorrect, must be numeric: " << std::endl; 
    } 
    return i; 
} 
+0

На самом деле это не то, что я намереваюсь сделать. Ввод, подобный этому: '123asd', должен быть отклонен, но он принимает' 123' (как и ожидалось). И если я вхожу: 'asd123', он ничего не делает. Ура !! – MacUsers

+0

Это будет успешным, если пользователь войдет в «1abc». –

+0

@James Kanze: Это то, чего я не хочу. Моя цель: все остальное, кроме числовых значений, должно быть отклонено. Ура !! – MacUsers

Смежные вопросы