6
votes

Chaîne à la conversion de points flottant avec support pour la virgule décimale et la virgule décimale

Comment convertir une chaîne à un numéro de point flottant si je veux interpréter les deux virgules comme une virgule décimale et un point interprété comme point décimal?

Le code analyse des fichiers texte créés par nos clients. Ils utilisent parfois des points décimaux et parfois des virgules décimales mais jamais mille séparateurs.

c++

2 commentaires

Vous ne pouvez pas substituer aux virgules pour un point décimal comme une étape de pré-traitement? Les facettes de localisation des iostreams seraient la voie à suivre, mais bonne chance d'essayer de les comprendre ...


Je suis d'accord avec Nim, chaque fois que je le fais, je normalise simplement les données d'entrée avant de traiter


3 Réponses :


4
votes

Il suffit de chercher la virgule décimale ',' code> et le convertit en un '.' code>, puis utilisez atof code> à partir de CODE>:

#include <cstdlib>
#include <cstdio>
#include <string>

double toDouble(std::string s){
    // do not use a reference, since we're going to modify this string
    // If you do not care about ',' or '.' in your string use a 
    // reference instead.
    size_t found = s.find(",");
    if(found != std::string::npos)
        s[found]='.'; // Change ',' to '.'
    return std::atof(s.c_str());
}

int main(){
    std::string aStr("0.012");
    std::string bStr("0,012");

    double aDbl = toDouble(aStr);
    double bDbl = toDouble(bStr);

    std::printf("%lf %lf\n",aDbl,bDbl);
    return 0;    
}


2 commentaires

Soyez prudent avec l'un des deux symboles utilisés comme des milliers de séparateur! Selon votre entrée, vous pouvez convertir 100.546,89 à 100.546.89 qui n'est pas un numéro légal. Assurez-vous de vérifier cela


@NICK: Je suis d'accord, SHOP a déclaré que «ils utilisent parfois des points décimaux et parfois des virgules décimales mais jamais mille séparateurs », donc ce problème ne devrait donc pas se produire.



13
votes

Utiliser std :: remplacer pour faire le travail acharné: xxx

Si vous devez faire face à des milliers de séparateurs, il serait beaucoup plus difficile.


0 commentaires

0
votes

Si vous voulez le faire dans le cadre de la lecture normale d'un std :: istream Vous créeriez un std :: num_get <...> facette , mettez-le dans un objet std :: locale objet et installez cela dans votre flux à l'aide de IMBUE () (ou en définissant le std :: locale En tant que local mondial avant de créer le flux).


2 commentaires

Puis-je créer une facette personnalisée :: num_get <...> facette sans écrire mon propre parseur à point flottant de zéro?


Eh bien, oui et non. La partie intéressante de l'analyse ponctuelle flottante transforme une chaîne en un double . Cet exemple strtod () peut faire. Cependant, vous devrez mettre les personnages pour cela ensemble. Ceci est un peu ennuyeux mais pas si difficile.