web-dev-qa-db-fra.com

C++ 11 std :: to_string (double) - Pas de zéros finaux

Aujourd'hui, j'ai essayé de nouvelles fonctions de la STL C++ 11 et rencontré std::to_string.

Lovely, bel ensemble de fonctions. Créer un objet stringstream pour une seule conversion de chaîne en chaîne me paraissait toujours excessif, alors je suis heureux que nous puissions maintenant faire quelque chose comme ceci:

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

Le résultat?

0.330000

Je ne suis pas entièrement satisfait de cela. Y a-t-il un moyen de dire à std::to_string de laisser de côté les zéros de fin? J'ai cherché sur Internet, mais pour autant que je sache, la fonction ne prend qu'un argument (la valeur à convertir). De retour à l'ancienne avec les chaînes de caractères, vous pouvez définir la largeur du flux, mais je préférerais ne pas reconvertir.

Quelqu'un at-il rencontré ce problème auparavant/a-t-il une solution? Certaines recherches StackOverflow n'ont donné aucun résultat.

(Une référence STL C++ 11: http://fr.cppreference.com/w/cpp/string/basic_string/to_string )

48
Stijn Frishert

La norme C++ 11 dit explicitement (21.5/7):

Retourne: Chaque fonction retourne un objet chaîne contenant la représentation de la valeur de son argument qui serait générée en appelant sprintf (buf, fmt, val) avec un spécificateur de format de "% d", "% u", "% ld ","% lu ","% lld ","% llu ","% f ","% f "ou"% Lf ", respectivement, où buf désigne un tampon de caractères interne de taille suffisante

pour les fonctions déclarées dans cet ordre:

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

Ainsi, vous ne pouvez pas contrôler le formatage de la chaîne résultante.

31
rubenvb

Si tout ce que vous voulez, c'est supprimer les zéros à la fin, eh bien, c'est facile.

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

std::to_string ne vous donne aucun contrôle sur le format; vous obtenez le même résultat que sprintf avec le spécificateur de format approprié pour le type ("%f" dans ce cas).

Si vous avez besoin de plus de flexibilité, vous aurez besoin d'un formateur plus flexible, tel que std::stringstream.

13
Mike Seymour

std::to_string(double) est défini par la norme pour ne renvoyer que la même séquence de caractères que celle générée par sprintf(buf, "%f", value). Ni plus, ni moins, surtout pas moyen de modifier le spécificateur de format. Donc non, vous ne pouvez rien faire.

3
Arne Mertz

Avec boost::to_string, vous ne pouvez pas contrôler le format non plus, mais cela produira un résultat plus proche de ce que vous voyez à l'écran. Idem avec std::lexical_cast<std::string>.

Pour une opération de type fonction avec contrôle de format, utilisez str(boost::format("...format...")% 0.33).

Quelle est la différence entre std :: to_string, boost :: to_string et boost :: lexical_cast <std :: string>?

1
alfC

Créez une fonction de conversion personnalisée, supprimez les zéros de queue si nécessaire. 

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

Les nombres entrés: 

1230
12.30

Compiler avec -std=c++11, puis le résultat:

1230
12.3
0
Kinght 金

Une solution variée au problème puisque to_string ne fonctionne pas . "La formule magique" - mon professeur 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;

Les sorties: 

$0.33
$42.37

toute sortie suivante effectuée avec des nombres décimaux sera définie comme telle.

vous pouvez toujours changer le setf et la précision comme bon vous semble.

0
StackAttack