【问题标题】:testing for double in visual c++在 Visual C++ 中测试双精度
【发布时间】:2012-05-09 11:32:30
【问题描述】:

我正在用 Visual c++ 设计一个 gui,并且有一个文本框,用户可以在其中输入值以便执行计算。如何验证输入以确保它可以转换为 double 值?

【问题讨论】:

  • 检查每个数字是数字并且有零个或一个句点是否有效?你可以为此设计一个非常小的正则表达式。或者,如果您接受它所接受的输入,则字符串流可能会很有用。
  • 请注意,根据区域设置,小数点可能是逗号,而不是句点。
  • @Pete,说得好。不过,在正则表达式中仍然很容易。
  • 如果你使用 MFC - 你可以使用DDX_Text。它将字符串转换为double,如果无法完成转换,还会向用户报告错误。
  • @Chris:实际上并非如此......您可以轻松地使用逗号或句点的正则表达式([,\.] 或者您可以转义它),但如果您同时接受两者,则无论哪个在您的实际语言环境中是不允许的,但稍后仍可能会意外破坏某些内容(即,当您尝试将值传递给尝试实际转换的函数时)。

标签: c++ .net windows


【解决方案1】:

在任何有 std::string 字段并希望检查它是否包含 double 的 C++ 环境中,您可以简单地执行以下操作:

#include <sstream>

std::istringstream iss(string_value);
double double_value;
char trailing_junk;
if (iss >> double_value && !(iss >> trailing_junk))
{
    // can use the double...
}

如前所述,这将拒绝 "1.234q""-13 what?" 之类的内容,但接受周围的空格,例如" 3.9E2 "。如果你想拒绝空格,试试#include &lt;iomanip&gt; 然后if (iss &gt;&gt; std::noskipws &gt;&gt; double_value &amp;&amp; iss.peek() == EOF) ...

您也可以使用旧式 C API 来做到这一点:

double double_value;
if (sscanf(string_value.c_str(), "%lf%*c", &double_value) == 1)

【讨论】:

    【解决方案2】:

    您不能将字符串“转换”为双精度,您只能转换它。 strtod 函数将返回一个指针,指向转换停止的字符串中的字符,因此您可以决定下一步做什么。所以你可以使用这个函数进行转换和检查。

    【讨论】:

    • 好吧,你可以lexical_cast,这可能是个好主意。
    • 不幸的是,如果字符串无法转换,strtod() 将返回 0,因此很难将这种情况与真正的 0 区分开来。并非不可能 - 您可以检查转换停止的位置,但要注意空格。
    • @IanGoldby 我建议(可能不够明确)应该使用转换停止的位置来决定它是否也成功。此外,它(方便地)丢弃前导空格。
    • @zvbra 我对空白的评论是专门用于检查转换停止的位置 - 所以它是关于 trailing 空白。
    • @IanGoldby 是的。无论如何,是否允许尾随垃圾的问题尚不清楚。在最简单的情况下,我会检查 *endptr==0.
    【解决方案3】:

    我推荐Boost's lexical_cast,如果转换失败会抛出异常。

    【讨论】:

    • 异常不适用于程序流。如果无效输入不被视为“异常”事件,您仍然需要验证输入而不导致异常。
    【解决方案4】:

    由于这似乎是与 C++ CLI 相关的问题,并且您在文本框中的字符串可能是 .NET 字符串,您可能需要检查静态 Double::Parse 方法。有关更便携的解决方案,请参阅其他答案...

    【讨论】:

      【解决方案5】:

      如前所述,strtod(3) 就是答案。

      bool is_double(const char* str) {
          char *end = 0;
          strtod(str, &end);
          // Is the end point of the double the end of string?
          return end == str + strlen(str);
      }
      

      为了解决@Ian Goldby 的担忧,如果在刺痛末尾的空白是一个问题,那么:

      bool is_double(const char* str) {
          char *end = 0;
          strtod(str, &end);
          // Is the end point of the double plus white space the end of string?
          return end + strspn(end, " \t\n\r") == str + strlen(str);
      }
      

      【讨论】:

      • 如果有尾随空格,此示例返回 false。并不是说这一定有什么问题。
      【解决方案6】:

      只需将其转换为双精度值。如果成功,则输入有效。

      真的,您不应该编写自己的规则来决定什么是有效的。您永远不会得到与执行实际转换的库函数完全相同的规则。

      我最喜欢的方法是使用 sscanf(),并检查返回值以确保恰好转换了一个字段。如需额外积分,请使用 %n 参数检查是否没有剩余非空白字符。

      【讨论】:

        猜你喜欢
        • 2022-01-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-27
        • 1970-01-01
        • 1970-01-01
        • 2011-01-08
        相关资源
        最近更新 更多