2009-09-14 15 views
9

In C++ ho una variabile float/double.Come stampare una doppia con una virgola

Quando si stampa questo ad esempio cout, la stringa risultante è delimitata periodicamente.

cout << 3.1415 << endl 
$> 3.1415 

C'è un modo semplice per forzare il doppio a essere stampato con una virgola?

cout << 3.1415 << endl 
$> 3,1415 

risposta

11

imbue() cout con funzione di decimal_point() membro un locale cui numpunct di sfaccettatura restituisce una virgola.

Ottenere tale locale può essere fatto in diversi modi. È possibile utilizzare una locale denominata disponibile sul proprio sistema (forse std::locale("fr")). In alternativa, è possibile ottenere il proprio numpuct, implementare il membro do_decimal_point() in esso.

Esempio del secondo approccio:

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

utilizzato come:

std::cout.imbue(std::locale(std::cout.getloc(), new DecimalSeparator<char>(','))); 
+0

utilizzo dell'esempio restituisce: std :: errore di runtime locale :: facet :: _ S_create_c_locale nome non valido – NomeN

+0

Questo errore probabilmente significa che, sulla piattaforma, il nome "fr" non si associa a una locale. –

+0

Immaginai tanto, ma come hai potuto scoprire quali nomi * sono * legato a un locale. – NomeN

2

Questo è controllato dal locale del programma.

Come si imposta la locale predefinita di un programma dipende dalla piattaforma. Su piattaforme di tipo POSIX, ad esempio, sono le variabili di ambiente LANG e LC_ *.

È possibile forzare una locale specifica, diversa dall'impostazione predefinita, all'interno di un programma C++ chiamando ios :: imbue. Qualcosa del genere potrebbe funzionare:

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

L'idea è di forzare un locale in cui la virgola è il separatore decimale. Potrebbe essere necessario regolare la stringa "German_germany" per ottenere il comportamento desiderato sulla piattaforma specifica.

+0

utilizzando l'esempio risulta in: std :: errore di runtime locale :: facet :: _ S_create_c_locale nome non valido – NomeN

3

È necessario imporre lo streaming con un diverso locale, uno il cui num_punct (iirc) sfaccettatura specifica una virgola.

Se i formati di locale piattaforma con virgole, poi

cout.imbue(locale("")); 

dovrebbero essere sufficienti.

+0

t hx, la tua risposta ha funzionato. Ma mi piacerebbe accettare una risposta che sarà più generica (se non sei così fortunato con il presetup locale corretto sulla tua piattaforma). Ancora +1 perché è il metodo più semplice. – NomeN

1

Per la precisione, questo è controllato dal valore std::numpunct<charT>::decimal_point(). È possibile imbue() un altro locale con un altro decimal_point()

0

thread vecchio, ma comunque ... Uno dovrebbe essere consapevole che l'utilizzo di un std::locale rende la stringa "abbastanza", completa con il punto decimale corretto, separatori di migliaia e cosa no, a seconda della piattaforma e del locale. Molto probabilmente, usando imbue() si interromperà qualsiasi analisi della stringa dopo che è stata formattata.Per esempio:

std::ostringstream s; 
std::locale l("fr-fr"); 
s << "without locale: " << 1234.56L << std::endl; 
s.imbue(l); 
s << "with fr locale: " << 1234.56L << std::endl; 
std::cout << s.str(); 

ha pronunciato la seguente uscita:
without locale: 1234.56
with fr locale: 1 234,56

Utilizzando strtod() o simili sulla seconda corda probabilmente non funzionerà molto bene ... Inoltre, lo spazio tra "1 "e" 2 "nella seconda stringa di output è uno stringente, rendendo la stringa ancora più carina :-)

Problemi correlati