Проверьте, является ли ввод пустым, когда вход объявлен как double [C ++] - PullRequest
3 голосов
/ 27 августа 2009

У меня есть три переменные, объявленные как double:

double Delay1 = 0;
double Delay2 = 0;
double Delay3 = 0;

Тогда я получу свои значения от пользователя:

cout << "Please Enter Propogation Delay for Satellite #1:";  
cin >> Delay1;
...

Но когда я проверяю эти значения, чтобы увидеть, являются ли они нулевыми (пользователь просто нажал Enter и не указал число), это не работает

if(Delay1  || Delay2 || Delay3 == NULL)  
      print errror...

Это выполняется каждый раз.
Как правильно проверить, является ли вход, объявленный двойным, пустым?

Ответы [ 8 ]

11 голосов
/ 27 августа 2009

Что-то вроде

cin >> Delay1;
if(cin) { ... }

не будет работать в соответствии с вашей спецификацией, потому что cin пропустит первые пробелы. Пользователь не может просто нажать Enter. Сначала он должен ввести текст. Если он вводит следующее

3a

Затем вход считывается в двойном, до a, где он останавливается. cin не найдет ничего плохого и оставляет a в потоке. Я думаю, что для этого достаточно обработки ошибок. Но если требуется, чтобы вы действительно повторяли, когда пользователь вводит что-то подобное, то вам нужно немного больше кода.

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

string delay;
if(!getline(std::cin, delay) || !isnumber(delay)) {
  ...
}

Функция isnumber может использовать поток строк для проверки строки

bool isnumber(string const &str) {
  std::istringstream ss(str);
  double d;

  // allow leading and trailing whitespace, but no garbage
  return (ss >> d) && (ss >> std::ws).eof();
}

operator>> будет использовать первые пробелы, а std::ws будет использовать конечные пробелы. Если он достигнет конца потока, он выдаст сигнал eof. Таким образом, вы можете сразу же сообщить пользователю об ошибке, а не при следующей попытке чтения из cin.

Напишите аналогичную функцию, которая возвращает double или передает адрес double в `isnumber, чтобы он мог записать результат в случае успешного разбора.


Также стоит взглянуть на различные флаги ошибок и их отношение к operator void*, operator!, good(), fail(), bad() и eof(), которые могут быть довольно запутанными:

            flag | badbit  |  failbit  |  eofbit
function         |         |           |
-----------------+---------+-----------+--------
op void*         |    x    |     x     |
-----------------+---------+-----------+--------
op !             |    x    |     x     |
-----------------+---------+-----------+--------
good()           |    x    |     x     |    x
-----------------+---------+-----------+--------
fail()           |    x    |     x     |
-----------------+---------+-----------+--------
bad()            |    x    |           |
-----------------+---------+-----------+--------
eof()            |         |           |    x
-----------------+---------+-----------+--------

Существует x, если соответствующий бит влияет на результат. operator void* используется при преобразовании в bool (if(cin) ...), а operator! используется для выполнения кода !cin

.
4 голосов
/ 27 августа 2009
std::cout << "Enter doubles: ";
std::cin >> d1 >> d2 >> d3;

if(std::cin.fail())
{
    // error!
}
3 голосов
/ 27 августа 2009

Вам нужно проверить состояние входного потока после того, как вы попытаетесь прочитать в двойном числе.

Например

cin >> Delay1;
if (!cin.fail()) {
  // Input was a double
} else {
  // Input was something that could not be interpreted as a double
}

Вы можете написать это более кратко следующим образом

if (cin >> Delay1) {
  // Input was a double
} else {
  // Input was something that could not be interpreted as a double
}

Если ввод не удастся, значение Delay1 не изменится, и поэтому, если вы ранее не инициализировали его, это будет произвольное значение. Как уже указывалось, он не станет «NULL», поскольку только указатели могут быть нулевыми, а не типами значений.

3 голосов
/ 27 августа 2009

Способ проверки работоспособности входного потока - проверить поток:

if(!std::cin) throw "Doh!";

Поскольку operator>> всегда возвращает свой левый аргумент, это тоже работает:

if( std::cin >> Delay1 ) 
  good();
else
  bad();

Входные потоки не изменят значение в случае неудачного ввода. В вашем случае они, таким образом, сохранят случайные значения, которые они имели раньше. Вы никогда не должны принимать ввод, не проверив поток.

2 голосов
/ 27 августа 2009

Ваш, если условие неверно. if(Delay1 || Delay2 || Delay3 == NULL) будет истинным, если Задержка не равна нулю или delay2 равен не равен нулю или Задержка3 равна нулю Конечно, это не то, что вы хотите. Также вы должны использовать 0 для примитивных типов данных. Кроме того, сравнение двойных значений с абсолютным значением всегда опасно. Вы проверяете, меньше ли значение небольшого значения эпсилона.

2 голосов
/ 27 августа 2009

Здесь происходит много проблем.

Сначала: , чтобы проверить, не удалось ли выполнить синтаксический анализ, используйте if (cin.fail()) { /* print error */ }.

Второе: Delay1 || Delay2 || Delay3 преобразует двойные значения в логические значения, а затем логически-ИЛИ их вместе.

Третье: == NULL будет сравнивать ваше логическое значение (в данном случае false) со значением указателя NULL. Я считаю, что это всегда будет true.

1 голос
/ 27 августа 2009

просто используйте состояние потока, оно будет в состоянии сбоя, если не может прочитать двойной.

if(!(std::cin >> Delay1 >> Delay2 >> Delay3)) {
    // error
}
0 голосов
/ 27 августа 2009

Я думаю, вам нужно прочитать переменную в виде строки, затем проверить, не является ли она пустой, затем преобразовать ее в двойное (и проверить, является ли оно допустимым двойным - пользователь мог просто ввести «привет»).

...