C ++ тест, если вход является двойным / символ - PullRequest
0 голосов
/ 14 января 2010

Я пытаюсь получить ввод от пользователя, и мне нужно знать, как программа распознает, что было или не было double / char есть прямо сейчас ... но при вводе неверного типа ввода

1) двойной тест просто зацикливается

2) символ, который не прекратится зацикливаться даже при правильном вводе

int main () {
    double _double = 0;
    bool done = true;
while ( done ) {
    cout << "Please enter a DOUBLE:\n" << endl;
    cin >> _double;
    if ( _double > 0 ) { done = false; }
    if ( _double < 0 ) { cout << "\nthe number you entered was less than zero\nplease enter a valad number..." << endl; } 
    if(cin.fail()) { cin.clear(); }
}

done = false;
char _char = ' ';
while ( !done ) {
    cout << "Please enter a CHAR" << "\n";
    cout << "\t'y' = yes\n\t'n' = no" << endl;
    cin >> _char;
    if ( _char == 'y' || _char == 'n' ) { done = true; }
    if ( ! (_char == 'y' || _char == 'n') ) { cout << "\nyou have entered an invald symbol... \n" << endl; }
    if(cin.fail()) { cin.clear(); }
}

Ответы [ 3 ]

5 голосов
/ 14 января 2010

Лучше всего всегда читать ваши данные в виде строк. Затем вы можете использовать такие функции, как std::strtod(), чтобы проверить и преобразовать в двойники. Проверка сбоя потоков, а затем их сброс - в лучшем случае подвержена ошибкам и не дает возможности создавать хорошие сообщения об ошибках.

Например:

string s;
cin >> s;
char * p;
double d = strtod( s.c_str(), & p );
if ( * p == 0 ) {
   cout << "Read double: " << d << endl;
}
else {
   cout << "Read string: " << s << endl;
}

Указатель 'p' будет указывать на первый символ, который нельзя преобразовать в двойной. Как именно вы справляетесь с этим, зависит от логики вашего приложения.

3 голосов
/ 14 января 2010

Проблема в том, что когда вы что-то читаете и cin видит, что ввод никогда не может быть двойным, он прекращает чтение, оставляя содержимое в буфере, который он не использовал. Он будет сигнализировать о сбое, который вы очистите, но вы не будете есть оставшиеся данные, которые cin не съели. Итак, в следующий раз тот же неправильный ввод снова будет прочитан, и снова ...

Проблема с char в том, что вам нужно нажать клавишу возврата, чтобы он обрабатывал любые символы на большинстве терминалов (этого не происходит, если вы, например, заставляете вашу программу читать из файла). Поэтому, если вы нажмете y, он не выйдет из вызова на чтение, пока вы не нажмете клавишу возврата. Тем не менее, тогда он будет продолжаться и выйдет из цикла.

Как уже упоминали другие, вам лучше прочитать целую строку, а затем решить, что делать. Вы также можете проверить число с потоками C ++ вместо функций C:

bool checkForDouble(std::string const& s) {
  std::istringstream ss(s);
  double d;
  return (ss >> d) && (ss >> std::ws).eof();
}

Это читает любой начальный двойной номер и затем любой оставшийся пробел. Если он затем нажмет eof (конец файла / потока), это означает, что строка содержит только двойное число.

std::string line;
while(!getline(std::cin, line) || !checkForDouble(line)) 
  std::cout << "Please enter a double instead" << std::endl;

Для символа вы можете просто проверить длину 1

std::string line;
while(!getline(std::cin, line) || line.size() != 1) 
  std::cout << "Please enter a double instead" << std::endl;

Если вы хотите прочитать only 1 char и продолжить, как только этот char был напечатан, вам придется использовать зависимые от платформы функции (C ++ не будет предоставлять их в качестве стандартных функций). Найдите, например, файл conio.h для Windows, для которого есть функция _getch. В системах Unix ncurses обеспечивает такую ​​функциональность.

2 голосов
/ 14 января 2010

cin >> _double всегда получит двойную сумму, независимо от того, набрали ли они «42», «0» или «у Мэри был маленький ягненок» Вам нужно прочитать пользовательский ввод как строку, а затем проверить эту строку, чтобы увидеть, является ли она двойной. sscanf вернет 0, если не сможет преобразовать входную строку в нужный тип:

cout << "Please enter a DOUBLE:\n" << endl;
    string s;
cin >> s;
    if( !sscanf(s.c_str(), "%lf", &_double) )
    {
        done = false;
        cout << "Not a number, sparky. Try again." << endl;
        continue;
    }

Кроме того, идентификаторы с начальными подчеркиваниями, как у вас, зарезервированы языком. Не имейте привычку называть такие вещи, как _double - когда-нибудь они могут не работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...