如何在 C++ 中将字符串转换为双精度值?

Posted

技术标签:

【中文标题】如何在 C++ 中将字符串转换为双精度值?【英文标题】:How can I convert string to double in C++? 【发布时间】:2008-12-25 17:17:21 【问题描述】:

我想要一个在字符串不是数字时返回 0 的函数。

【问题讨论】:

你应该给它一个更具描述性的标题,否则没人会帮忙。 查看类似问题的答案How to parse a string to an int in C++? 下面的一些例子怎么样:codeproject.com/KB/recipes/Tokenizer.aspx 它们非常高效而且有点优雅。 既然可以返回 NaN,为什么还要返回 0? 不是重复的,这是相反的操作。 【参考方案1】:

参见 C++ FAQ Lite How do I convert a std::string to a number?

请参阅 C++ 超级常见问题解答How do I convert a std::string to a number?

请注意,根据您的要求,您无法区分所有允许的零字符串表示形式和非数字字符串。

 // the requested function
 #include <sstream>
 double string_to_double( const std::string& s )
 
   std::istringstream i(s);
   double x;
   if (!(i >> x))
     return 0;
   return x;
  

 // some tests
 #include <cassert>
 int main( int, char** )
 
    // simple case:
    assert( 0.5 == string_to_double( "0.5"    ) );

    // blank space:
    assert( 0.5 == string_to_double( "0.5 "   ) );
    assert( 0.5 == string_to_double( " 0.5"   ) );

    // trailing non digit characters:
    assert( 0.5 == string_to_double( "0.5a"   ) );

    // note that with your requirements you can't distinguish
    // all the the allowed string representation of zero from
    // the non numerical strings:
    assert( 0 == string_to_double( "0"       ) );
    assert( 0 == string_to_double( "0."      ) );
    assert( 0 == string_to_double( "0.0"     ) );
    assert( 0 == string_to_double( "0.00"    ) );
    assert( 0 == string_to_double( "0.0e0"   ) );
    assert( 0 == string_to_double( "0.0e-0"  ) );
    assert( 0 == string_to_double( "0.0e+0"  ) );
    assert( 0 == string_to_double( "+0"      ) );
    assert( 0 == string_to_double( "+0."     ) );
    assert( 0 == string_to_double( "+0.0"    ) );
    assert( 0 == string_to_double( "+0.00"   ) );
    assert( 0 == string_to_double( "+0.0e0"  ) );
    assert( 0 == string_to_double( "+0.0e-0" ) );
    assert( 0 == string_to_double( "+0.0e+0" ) );
    assert( 0 == string_to_double( "-0"      ) );
    assert( 0 == string_to_double( "-0."     ) );
    assert( 0 == string_to_double( "-0.0"    ) );
    assert( 0 == string_to_double( "-0.00"   ) );
    assert( 0 == string_to_double( "-0.0e0"  ) );
    assert( 0 == string_to_double( "-0.0e-0" ) );
    assert( 0 == string_to_double( "-0.0e+0" ) );
    assert( 0 == string_to_double( "foobar"  ) );
    return 0;
 

【讨论】:

【参考方案2】:

最简单的方法是使用boost::lexical_cast:

double value;
try

    value = boost::lexical_cast<double>(my_string);

catch (boost::bad_lexical_cast const&)

    value = 0;

【讨论】:

异常处理不应该用于流控制。 exceptional 条件例外。 @adam,在这种情况下,当 my_string 中存在非数字数据时, boost::lexical_cast() 会抛出。只要 my_string 通常包含一个数字,那么我会说这符合 exceptional 条件。 不幸的是,这看起来适用于“10.5xxxx”。这个字符串也应该失败吗?还是应该返回 10.5?【参考方案3】:

atof 和 strtod 做你想做的,但非常宽容。如果您不想接受像“32asd”这样的字符串有效,则需要将 strtod 包装在这样的函数中:

#include <stdlib.h>
double strict_str2double(char* str)

    char* endptr;
    double value = strtod(str, &endptr);
    if (*endptr) return 0;
    return value;

【讨论】:

请注意,该代码将接受空字符串 :) (endptr == str || *endptr) 应该修复它 如果字符串为空,则值为0。【参考方案4】:

如果它是一个 c 字符串(char 类型的以 null 结尾的数组),您可以执行以下操作:

#include <stdlib.h>
char str[] = "3.14159";
double num = atof(str);

如果是 C++ 字符串,使用 c_str() 方法即可:

double num = atof( cppstr.c_str() );

atof() 将字符串转换为双精度,失败时返回 0。该函数记录在这里:http://www.cplusplus.com/reference/clibrary/cstdlib/atof.html

【讨论】:

【参考方案5】:
#include <iostream>
#include <string>
using namespace std;

int main()

    cout << stod("  99.999  ") << endl;

输出:99.999(双精度,空格被自动去除)

从 C++11 开始,将字符串转换为浮点值(如 double)可用于以下函数:stof - 将 str 转换为 floatstod - 将 str 转换为 doublestold - 将 str 转换为 long double

我想要一个在字符串不是数字时返回 0 的函数。

stod 抛出异常时可以添加 try catch 语句。

【讨论】:

【参考方案6】:

必须说我同意最优雅的解决方案是使用 boost::lexical_cast。然后,您可以捕获可能发生的 bad_lexical_cast,并在它失败时执行某些操作,而不是获得 atof 给出的 0.0。

#include <boost/lexical_cast.hpp>
#include <string>

int main()

    std::string str = "3.14";
    double strVal;
    try 
        strVal = boost::lexical_cast<double>(str);
     catch(bad_lexical_cast&) 
        //Do your errormagic
    
    return 0;

【讨论】:

【参考方案7】:

解决这个问题最优雅的方法之一是使用 @Evgeny Lazin 提到的 boost::lexical_cast。

【讨论】:

【参考方案8】:

我认为atof 正是您想要的。此函数解析字符串并将其转换为双精度。如果字符串不以数字(非数字)开头,则返回 0.0。

但是,它会尝试尽可能多地解析字符串。换句话说,字符串“3abc”将被解释为 3.0。如果你想要一个在这些情况下返回 0.0 的函数,你需要自己编写一个小包装器。

此外,此函数适用于以空字符结尾的字符数组的 C 样式字符串。如果您使用的是字符串对象,则需要在使用此函数之前将其转换为 char*。

【讨论】:

【参考方案9】:

没有一个函数可以做到这一点,因为 0 是一个有效数字,当字符串不是有效数字时,您需要能够捕捉到。

您需要先检查字符串(可能使用正则表达式)以查看它是否仅包含数字和数字标点符号。如果这是您的应用程序需要的,您可以决定返回 0 或将其转换为双精度数。

在查找 atof()strtod() 之后,我应该将我的陈述改写为“不应该”而不是“没有”......呵呵

【讨论】:

【参考方案10】:

在 C 中将字符串转换为双精度的示例 C 程序

#include <iostream>
#include <comutil.h>
#include <iomanip>

bool ParseNumberToDouble(const std::wstring& strInput, double & dResult)

    bool bSucceeded = false;
    dResult = 0;
    if (!strInput.empty() && dResult)
    
        _variant_t varIn = strInput.c_str();
        if (SUCCEEDED(VariantChangeTypeEx(&varIn, &varIn, GetThreadLocale(), 0, VT_R8)))
        
            dResult = varIn.dblVal;
            bSucceeded = true;
        
    
    return bSucceeded;


int main()

    std::wstring strInput = L"1000";
    double dResult = 0;

    ParseNumberToDouble(strInput, dResult);

    return 0;

【讨论】:

以上是关于如何在 C++ 中将字符串转换为双精度值?的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中将字符串转换为双精度

尝试在 C++ 中将字符串转换为双精度时遇到分段错误

在 C# 中将字符串转换为双精度

在java中将十六进制数字字符串转换为双精度数字

尝试将字符串转换为双精度时出错

在 vc++ 中将字符串转换为双精度