std :: string浮动或加倍


98

我正在尝试转换std::stringfloat/double。我试过了:

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

但是它总是返回零。还有其他方法吗?


3
抵制过度改造某些已经在十年前解决的问题的冲动。
haavee

1
您确定输出正确吗?它不应产生零
Johannes Schaub-litb

1
另外,您不需要强制转换atof,它已经返回了double。
AlbertoPL 2009年

我确定。调试器显示0。结果为0。平台:Linux。
Max Frai

13
您确定安装了正确的语言环境吗?尝试“ 0,​​6”或setlocale(LC_NUMERIC,“ C”);
Johannes Schaub-litb

Answers:


125
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则会更快。


7
boost :: lexical_cast正在流式传输。
2009年

1
我认为,您通常不能说它们会带来性能损失。想一想,当您刚接触cin >> num;时会发生什么。用户必须非常快速地键入(像rly jon skeet一样)才能注意到lexical_cast的毫秒数很慢:)也就是说,我相信有些任务中lexical_cast的性能
太糟了

3
对于此解决方案,atof()前面的::是做什么的?它在那里需要什么?
sivabudh'2

4
@ShaChris因为我想确保使用全局命名空间中的atof函数。
TimW 2010年

1
取决于当前的语言环境
nmr

104

标准库(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>


4
我喜欢这种解决方案,但看来它仅来自C ++ 11。因此在我的SDK上不可用。
pamplemousse_mk2

高兴知道C ++标准委员会添加了此内容。ostringstream本身太长了,无法输入,更不用说了..
bobobobo 2014年

4
对于浮点数(如我通过键入“ c ++ string to float”在Google中找到的问题所问),应使用std :: stof。
艾蒂安

1
请注意,这可能会引发异常:std :: invalid_argument(如果转换失败)std :: out_of_range(如果超出范围)
Jason Doucette 2015年

3
买方当心,取决于当前的语言环境。
nmr

29

词法转换非常好。

#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;
}

谢谢,它有效..但这对我来说是个问题:为什么我的代码不起作用。
Max Frai

2
@Johannes Schaub:基于ADL,他可能也有,使用定义加上他实际使用的内容可能会把大量的std元素纳入范围。而且lexical_cast非常慢,所以我没有+1。

boost :: lexical_cast的一个不错的功能是错误处理。如果转换失败,则会引发异常:try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
SemjonMössinger16年

更准确地说,使用catch ( boost::bad_lexical_cast const& err )捕获异常。
SemjonMössinger,

14

您可以使用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");

嗯,所以您认为boost :: lexical_cast有一个糟糕的界面,不是吗?看看stefanB的答案!Boost的作用相同。
kirsche40 2014年

@ kirsche40对于那些尚不依赖Boost的人来说似乎是一个不错的选择(仅与Boost链接以将std :: string转换为数字有点过分!)
Jean-Philippe Jodoin 2014年

@ JEan-Phillippe Jodiun我回答了一条现在删除的评论,有人在其中推荐了Boost。我知道,Boost在大多数情况下都是过分杀伤力的。顺便说一下,一段时间以来,Boost的使用仅限于“较新的”编译器。较旧的项目不能使用Boost。例如,ASIO严重依赖于std :: addressof之类的C ++ 11功能,这对于C ++ 98 / C ++ 03编译器而言毫无价值。恕我直言,当项目开始时,Boost的意图是为较旧的编译器版本提供新的“标准化”功能... :-(
kirsche40 2014年

10

是的,带有词法转换。使用stringstream和<<操作符,或使用Boost,他们已经实现了它。

您自己的版本可能如下所示:

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

  os << x;
  os >> ret;

  return ret;  
}

7

您可以使用boost词法转换:

#include <boost/lexical_cast.hpp>

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

注意:boost :: lexical_cast引发异常,因此当您传递无效值时,您应该准备处理它,请尝试传递字符串(“ xxx”)


5

如果您不想拖动所有增强,请使用strtod(3)from- <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()不起作用...您在使用什么平台/编译器?


使用stringstream不需要增强
jalf

您的方法也返回零。Linux。
Max Frai

3

我在Linux中遇到了同样的问题

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

有用。


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

1
无效的答案,您怎么知道num中存储的值实际上是有效的浮点数?您无需检查sscanf的返回类型,就好像是MS编码样式。

1

这个答案是备份您评论中的litb。我非常怀疑您只是没有正确显示结果。

我曾经发生过完全相同的事情。我花了整整一天的时间来弄清楚为什么我将错误的值赋给64位int,却发现printf忽略了第二个字节。您不能像int一样将64位值传递给printf。


我没有用printf看到的结果...我使用该值来设置窗口的不透明度,和我的窗口是全trasparent,所以值是0
最大Frai

1

C ++ 11的方法是使用std :: stod和std :: to_string。两者都可以在Visual Studio 11中使用。


1

至于为什么atof()在最初的问题中不起作用:将其转换为两倍的事实使我感到怀疑。#include <stdlib.h>如果没有,则代码不应编译,但是如果添加了强制类型转换以解决编译警告,则atof()不会正确声明。如果编译器假定atof()返回的是int,则强制转换将解决转换警告,但不会导致将返回值识别为double。

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

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

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


0

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

但是,当然,如果您仍在使用Boost,则实际上并没有太大的问题。


0

无论如何,您都不希望Boost lexical_cast用于字符串<->浮点。该用例子集是唯一一组始终如一地比旧功能更强大的提升-并且它们基本上集中了所有失败,因为它们自己的性能结果显示,与使用sscanf和printf进行这种转换相比,其性能降低了20-25倍。

自己搜索它。boost :: lexical_cast可以处理大约50次转换,并且如果排除那些涉及浮点数的转换,其效果与显而易见的替代品一样好(或更高)(具有为所有这些操作使用单个API的额外优势)。但是要带上浮标,就像泰坦尼克号一样,在性能方面会碰上冰山。

旧的专用str-> double函数都可以在30毫秒(或更短的时间)内完成10000个解析。lexical_cast大约需要650毫秒才能完成相同的工作。


没有消息来源?我自己用Google
Blake

0

我的问题:

  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 ...花了我很长时间才获得此解决方案。而且我仍然觉得我对字符串本地化和东西还不够了解...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.