要浮动或双精度的字符串

我正试着把 std::string转换成 float/double。 我试过:

std::string num = "0.6";
double temp = (double)atof(num.c_str());

但结果总是零,还有别的办法吗?

331971 次浏览

是的,使用词法强制转换。使用字符串流和 < < 操作符,或者使用 Boost,他们已经实现了它。

你自己的版本可能是这样的:

template<typename to, typename from>to lexical_cast(from const &x) {
std::stringstream os;
to ret;


os << x;
os >> ret;


return ret;
}

词汇表演很不错。

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


using std::endl;
using std::cout;
using std::string;
using boost::lexical_cast;


int main() {
string str = "0.6";
double dub = lexical_cast<double>(str);
cout << dub << endl;
}

你可以使用增强词法强制转换:

#include <boost/lexical_cast.hpp>


string v("0.6");
double dd = boost::lexical_cast<double>(v);
cout << dd << endl;

注意: ost: : lexical _ cast 抛出异常,因此在传递无效值时应该准备好处理异常,尝试传递字符串(“ xxx”)

如果你不想拖入所有的提升,去 strtod(3)<cstdlib>-它已经返回一个双。

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>


using namespace std;


int main()  {
std::string  num = "0.6";
double temp = ::strtod(num.c_str(), 0);


cout << num << " " << temp << endl;
return 0;
}

产出:

$ g++ -o s s.cc
$ ./s
0.6 0.6
$

为什么 atof ()不能工作... ... 您使用的是什么平台/编译器?

std::string num = "0.6";
double temp = ::atof(num.c_str());

对我来说,将字符串转换为 double 是一种有效的 C + + 语法。

您可以使用字符串流或者升级: : lexical _ cast 来完成,但是这些都会带来性能损失。


啊哈哈,你有一个 QT 项目..。

QString winOpacity("0.6");
double temp = winOpacity.toDouble();

附加说明:
如果输入数据是 const char*,那么 QByteArray::toDouble会更快。

You can use std::stringstream:

   #include <sstream>
#include <string>
template<typename T>
T StringToNumber(const std::string& numberAsString)
{
T valor;


std::stringstream stream(numberAsString);
stream >> valor;
if (stream.fail()) {
std::runtime_error e(numberAsString);
throw e;
}
return valor;
}

用法:

double number= StringToNumber<double>("0.6");

这个答案在你的评论中支持 litb。我深深地怀疑你只是没有正确地展示结果。

我也经历过同样的事。我花了一整天的时间试图弄清楚为什么我在64位 int 中获得了一个坏值,结果发现 printf 忽略了第二个字节。您不能像传递 int 一样将64位值传递给 printf。

您可以将字符串(暂时)保留为 char[]并使用 sprintf(),而不是将 Boost 拖入方程式中。

当然,如果您正在使用 Boost,那么它真的不是什么大问题。

   double myAtof ( string &num){
double tmp;
sscanf ( num.c_str(), "%lf" , &tmp);
return tmp;
}

The C++ 11 way is to use std::stod and std::to_string. Both work in Visual Studio 11.

至于为什么 atof()在最初的问题中不起作用: 事实上,它被投到双倍让我怀疑。代码在没有 #include <stdlib.h>的情况下不应该编译,但是如果添加强制转换是为了解决编译警告,那么就没有正确地声明 atof()。如果编译器假定 atof()返回一个 int 值,那么强制转换将解决转换警告,但是 没有将导致返回值被识别为 double。

#include <stdlib.h>
#include <string>


...
std::string num = "0.6";
double temp = atof(num.c_str());

应该在没有警告的情况下工作。

标准库(C + + 11)使用 std::stod提供了所需的功能:

std::string  s  = "0.6"
std::wstring ws = "0.7"
double d  = std::stod(s);
double dw = std::stod(ws);

对于大多数其他基本类型,参见 <string>。 C 字符串也有一些新特性。参见 <stdlib.h>

我在 Linux 上也遇到过同样的问题

double s2f(string str)
{
istringstream buffer(str);
double temp;
buffer >> temp;
return temp;
}

很管用。

You don't want Boost lexical_cast for string <-> floating point anyway. That subset of use cases is the only set for which boost consistently is worse than the older functions- and they basically concentrated all their failure there, because their own performance results show a 20-25X SLOWER performance than using sscanf and printf for such conversions.

你自己谷歌一下。Lexical _ cast 可以处理大约50个转换,如果你排除了那些包含浮点数的转换,那么它的效果就和其他明显的替代方案一样好或者更好(还有一个额外的好处,就是对所有这些操作都有一个单一的 API)。但是带来漂浮物,就像泰坦尼克号撞上冰山一样。

旧的、专用的 str-> double 函数都可以在大约30ms (或更快)的时间内完成10000次解析。Lexical _ cast 需要大约650ms 来完成相同的工作。

My Problem:

  1. 语言环境独立字符串双精度(小数点总是’。’)
  2. 字符串转换失败时的错误检测

我的解决方案(使用 Windows 函数 _ wcstod _ l) :

// string to convert. Note: decimal seperator is ',' here
std::wstring str = L"1,101";


// Use this for error detection
wchar_t* stopString;


// Create a locale for "C". Thus a '.' is expected as decimal separator
double dbl = _wcstod_l(str.c_str(), &stopString, _create_locale(LC_ALL, "C"));


if (wcslen(stopString) != 0)
{
// ... error handling ... we'll run into this because of the separator
}

HTH... 我花了很长时间才得到这个解决方案。而且我仍然觉得我对字符串本地化之类的知识还不够..。

使用 C + + 17,您可以使用 std::from_chars,它比 std::stofstd::stod重量更轻、速度更快。它不涉及任何内存分配或查看语言环境,而且它是非抛出的。

std::from_chars函数返回一个类型为 from_chars_result的值,该值基本上是一个包含两个字段的结构:

struct from_chars_result {
const char* ptr;
std::errc ec;
};

通过检查 ec,我们可以判断转换是否成功:

#include <iostream>
#include <charconv>


int main()
{
const std::string str { "12345678901234.123456" };
double value = 0.0;
auto [p, ec] = std::from_chars(str.data(), str.data() + str.size(), value);
if (ec != std::errc()) {
std::cout << "Couldn't convert value";
}
    

return 0;
}

注意: std::from_chars需要一个相当新的编译器(例如 gcc11)来处理浮点类型。