如何在C++中将double转换为字符串?

202

我需要将一个双精度浮点数存储为字符串。我知道可以使用printf来显示它,但我只想将其存储在一个字符串变量中,以便稍后将其存储在映射中(作为,而不是)。


2
一个问题来回答你的问题:为什么要将双精度值存储在字符串中再存储到映射中?你打算使用字符串化的双精度作为键吗?如果不是,为什么不保留双精度值呢? - Matt McClellan
1
有趣的观点。在地图键中使用double可能存在一些风险,因为浮点值上的精确比较总是如此。在字符串表示法上进行索引避免了这个问题。 - Fred Larson
2
为什么要进行转换呢?将其存储在映射表中作为双精度浮点数,并避免进行转换。 - EvilTeach
3
听起来仍然需要使用对象。使用一个联合体会比较合适。每个对象可以插入不同的值,并自我验证。 - EvilTeach
2
我只有一个文件中的一堆名称/值对,不需要使用对象。 - Bill the Lizard
显示剩余4条评论
18个回答

234
// The C way:
char buffer[32];
snprintf(buffer, sizeof(buffer), "%g", myDoubleVar);

// The C++03 way:
std::ostringstream sstream;
sstream << myDoubleVar;
std::string varAsString = sstream.str();

// The C++11 way:
std::string varAsString = std::to_string(myDoubleVar);

// The boost way:
std::string varAsString = boost::lexical_cast<std::string>(myDoubleVar);

15
因为C++ 11的方式而点赞。我是C++新手,不知道有一个to_string函数。我正在使用Microsoft Visual C++ 2013。 - user189198
3
重要提示: "std::to_string" 的精度为6位数字。因此,生成的字符串基本上是一个浮点数而不是双精度。 - Sheradil

198

提升(boost)的方法:

std::string str = boost::lexical_cast<std::string>(dbl);

标准C++的方式:

std::ostringstream strs;
strs << dbl;
std::string str = strs.str();

注意:不要忘记 #include <sstream>


3
我认为boost::lexical_cast基本上就是标准的C++方式,只不过它被很好地打包了。顺便说一句,litb,你在里面有一个小错别字--"boot:lexical_cast"。 - Fred Larson
2
boost::lexical_cast并不仅仅是一个简单的stringstream代码包装器。许多转换程序都是内联实现的。根据这个页面底部的性能测量结果(http://www.boost.org/doc/libs/1_47_0/libs/conversion/lexical_cast.htm),boost::lexical_cast比使用stringstream更快,在大多数情况下,也比scanf/printf更快。 - Ferruccio
1
@Ferr谁说这只是一个简单的包装器了?感谢您提供链接,我实际上确实认为它更多或更少是一个简单的包装器 :) - Johannes Schaub - litb
30
别忘了在 C++ 中使用 #include <sstream> :) - VladL
3
为了记录,如果您不包含#include <sstream>,将会出现错误“不允许不完整类型”。 - user189198
显示剩余2条评论

146

如果您不关心输出格式,可以使用标准C++11方式:

#include <string>

auto str = std::to_string(42.5); 

to_string 是一个新的库函数,引入自 N1803 (r0), N1982 (r1) 和 N2408 (r2) "Simple Numeric Access"。还有 stod 函数可以执行相反的操作。

如果您想要与 "%f" 不同的输出格式,请使用其他答案中所示的 snprintfostringstream 方法。


3
哦,是的宝贝。在Visual Studio 11中,to_string和stod都可以使用。 - BSalita
哦,亲爱的宝贝...在VisualStudio 2010中似乎无法使用to_string()函数 ): 要么是我不知道该怎么用(很有可能)。 - chessofnerd
1
有没有办法让这个函数不添加比所需更多的小数位?当我将双精度数 8.0 转换为字符串时,它会给出字符串 "8.000000",而 "8" 就足够了。 - HelloGoodbye
你可以像这样做:for(int lsd=str.len(); lsd>0 && str[lsd] == '0'; lsd--); str = str.substr(lsd); - Matt G
3
这对于小数字不起作用……例如:1e-9 会产生 0.000000 - FreelanceConsultant

32

在C++11中,您可以使用std::to_string

double d = 3.0;
std::string str = std::to_string(d);

3
我的数字非常小,而 std::to_string() 只返回了 0.000000 而不是科学计数法。 - Irfanullah Jan
@erfan 怎样解决这个问题? - laughing
1
@laughing 一种方法是使用 std::stringstream myStringStream,然后执行 myStringStream << myDouble。你也可以使用 std::setprecision(x) - Irfanullah Jan
1
@erfan,这个不错,谢谢。有没有更短的? - laughing
这个答案和kennytm的回答有何不同? - Rabter

24

如果你使用C++,请避免使用sprintf。它不符合C++的规范,并且存在一些问题。字符串流是首选方法,最好封装成Boost.LexicalCast,这可以很容易地实现:

template <typename T>
std::string to_string(T const& value) {
    stringstream sstr;
    sstr << value;
    return sstr.str();
}

使用方法:

string s = to_string(42.5);

11

sprintf 可以完成这个任务,但在 C++ 中更好、更安全、稍微慢一些的方法是使用 stringstream 进行转换:

#include <sstream>
#include <string>

// In some function:
double d = 453.23;
std::ostringstream os;
os << d;
std::string str = os.str();

您还可以使用Boost.LexicalCast

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

// In some function:
double d = 453.23;
std::string str = boost::lexical_cast<string>(d);

在这两种情况下,str 后应该是 "453.23"。LexicalCast 有一些优点,它确保了转换的完整性。它在内部使用 stringstream


10

我会看一下C++字符串工具库。在其他地方发布过类似的答案。我发现它非常快速可靠。

#include <strtk.hpp>

double pi = M_PI;
std::string pi_as_string  = strtk::type_to_string<double>( pi );

6

lexical_cast的问题在于无法定义精度。通常,如果您将double转换为字符串,那是因为您想将其打印出来。如果精度过高或过低,它会影响您的输出结果。


4

通常情况下,您需要使用C语言默认的ecvt、fcvt或gcvt函数来执行这些操作:

/* gcvt example */
#include <stdio.h>
#include <stdlib.h>

main ()
{
  char buffer [20];
  gcvt (1365.249,6,buffer);
  puts (buffer);
  gcvt (1365.249,3,buffer);
  puts (buffer);
  return 0;
}

Output:
1365.25
1.37e+003   

作为函数:

void double_to_char(double f,char * buffer){
  gcvt(f,10,buffer);
}

4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接