提问人:Max Frai 提问时间:6/18/2009 最后编辑:Jan SchultkeMax Frai 更新时间:9/9/2023 访问量:345523
为什么我不能使用 atof 将 std::string 转换为 double?
Why can't I convert a std::string to double using atof?
问:
我正在尝试转换为 .
我试过了:std::string
float/double
std::string num = "0.6";
double temp = (double)atof(num.c_str());
但它总是返回零。还有其他方法吗?
答:
是的,有词汇演员表。使用 stringstream 和 << 运算符,或者使用 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;
}
评论
try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
catch ( boost::bad_lexical_cast const& err )
您可以使用增强词法转换:
#include <boost/lexical_cast.hpp>
string v("0.6");
double dd = boost::lexical_cast<double>(v);
cout << dd << endl;
注意:boost::lexical_cast抛出异常,因此您应该准备好在传递无效值时处理它,请尝试传递string(“xxx”)
如果您不想拖入所有 boost,请使用 from - 它已经返回双精度。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());
对我来说,将字符串转换为双精度是一种有效的 C++ 语法。
您可以使用 stringstream 或 boost::lexical_cast 来做到这一点,但这些都会降低性能。
啊哈哈,你有一个Qt项目......
QString winOpacity("0.6");
double temp = winOpacity.toDouble();
额外注意:
如果输入数据是 ,会更快。const char*
QByteArray::toDouble
评论
您可以使用 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。
评论
与其将 Boost 拖入等式中,不如将字符串(暂时)保留为 a 并使用 .char[]
sprintf()
但是,当然,如果您仍然使用Boost,那真的不是什么大问题。
double myAtof ( string &num){
double tmp;
sscanf ( num.c_str(), "%lf" , &tmp);
return tmp;
}
评论
C++ 11 方法是使用 std::stod 和 std::to_string。两者都适用于 Visual Studio 11。
至于为什么在原来的问题中不起作用:它被投射到双倍的事实让我怀疑。如果没有 ,代码就不应该编译,但如果添加强制转换是为了解决编译警告,则不会正确声明。如果编译器假定返回 int,则强制转换它将解决转换警告,但不会导致返回值被识别为双精度值。atof()
#include <stdlib.h>
atof()
atof()
#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>
评论
ostringstream
我在 Linux 中遇到了同样的问题
double s2f(string str)
{
istringstream buffer(str);
double temp;
buffer >> temp;
return temp;
}
它有效。
无论如何,您都不希望 Boost lexical_cast 用于字符串 <->浮点。该用例子集是唯一一个 boost 始终比旧函数差的集合 - 他们基本上将所有失败都集中在那里,因为他们自己的性能结果显示性能比使用 sscanf 和 printf 进行此类转换慢 20-25 倍。
你自己用谷歌搜索一下。boost::lexical_cast 可以处理大约 50 次转换,如果您排除涉及浮点 #s 的转换,它与明显的替代方案一样好或更好(额外的优势是所有这些操作都使用单个 API)。但是带上花车,就像泰坦尼克号在性能方面撞上冰山一样。
旧的专用 str->double 函数都可以在 30 毫秒(或更好)的时间内完成 10000 次解析。lexical_cast大约需要 650 毫秒才能完成相同的工作。
评论
我的问题:
- 与区域设置无关的字符串为 double(小数点分隔符始终为 '.')
- 字符串转换失败时的错误检测
我的解决方案(使用 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::stof
std::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;
}
注意:你需要一个相当最新的编译器(例如gcc11)来处理浮点类型。std::from_chars
评论