【问题标题】:Check if input is blank when input is declared as double [C++]当输入声明为双精度 [C++] 时检查输入是否为空
【发布时间】:2009-08-27 17:14:59
【问题描述】:

我有三个变量声明为双精度:

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...

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

【问题讨论】:

    标签: c++ null double


    【解决方案1】:

    有点像

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

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

    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&gt;&gt; 将占用前导空格,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* 用于转换为bool (if(cin) ...) 而operator! 用于代码执行!cin

    【讨论】:

    • @litb:那张桌子很棒! +1
    【解决方案2】:
    std::cout << "Enter doubles: ";
    std::cin >> d1 >> d2 >> d3;
    
    if(std::cin.fail())
    {
        // error!
    }
    

    【讨论】:

    • 基本类型如double在Java中也不能为NULL
    • @Tyler 对不起,我只是一个 java 新手 :)
    【解决方案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”,因为只有指针可以为空,而不是值类型。

    【讨论】:

    • 请注意if(is.good()) 和if(is) 之间的区别:如果is.eof() 是true,前者也会失败。在cin&gt;&gt;var; if (cin.good()) 的情况下,即使var 被正确读取,也会报告错误,但恰好是输入流中的最后一件事。这使得第一个示例错误。
    【解决方案4】:

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

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

    由于operator&gt;&gt;always 返回它的左参数,这也有效:

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

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

    【讨论】:

      【解决方案5】:

      这里有很多问题。

      首先:判断是否解析失败,使用if (cin.fail()) { /* print error */ }。

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

      第三:== NULL 会将您的布尔值(在本例中为false)与指针值NULL 进行比较。我相信这永远是true。

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

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

          if(!(std::cin >> Delay1 >> Delay2 >> Delay3)) {
              // error
          }
          

          【讨论】:

            【解决方案8】:

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

            【讨论】:

            • 因为在 C++ 中从字符串转换最容易使用字符串流完成,所以他又回到了原点。国际海事组织的坏主意。
            • +1 了你。我认为@colen 有道理。请参阅我的代码答案。这不是一成不变的,因为字符串流的行为与连接到标准输入的流不同(尤其是关于 EOF)。
            • @litb:他们的行为有何不同?
            • 如果要测试数字后面是否还有字符,那么“cin”可能会阻塞等待输入。但是,字符串流不会阻塞。
            • @litb:啊,我明白了。我没有考虑检查更多输入,因为这似乎不是必需的,但你确实有一点。 (OTOH,科伦的回答仍然无济于事,因为它没有说明如何进行实际转换 - 除了您提出的微妙问题之外,这需要与从 @987654321 读取值相同的代码直接@@。还是你的“你”是针对我的?我对此感到有些困惑。)
            猜你喜欢
            • 2019-07-09
            • 1970-01-01
            • 2022-01-11
            • 1970-01-01
            • 2018-05-26
            • 1970-01-01
            • 2011-08-18
            • 2015-01-11
            相关资源
            最近更新 更多