在 C + + 中将 float 转换为 std: : string

我有一个浮点值,需要放入一个 std::string。如何从 float 转换为 string?

float val = 2.5;
std::string my_val = val; // error here
306277 次浏览

Unless you're worried about performance, use string streams:

#include <sstream>
//..


std::ostringstream ss;
ss << myFloat;
std::string s(ss.str());

If you're okay with Boost, lexical_cast<> is a convenient alternative:

std::string s = boost::lexical_cast<std::string>(myFloat);

Efficient alternatives are e.g. FastFormat or simply the C-style functions.

If you're worried about performance, check out the Boost::lexical_cast library.

You can define a template which will work not only just with doubles, but with other types as well.

template <typename T> string tostr(const T& t) {
ostringstream os;
os<<t;
return os.str();
}

Then you can use it for other types.

double x = 14.4;
int y = 21;


string sx = tostr(x);
string sy = tostr(y);

As of C++11, the standard C++ library provides the function std::to_string(arg) with various supported types for arg.

This tutorial gives a simple, yet elegant, solution, which i transcribe:

#include <sstream>
#include <string>
#include <stdexcept>


class BadConversion : public std::runtime_error {
public:
BadConversion(std::string const& s)
: std::runtime_error(s)
{ }
};


inline std::string stringify(double x)
{
std::ostringstream o;
if (!(o << x))
throw BadConversion("stringify(double)");
return o.str();
}
...
std::string my_val = stringify(val);

Important:
Read the note at the end.

Quick answer :
Use to_string(). (available since c++11)
example :

#include <iostream>
#include <string>


using namespace std;
int main ()
{
string pi = "pi is " + to_string(3.1415926);
cout<< "pi = "<< pi << endl;


return 0;
}

run it yourself : http://ideone.com/7ejfaU
These are available as well :

string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned 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);

Important Note:
As @Michael Konečný rightfully pointed out, using to_string() is risky at best that is its very likely to cause unexpected results.
From http://en.cppreference.com/w/cpp/string/basic_string/to_string :

With floating point types std::to_string may yield unexpected results as the number of significant digits in the returned string can be zero, see the example.
The return value may differ significantly from what std::cout prints by default, see the example. std::to_string relies on the current locale for formatting purposes, and therefore concurrent calls to std::to_string from multiple threads may result in partial serialization of calls. C++17 provides std::to_chars as a higher-performance locale-independent alternative.

The best way would be to use stringstream as others such as @dcp demonstrated in his answer.:

This issue is demonstrated in the following example :
run the example yourself : https://www.jdoodle.com/embed/v0/T4k

#include <iostream>
#include <sstream>
#include <string>


template < typename Type > std::string to_str (const Type & t)
{
std::ostringstream os;
os << t;
return os.str ();
}


int main ()
{


// more info : https://en.cppreference.com/w/cpp/string/basic_string/to_string
double    f = 23.43;
double    f2 = 1e-9;
double    f3 = 1e40;
double    f4 = 1e-40;
double    f5 = 123456789;
std::string f_str = std::to_string (f);
std::string f_str2 = std::to_string (f2); // Note: returns "0.000000"
std::string f_str3 = std::to_string (f3); // Note: Does not return "1e+40".
std::string f_str4 = std::to_string (f4); // Note: returns "0.000000"
std::string f_str5 = std::to_string (f5);


std::cout << "std::cout: " << f << '\n'
<< "to_string: " << f_str << '\n'
<< "ostringstream: " << to_str (f) << "\n\n"
<< "std::cout: " << f2 << '\n'
<< "to_string: " << f_str2 << '\n'
<< "ostringstream: " << to_str (f2) << "\n\n"
<< "std::cout: " << f3 << '\n'
<< "to_string: " << f_str3 << '\n'
<< "ostringstream: " << to_str (f3) << "\n\n"
<< "std::cout: " << f4 << '\n'
<< "to_string: " << f_str4 << '\n'
<< "ostringstream: " << to_str (f4) << "\n\n"
<< "std::cout: " << f5 << '\n'
<< "to_string: " << f_str5 << '\n'
<< "ostringstream: " << to_str (f5) << '\n';


return 0;
}

output :

std::cout: 23.43
to_string: 23.430000
ostringstream: 23.43


std::cout: 1e-09
to_string: 0.000000
ostringstream: 1e-09


std::cout: 1e+40
to_string: 10000000000000000303786028427003666890752.000000
ostringstream: 1e+40


std::cout: 1e-40
to_string: 0.000000
ostringstream: 1e-40


std::cout: 1.23457e+08
to_string: 123456789.000000
ostringstream: 1.23457e+08

You can use std::to_string in C++11

float val = 2.5;
std::string my_val = std::to_string(val);

Use std::to_chars once your standard library provides it:

std::array<char, 32> buf;
auto result = std::to_chars(buf.data(), buf.data() + buf.size(), val);
if (result.ec == std::errc()) {
auto str = std::string(buf.data(), result.ptr - buf.data());
// use the string
} else {
// handle the error
}

The advantages of this method are:

  • It is locale-independent, preventing bugs when writing data into formats such as JSON that require '.' as a decimal point
  • It provides shortest decimal representation with round trip guarantees
  • It is potentially more efficient than other standard methods because it doesn't use the locale and doesn't require allocation

Unfortunately std::to_string is of limited utility with floating point because it uses the fixed representation, rounding small values to zero and producing long strings for large values, e.g.

auto s1 = std::to_string(1e+40);
// s1 == 10000000000000000303786028427003666890752.000000


auto s2 = std::to_string(1e-40);
// s2 == 0.000000

C++20 might get a more convenient std::format API with the same benefits as std::to_chars if the P0645 standards proposal gets approved.