web-dev-qa-db-fra.com

Comment convertir un nombre en chaîne et vice versa en C ++

Puisque cette question est posée toutes les semaines, ceci FAQ pourrait aider beaucoup d'utilisateurs.

  • Comment convertir un entier en chaîne en C++

  • comment convertir une chaîne en un entier en C++

  • comment convertir un nombre à virgule flottante en chaîne en C++

  • comment convertir une chaîne en un nombre à virgule flottante en C++

119
Armen Tsirunyan

Mise à jour pour C++ 11

À partir du C++11 standard, la conversion chaîne à numéro et vice-versa sont intégrés à la bibliothèque standard. Toutes les fonctions suivantes sont présentes dans <string> (conformément au paragraphe 21.5).

chaîne en numérique

float              stof(const string& str, size_t *idx = 0);
double             stod(const string& str, size_t *idx = 0);
long double        stold(const string& str, size_t *idx = 0);
int                stoi(const string& str, size_t *idx = 0, int base = 10);
long               stol(const string& str, size_t *idx = 0, int base = 10);
unsigned long      stoul(const string& str, size_t *idx = 0, int base = 10);
long long          stoll(const string& str, size_t *idx = 0, int base = 10);
unsigned long long stoull(const string& str, size_t *idx = 0, int base = 10);

Chacun de ceux-ci prend une chaîne en entrée et essaiera de la convertir en nombre. Si aucun nombre valide ne peut être construit, par exemple parce qu'il n'y a pas de données numériques ou que le nombre est hors limites pour le type, une exception est levée (std::invalid_argument ou std::out_of_range).

Si la conversion a réussi et que idx n’est pas 0, idx contiendra l'index du premier caractère qui n'a pas été utilisé pour le décodage. Cela pourrait être un index derrière le dernier caractère.

Enfin, les types d’intégraux permettent de spécifier une base. Pour les chiffres supérieurs à 9, l’alphabet est utilisé (a=10 jusqu'à ce que z=35). Vous pouvez trouver plus d'informations sur la mise en forme exacte analysable ici pour nombres à virgule flottante , entiers signés et entiers non signés .

Enfin, pour chaque fonction, il existe également une surcharge qui accepte un std::wstring comme premier paramètre.

numérique en chaîne

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

Celles-ci sont plus simples, vous passez le type numérique approprié et vous récupérez une chaîne. Pour les options de formatage, vous devez revenir à l'option stringsream C++ 03 et utiliser des manipulateurs de flux, comme expliqué dans une autre réponse ici.

Comme indiqué dans les commentaires, ces fonctions retombent dans une précision de mantisse par défaut qui n'est probablement pas la précision maximale. Si votre application nécessite plus de précision, il est également préférable de revenir à d'autres procédures de formatage de chaîne.

Il existe également des fonctions similaires définies nommées to_wstring, ils renverront un std::wstring.

125
KillianDS

Comment convertir un nombre en chaîne en C++ 03

  1. Ne pas utiliser les fonctions itoa ou itof car elles ne sont pas standard et donc pas portable.
  2. Utiliser des flux de chaîne

     #include <sstream>  //include this to use string streams
     #include <string> 
    
    int main()
    {    
        int number = 1234;
    
        std::ostringstream ostr; //output string stream
        ostr << number; //use the string stream just like cout,
        //except the stream prints not to stdout but to a string.
    
        std::string theNumberString = ostr.str(); //the str() function of the stream 
        //returns the string.
    
        //now  theNumberString is "1234"  
    }
    

    Notez que vous pouvez également utiliser les flux de chaîne pour convertir des nombres à virgule flottante en chaîne et pour formater la chaîne à votre guise, comme avec cout.

    std::ostringstream ostr;
    float f = 1.2;
    int i = 3;
    ostr << f << " + " i << " = " << f + i;   
    std::string s = ostr.str();
    //now s is "1.2 + 3 = 4.2" 
    

    Vous pouvez utiliser des manipulateurs de flux, tels que std::endl, std::hex Et les fonctions std::setw(), std::setprecision() etc. avec des flux de chaîne exactement de la même manière qu'avec cout

    Ne confondez passtd::ostringstream Avec std::ostrstream. Ce dernier est obsolète

  3. Utilisez boost lexical cast . Si vous n'êtes pas familier avec boost, c'est une bonne idée de commencer avec une petite bibliothèque comme celle-ci lexical_cast. Pour télécharger et installer boost et sa documentation allez ici . Bien que boost ne soit pas au standard C++, de nombreuses bibliothèques boost sont finalement normalisées et boost est largement considéré comme étant l'une des meilleures bibliothèques C++.

    La distribution lexicale utilise les flux situés en dessous. Cette option est donc fondamentalement la même que la précédente, mais elle est moins détaillée.

    #include <boost/lexical_cast.hpp>
    #include <string>
    
    int main()
    {
       float f = 1.2;
       int i = 42;
       std::string sf = boost::lexical_cast<std::string>(f); //sf is "1.2"
       std::string si = boost::lexical_cast<std::string>(i); //sf is "42"
    }
    

Comment convertir une chaîne en un nombre en C++ 03

  1. L'option la plus légère, héritée de C, est la fonction atoi (pour les entiers (alphabétique à l'entier)) et atof (pour les valeurs à virgule flottante (alphabétique à flottante)). Ces fonctions prennent comme argument une chaîne de style C (const char *) Et donc leur utilisation peut être considéré comme une pratique pas vraiment bonne C++. cplusplus.com a une documentation facile à comprendre sur atoi et atof , y compris sur la manière dont ils se comportent en cas de mauvaise saisie. Toutefois, le lien contient une erreur en ce sens que, conformément à la norme, si le nombre saisi est trop grand pour tenir dans le type de cible, le comportement n'est pas défini.

    #include <cstdlib> //the standard C library header
    #include <string>
    int main()
    {
        std::string si = "12";
        std::string sf = "1.2";
        int i = atoi(si.c_str()); //the c_str() function "converts" 
        double f = atof(sf.c_str()); //std::string to const char*
    }
    
  2. Utiliser des flux de chaîne (flux de chaîne d'entrée, istringstream). Encore une fois, istringstream est utilisé comme cin. Encore une fois, ne confondez pas istringstream avec istrstream. Ce dernier est obsolète.

    #include <sstream>
    #include <string>
    int main()
    {
       std::string inputString = "1234 12.3 44";
       std::istringstream istr(inputString);
       int i1, i2;
       float f;
       istr >> i1 >> f >> i2;
       //i1 is 1234, f is 12.3, i2 is 44  
    }
    
  3. Utilisez boost lexical cast .

    #include <boost/lexical_cast.hpp>
    #include <string>
    
    int main()
    {
       std::string sf = "42.2"; 
       std::string si = "42";
       float f = boost::lexical_cast<float>(sf); //f is 42.2
       int i = boost::lexical_cast<int>(si);  //i is 42
    }       
    

    En cas de mauvaise entrée, lexical_cast Lève une exception de type boost::bad_lexical_cast

84
Armen Tsirunyan

En C++ 17, les nouvelles fonctions std :: to_chars et std :: from_chars sont introduites dans l'en-tête charconv .

std :: to_chars est indépendant de la localisation, non alloué et non lancé.

Seul un petit sous-ensemble de règles de formatage utilisées par d'autres bibliothèques (telles que std :: sprintf) est fourni.

De std :: to_chars , de même pour std :: from_chars .

La garantie que std :: from_chars puisse récupérer chaque valeur à virgule flottante formatée exactement par to_chars n'est fournie que si les deux fonctions proviennent de la même implémentation.

 // See en.cppreference.com for more information, including format control.
#include <cstdio>
#include <cstddef>
#include <cstdlib>
#include <cassert>
#include <charconv>

using Type =  /* Any fundamental type */ ;
std::size_t buffer_size = /* ... */ ;

[[noreturn]] void report_and_exit(int ret, const char *output) noexcept 
{
    std::printf("%s\n", output);
    std::exit(ret);
}
void check(const std::errc &ec) noexcept
{
    if (ec ==  std::errc::value_too_large)
        report_and_exit(1, "Failed");
}
int main() {
    char buffer[buffer_size];        
    Type val_to_be_converted, result_of_converted_back;

    auto result1 = std::to_chars(buffer, buffer + buffer_size,  val_to_be_converted);
    check(result1.ec);
    *result1.ptr = '\0';

    auto result2 = std::from_chars(buffer, result1.ptr, result_of_converted_back);
    check(result2.ec);

    assert(val_to_be_converted == result_of_converted_back);
    report_and_exit(0, buffer);
}

Bien que cela ne soit pas entièrement mis en œuvre par les compilateurs, il le sera certainement.

2
JiaHao Xu

J'ai volé cette classe convienent quelque part ici chez StackOverflow pour convertir tout ce qui peut être streamé en chaîne:

// make_string
class make_string {
public:
  template <typename T>
  make_string& operator<<( T const & val ) {
    buffer_ << val;
    return *this;
  }
  operator std::string() const {
    return buffer_.str();
  }
private:
  std::ostringstream buffer_;
};

Et puis vous l'utilisez comme;

string str = make_string() << 6 << 8 << "hello";

Assez chouette!

J'utilise également cette fonction pour convertir des chaînes en n'importe quoi pouvant être streamé, bien que ce ne soit pas très sûr si vous essayez d'analyser une chaîne ne contenant pas de nombre; (et ce n'est pas aussi intelligent que le dernier)

// parse_string
template <typename RETURN_TYPE, typename STRING_TYPE>
RETURN_TYPE parse_string(const STRING_TYPE& str) {
  std::stringstream buf;
  buf << str;
  RETURN_TYPE val;
  buf >> val;
  return val;
}

Utilisé comme:

int x = parse_string<int>("78");

Vous pourriez aussi vouloir des versions pour wstrings.

0
Viktor Sehr