views:

570

answers:

4

In C++ I've got a float/double variable.

when I print this with for example cout the resulting string is period-delimited.

cout << 3.1415 << endl
$> 3.1415

Is there an easy way to force the double to be printed with a comma?

cout << 3.1415 << endl
$> 3,1415
+2  A: 

This is controlled by your program's locale.

How you set a program's default locale depends on the platform. On POSIX type platforms, it's with the LANG and LC_* environment variables, for instance.

You can force a particular locale -- different from the default -- within a C++ program by calling ios::imbue. Something like this might work:

#include <locale>
cout.imbue(std::locale("German_germany"));

The idea is to force a locale where comma is the decimal separator. You might need to adjust the "German_germany" string to get the behavior you want on your particular platform.

Warren Young
using your example results in: std::runtime error locale::facet::_S_create_c_locale name not valid
NomeN
+1  A: 

You need to impue the stream with a different locale, one whose num_punct (iirc) facet specifies a comma.

If your platform locale formats with commas, then

cout.imbue(locale(""));

should be sufficient.

me22
thx, your answer worked. But I'd like to accept an answer that will be more generic (if you're not so lucky with the correct locale presetup on your platform). Still +1 because it's the easiest method.
NomeN
A: 

To be precise, this is controlled by the std::numpunct<charT>::decimal_point() value. You can imbue() another locale with another decimal_point()

MSalters
+3  A: 

imbue() cout with a locale whose numpunct facet's decimal_point() member function returns a comma.

Obtaining such a locale can be done in several ways. You could use a named locale available on your system (std::locale("fr"), perhaps). Alternatively, you could derive your own numpuct, implement the do_decimal_point() member in it.

Example of the second approach:

template<typename CharT>
class DecimalSeparator : public std::numpunct<CharT>
{
public:
    DecimalSeparator(CharT Separator)
    : m_Separator(Separator)
    {}

protected:
    CharT do_decimal_point()const
    {
        return m_Separator;
    }

private:
    CharT m_Separator;
};

Used as:

std::cout.imbue(std::locale(std::cout.getloc(), new DecimalSeparator<char>(',')));
Éric Malenfant
using your example results in: std::runtime error locale::facet::_S_create_c_locale name not valid
NomeN
This error probably means that, on your platform, the "fr" name does not bind to a locale.
Éric Malenfant
I guessed as much, but how could you find out which names *are* bound to a locale.
NomeN
Sadly, I don't think there is a portable way.
Éric Malenfant
do you know it for *nix perhaps?
NomeN
On linux: the locale -a command, but I don't know how to do this programmatically.
Éric Malenfant
programmatically retrieving the locale was no requirement, this works fine. And I guess anybody needing to do this programmatically could do some search-fu on a system() call. Thx! consider your answer accepted.
NomeN