2016-11-28 3 views
1

Donc j'utilise atof pour convertir ma chaîne en double. Mais j'ai besoin de savoir si je me trompe d'entrée (comme y564 etc.). Comment puis-je le vérifier? J'ai besoin d'un nombre correct pour d'autres actions avec.C++ atof. Comment vérifier la mauvaise entrée?

double x = atof(s.c_str()); 

Répondre

5

Vous pouvez utiliser std::stod:

[live]

bool parse_double(std::string in, double& res) { 
    try { 
     size_t read= 0; 
     res = std::stod(in, &read); 
     if (in.size() != read) 
      return false; 
    } catch (std::invalid_argument) { 
     return false; 
    }  
    return true; 
} 

int main() 
{ 
    double d; 
    bool b = parse_double("123z", d); 
    if (b) 
     std::cout << d; 
    else 
     std::cout << "Wrong input"; 
} 

[modifier]

Vous pouvez trouver here:

Valeur de retour

double valeur correspondant au contenu de str on succès. Si la valeur convertie est hors plage du type de retour, la valeur de retour est indéfinie. Si aucune conversion ne peut être effectuée, 0.0 est renvoyé.

de sorte qu'il est impossible de décider si l'entrée est incorrecte ou contient 0.

+0

Nice. Cependant, 'd' n'est pas imprimé comme non initialisé sur' invalid_argument'? – chi

+0

@chi oui, c'était faux, je l'ai réparé avec un meilleur exemple – marcinj

1

Utilisez std::stod. Il lance des exceptions sur les entrées invalides. Ou, si vous insistez sur les solutions C, utilisez strtod; cela vous donne plus d'informations sur le résultat.

-1

Vous pouvez simplement vérifier si chaque caractère de votre chaîne est un '.' ou std::isdigit(int ch) avant de le passer à atof (et le '.' doit être unique)

Une solution plus compacte est à votre chaîne avec une expression régulière comme ^[0-9]+(\.[0-9]+)?$ qui devrait fonctionner pour les valeurs flottantes génériques.

+1

Ceci est faux. Il peut aussi commencer par un espace, avoir un signe plus ou moins, avoir un préfixe binaire, avoir un exposant décimal ou binaire, être un des éléments inf, nan, nan (...) etc ... – ybungalobill

+0

à droite, mieux en utilisant std :: stod ou similaire pour les entrées génériques à la place. –

1
définition

de atof (http://en.cppreference.com/w/cpp/string/byte/atof):

Valeur de retour

de double valeur correspondant au contenu de str sur la réussite. Si la valeur convertie est hors plage du type de retour, la valeur de retour est indéfinie. Si aucune conversion ne peut être effectuée, 0.0 est renvoyé.

Si vous utilisez c moderne ++ et vous devez maintenant le retour, une meilleure utilisation std::strtod (http://en.cppreference.com/w/cpp/string/byte/strtof):

double strtod(const char* str, char** str_end); 

et sa valeur de retour est définie:

Valeur de retour

Valeur de virgule flottante correspondant au contenu de str on success. Si la valeur convertie est hors plage du type de retour correspondant, une erreur de plage se produit et HUGE_VAL, HUGE_VALF ou HUGE_VALL est renvoyé. Si aucune conversion ne peut être effectuée, 0 est renvoyé et * str_end est défini sur str.

+0

Comment pouvez-vous dire si le texte "0.0" est converti correctement? –

+0

@ ThomasMatthews: vous ne pouvez pas, c'est pourquoi atof n'est pas le meilleur FCT. et la plupart des réponses ont recommandé différentes fonctions avec de meilleures valeurs de retour ... – goeddek

0

Expressions régulières (c.-à-d.libpcre) à la rescousse:

// checked_atof.cpp 
#include <iostream> 
#include <cstdlib> 

#include <pcrecpp.h> 

const char FP_RE[] = "^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?"; 

using namespace std; 

int main() 
{ 
    std:string s; 
    double number; 

    pcrecpp::RE fpre(FP_RE); 

    cout << "Enter a floating point number: " << endl; 
    cin >> s; 

    if (!fpre.FullMatch(s)) { 
    cout << "Sorry, not a valid floating point number!" << endl; 
    } else { 
    number = atof(s.c_str()); 
    cout << "Ok, result: " << number << endl; 
    } 

    return 0; 
} 

Pour plus de détails concernant l'installation/compilation, s'il vous plaît se référer à la documentation libpcre - les éléments suivants peuvent fonctionner sur votre système:

g++ checked_atof.cpp $(pkg-config --cflags libpcrecpp) $(pkg-config --libs libpcrecpp) -o checked_atof

$ ./checked_atof.exe 
Enter a floating point number: 
23.42 
Ok, result: 23.42 

$ ./checked_atof.exe 
Enter a floating point number: 
3.14159e-4 
Ok, result: 0.000314159 

$ ./checked_atof.exe 
Enter a floating point number: 
x9 
Sorry, not a valid floating point number!