C + + 11 std: : to_string (double)-没有后面的零

今天我尝试了 C + + 11 STL 的一些新功能,遇到了 std::to_string

很好,很好的一套功能。只为一个双字符串转换创建一个 string stream 对象对我来说似乎总是有些过头,所以我很高兴我们现在可以做这样的事情:

std::cout << std::to_string(0.33) << std::endl;

结果呢?

0.330000

我对此并不完全满意。有没有办法告诉 std::to_string去掉后面的零?我搜索了互联网,但就我所知,该函数只有一个参数(要转换的值)。在使用字符串流的“旧时代”,您可以设置流的宽度,但是我宁愿不要转换回来。

有人曾经遇到过这个问题/有解决方案吗? 一些 StackOverflow 搜索没有得到任何结果。

(A C + + 11 STL 引用: http://en.cppreference.com/w/cpp/string/basic_string/to_string)

61183 次浏览

std::to_string不允许您控制格式; 您可以使用适当的类型格式说明符(在本例中为 "%f")获得与 sprintf相同的结果。

如果您需要更多的灵活性,那么您将需要更灵活的格式化程序-如 std::stringstream

std::to_string(double)由标准定义,只返回由 sprintf(buf, "%f", value)生成的相同字符序列。不多,不少,特别是没有办法调整格式说明符。所以你什么也做不了。

C + + 11标准明确表示(21.5/7) :

返回: 每个函数返回一个字符串对象,这个字符串对象包含参数值的字符表示形式,这个字符表示形式将通过调用 sprintf (buf、 fmt、 val)来生成,格式说明符分别为“% d”、“% u”、“% ld”、“% lu”、“% llu”、“% f”、“% f”、“% f”或“% Lf”,其中 buf 指定一个足够大小的内部字符缓冲区

对于以下顺序声明的函数:

string to_string(int val);
string to_string(unsigned val);
string to_string(long val);
string to_string(unsigned long val);
string to_string(long long val);
string to_string(unsigned long long val);
string to_string(float val);
string to_string(double val);
string to_string(long double val);

因此,您无法控制结果字符串的格式。

如果你只想删除后面的零,那很简单。

std::string str = std::to_string (f);
str.erase ( str.find_last_not_of('0') + 1, std::string::npos );
str.erase ( str.find_last_not_of('.') + 1, std::string::npos );

省略后面的零:

std::ostringstream oss;
oss << std::setprecision(8) << std::noshowpoint << double_value;
std::string str = oss.str();

注: #include <sstream>#include <iomanip>

由于 to_string不起作用,这个问题的解决方案多种多样。 “魔法公式”——我的 CS2400老师

std::cout.setf(ios::fixed);
std::cout.setf(ios::showpoint);
std::cout.precision(2);


const double x = 0.33, y = 42.3748;
std::cout << "$" << x << std::endl;
std::cout << "$" << y << std::endl;

产出:

$0.33
$42.37

以下任何十进制数的输出都将按此设置。

您总是可以根据需要更改 setf 和精度。

创建一个自定义转换函数,如果需要,删除尾部零。

//! 2018.05.14 13:19:20 CST
#include <string>
#include <sstream>
#include <iostream>
using namespace std;


//! Create a custom convert function, remove the tailing zeros if necessary.
template<typename T>
std::string tostring(const T &n) {
std::ostringstream oss;
oss << n;
string s =  oss.str();
int dotpos = s.find_first_of('.');
if(dotpos!=std::string::npos){
int ipos = s.size()-1;
while(s[ipos]=='0' && ipos>dotpos){
--ipos;
}
s.erase ( ipos + 1, std::string::npos );
}
return s;
}


int main(){
std::cout<< tostring(1230)<<endl;
std::cout<< tostring(12.30)<<endl;
}

输入号码:

1230
12.30

使用 -std=c++11编译,然后结果是:

1230
12.3

使用 boost::to_string你也不能控制格式,但是它会输出一些更接近你在屏幕上看到的东西。std::lexical_cast<std::string>也一样。

对于具有格式控制的类函数操作,请使用 str(boost::format("...format...")% 0.33)

Std: : to _ string、 ost: : to _ string 和 ost: : lexical _ cast < std: : string > 之间的区别是什么?

编写一个通用的 helper 函数,比如下面这样的函数,您可以在 C + + 项目中对它进行修整。

inline static const string roundDouble(const double input, const int decimal_places)
{
ostringstream str;
str << fixed << setprecision(decimal_places);
str << input;
return str.str();
}

有了 C + + 20,我们终于可以拥抱 std::format的力量!让我们希望海湾合作委员会和 Clang 将赶上 MSVC 并尽快实现它。

std::cout << std::format("{}\n", 0.33);