3

我有三个变量声明为双打:

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

然后我从用户那里获取他们的值:

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

但是当我检查这些值以查看它们是否为空时(用户只是按回车并没有输入数字)它不起作用:

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

每次都会运行。
检查已声明为双精度的输入是否为空白的正确方法是什么?

4

8 回答 8

11

就像是

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

不会根据您的规范工作,因为cin会跳过前导空格。用户不能只是按回车键。他首先必须输入一些文字。如果他输入以下

3a

然后输入被读入双精度,直到a它停止。cin不会发现有什么不对,a就在溪流中离开。通常,我认为这是足够的错误处理。但是,如果您希望在用户输入类似上述内容时实际重复,那么您需要更多代码。

如果要测试直到换行符的整个输入是否为数字,则应使用getline, 读入字符串,然后尝试转换为数字

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

isnumber函数可以使用 stringstream 来测试字符串

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.

编写一个类似的函数,返回双精度数或将双精度数的地址传递给`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*转换为boolif(cin) ...)时使用,而operator!用于代码执行!cin

于 2009-08-27T17:42:33.027 回答
4
std::cout << "Enter doubles: ";
std::cin >> d1 >> d2 >> d3;

if(std::cin.fail())
{
    // error!
}
于 2009-08-27T17:17:10.113 回答
3

检查流输入是否有效的方法是测试流:

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

由于operator>>总是返回它的左参数,这也有效:

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

如果输入失败,输入流不会改变值。在您的情况下,他们将因此保留他们之前拥有的随机值。你不应该在没有检查流的情况下接受输入。

于 2009-08-27T17:18:56.753 回答
3

您需要检查的是在您尝试读取双精度后输入流的状态。

例如

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”,因为只有指针可以为空,而不是值类型。

于 2009-08-27T17:21:57.827 回答
2

这里有很多问题。

第一:检查是否解析失败,使用if (cin.fail()) { /* print error */ }.

第二:Delay1 || Delay2 || Delay3将双精度转换为布尔值,然后将它们逻辑或。

第三:== NULL将您的布尔值(在这种情况下false)与指针值进行比较NULL。我相信这将永远是true

于 2009-08-27T17:19:36.597 回答
2

你的 if 条件是错误的。if(Delay1 || Delay2 || Delay3 == NULL)如果 Delay等于 0 或 delay2等于 0 或 Delay3 为零,则为真。这肯定不是你想要的。此外,您应该将 0 用于原始数据类型。此外,将双精度值与绝对值进行比较总是很危险的。您检查该值是否小于一个小的 epsilon 值。

于 2009-08-27T17:23:09.493 回答
1

只需使用流状态,如果无法读取双精度,它将处于失败状态。

if(!(std::cin >> Delay1 >> Delay2 >> Delay3)) {
    // error
}
于 2009-08-27T17:21:16.063 回答
0

我认为您需要将变量作为字符串读取,然后检查它是否为空白,然后将其转换为双精度(并检查它是否是有效的双精度 - 用户可能只是输入了“hello”)。

于 2009-08-27T17:17:09.800 回答