如何检查字符串是否可以转换为双精度C++

How to check if a string can be converted to double in C++?

本文关键字:转换 C++ 双精度 是否 字符串 何检查 检查      更新时间:2023-10-16

我有一个字符串,它可以是一个数字(甚至是浮点数或双精度类型,而不仅仅是整数),它也可以是非数字的单词。

我想

检查这个字符串是否可以转换为双精度,如果是这样,那么我想进行转换。如果是非数字字符串,我想要不同的行为。

我试过这个:

double tmp;
string str;
stringstream ss;
ss << str;
ss >> tmp;
if (ss.fail())
{
    // non-numeric string
}
else
{
    // string to double conversion is successful
}

这段代码的问题在于ss.fail()总是true的,即使tmp包含正确的值。

有一个名为 atof() 的函数将字符串转换为双精度,但这不适合我,因为如果输入字符串是非数字0.0它会返回值。这样我就无法区分非数字和零输入值。

如果你的输入字符串的类型来自 std::string,你可以使用这个函数(它适用于 Windows 和 unix 系统):

#include <stdlib.h>
#include <string>
/**
* @brief checkIsDouble - check inputString is double and if true return double result
* @param inputString - string for checking
* @param result - return double value
* @return true if string is double, false if not
*/
bool checkIsDouble(string inputString, double &result) {
    char* end;
    result = strtod(inputString.c_str(), &end);
    if (end == inputString.c_str() || *end != '') return false;
    return true;
}

std::stod呢?当它无法执行转换时,它将抛出 std::out_of_range。

try
{
    double value = std::stod(input_string);
    std::cout << "Converted string to a value of " << value << std::endl;
}
catch (const std::invalid_argument&)
{
    std::cerr << "No conversion could be performed" << std::endl;
}
catch (const std::out_of_range&)
{
    std::cerr << "Could not convert string to double, value falls out of range" << std::endl;
}

我还没有尝试编译它,但你应该明白这个想法。

也检查空格和流的结尾

if ((ss >> tmp) && (ss >> std::ws).eof() )
{
   // a double
}
提取

一个double值,然后提取任何空格,如果在此期间遇到 eof,则表示您只有有效的double

小心使用 std::ws,因为它会触发 failbit,如果它已经是 EOF。因此,以下建议不适用于"9.000"之类的情况。由于 cl 错误,这在 Visual Studio 2015 中有效。但是在VS2019中,该错误已修复并失败。

if ((ss >> tmp) && (ss >> std::ws).eof() )
{
   // a double
}

您可以考虑以下代码

if ((ss >> tmp) && (  ss.eof() ||  (ss >> std::ws).eof()) )
{
   // a double
}

有关VS错误的详细信息:https://developercommunity.visualstudio.com/t/regression-stdws-incorrectly-sets-failbit-when-the/382896

一个不太像 cpp 的解决方案呢:

double number;
string str;
if (sscanf(str.c_str(), "%lf", &number) != 1)
{
    // non-numeric string
}
else
{
    // string to double conversion is successful
}

什么是有效数字?atof() 会解析什么,还是你对空格有规则?你允许科学记数法,前导-,前导+吗?其他数据可以跟随这个数字吗?必须有小数点还是接受整数?您接受裸前导小数点还是必须以 0 开头?你接受 00.1 吗?你接受 0.1FRED 但拒绝 0.1.2FRED 吗?

atof() 函数 strtod() 现在是针对此问题而设计的,因为它不够健壮,无法处理格式错误的输入。然而,strtod() 不够灵活,无法接受格式正确的输入的特定规则。如果规则很简单,那么编写自己的临时匹配器并不难 - 跳过whitepspace,匹配数字,匹配小数点,匹配数字,跳过空格。如果你需要完全的灵活性,最终你必须求助于正则表达式,这是一种大锤式的答案。