Juste une petite question. J'ai pas mal regardé Internet et j'ai trouvé quelques solutions, mais aucune d'entre elles n'a encore fonctionné. Regarder convertir une chaîne en un entier et je ne veux pas dire des codes ASCII.
Pour un aperçu rapide, nous sommes passés dans une équation sous forme de chaîne. Nous devons le décomposer, le formater correctement et résoudre les équations linéaires. Maintenant, en disant cela, je ne suis pas capable de convertir une chaîne en un entier.
Je sais que la chaîne sera dans le format (-5) ou (25), etc., donc c'est certainement un int. Mais comment pouvons-nous extraire cela d'une chaîne?
Une façon dont je pensais était de lancer une boucle for/while à travers la chaîne, de rechercher un chiffre, d'extraire tous les chiffres suivants et ensuite de voir s'il y avait un '-' en tête, s'il y en a un, multipliez l'int 1.
Cela semble un peu compliqué pour un si petit problème. Des idées?
En C++ 11, il existe quelques nouvelles fonctions de conversion de Nice de std::string
vers un type de nombre.
Donc au lieu de
atoi( str.c_str() )
vous pouvez utiliser
std::stoi( str )
où str
est votre numéro en tant que std::string
.
Il existe des versions pour tous les types de nombres: long stol(string)
, float stof(string)
, double stod(string)
, ... voir http://fr.cppreference.com/w/cpp/string/basic_string/stol
std::istringstream ss(thestring);
ss >> thevalue;
Pour être tout à fait correct, vérifiez les indicateurs d'erreur.
utilisez la fonction atoi pour convertir la chaîne en entier:
string a = "25";
int b = atoi(a.c_str());
Les options possibles sont décrites ci-dessous:
1. Première option: sscanf ()
#include <cstdio>
#include <string>
int i;
float f;
double d;
std::string str;
// string -> integer
if(sscanf(str.c_str(), "%d", &i) != 1)
// error management
// string -> float
if(sscanf(str.c_str(), "%f", &f) != 1)
// error management
// string -> double
if(sscanf(str.c_str(), "%lf", &d) != 1)
// error management
Ceci est une erreur (également montrée par cppcheck) car "scanf sans limites de largeur de champ peut planter avec des données d'entrée énormes sur certaines versions de libc" _ (voir ici et ici ) .
2. Deuxième option: std :: sto * ()
#include <iostream>
#include <string>
int i;
float f;
double d;
std::string str;
try {
// string -> integer
int i = std::stoi(s);
// string -> float
float f = std::stof(s);
// string -> double
double d = std::stod(s);
} catch (...) {
// error management
}
Cette solution est courte et élégante, mais elle n’est disponible que sur les compilateurs conformes C++ 11.
3. Troisième option: sstreams
#include <string>
#include <sstream>
int i;
float f;
double d;
std::string str;
// string -> integer
std::istringstream ( str ) >> i;
// string -> float
std::istringstream ( str ) >> f;
// string -> double
std::istringstream ( str ) >> d;
// error management ??
Cependant, avec cette solution, il est difficile de faire la distinction entre une entrée incorrecte (voir ici ).
4. Quatrième option: lexical_cast de Boost
#include <boost/lexical_cast.hpp>
#include <string>
std::string str;
try {
int i = boost::lexical_cast<int>( str.c_str());
float f = boost::lexical_cast<int>( str.c_str());
double d = boost::lexical_cast<int>( str.c_str());
} catch( boost::bad_lexical_cast const& ) {
// Error management
}
Cependant, il ne s’agit que d’une enveloppe de sstream, et la documentation suggère d’utiliser sstrem pour une meilleure gestion des erreurs (voir ici ).
5. Cinquième option: strto * ()
Cette solution est très longue, en raison de la gestion des erreurs, et est décrite ici. Puisqu'aucune fonction ne retourne un int simple, une conversion est nécessaire en cas de nombre entier (voir ici pour savoir comment cette conversion peut être réalisée).
6. Sixième option: Qt
#include <QString>
#include <string>
bool ok;
std::string;
int i = QString::fromStdString(str).toInt(&ok);
if (!ok)
// Error management
float f = QString::fromStdString(str).toFloat(&ok);
if (!ok)
// Error management
double d = QString::fromStdString(str).toDouble(&ok);
if (!ok)
// Error management
Conclusions
En résumé, la meilleure solution est C++ 11 std :: stoi () ou, en deuxième option, l’utilisation des bibliothèques Qt . Toutes les autres solutions sont déconseillées ou erronées.
Qu'en est-il Boost.Lexical_cast ?
Voici leur exemple:
L'exemple suivant traite les arguments de ligne de commande comme une séquence de données numériques:
int main(int argc, char * argv[])
{
using boost::lexical_cast;
using boost::bad_lexical_cast;
std::vector<short> args;
while(*++argv)
{
try
{
args.Push_back(lexical_cast<short>(*argv));
}
catch(bad_lexical_cast &)
{
args.Push_back(0);
}
}
...
}
Certes, ma solution ne fonctionnerait pas pour les entiers négatifs, mais elle extrairait tous les entiers positifs du texte d'entrée contenant des entiers. Il utilise numeric_only
locale:
int main() {
int num;
std::cin.imbue(std::locale(std::locale(), new numeric_only()));
while ( std::cin >> num)
std::cout << num << std::endl;
return 0;
}
Texte de saisie:
the format (-5) or (25) etc... some text.. and then.. 7987...78hjh.hhjg9878
Entiers de sortie:
5
25
7987
78
9878
La classe numeric_only
est définie comme suit:
struct numeric_only: std::ctype<char>
{
numeric_only(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table()
{
static std::vector<std::ctype_base::mask>
rc(std::ctype<char>::table_size,std::ctype_base::space);
std::fill(&rc['0'], &rc[':'], std::ctype_base::digit);
return &rc[0];
}
};
Démo en ligne complète: http://ideone.com/dRWSj
C'est probablement un peu exagéré, mais boost::lexical_cast<int>( theString )
devrait faire l'affaire Très bien.
Sous Windows, vous pouvez utiliser:
const std::wstring hex = L"0x13";
const std::wstring dec = L"19";
int ret;
if (StrToIntEx(hex.c_str(), STIF_SUPPORT_HEX, &ret)) {
std::cout << ret << "\n";
}
if (StrToIntEx(dec.c_str(), STIF_SUPPORT_HEX, &ret)) {
std::cout << ret << "\n";
}
strtol
, stringstream
besoin de spécifier la base si vous avez besoin d'interpréter hexdécimal.
atoi
est une fonction intégrée qui convertit une chaîne en entier, en supposant que la chaîne commence par une représentation entière.
Mon code:
#include <iostream>
using namespace std;
int main()
{
string s="32"; //String
int n=stoi(s); //Convert to int
cout << n + 1 << endl;
return 0;
}
Eh bien, beaucoup de réponses, beaucoup de possibilités. Ce qui me manque ici, c'est une méthode universelle qui convertit une chaîne en différents types d'intégraux C++ (short, int, long, bool, ...) . J'ai proposé la solution suivante:
#include<sstream>
#include<exception>
#include<string>
#include<type_traits>
using namespace std;
template<typename T>
T toIntegralType(const string &str) {
static_assert(is_integral<T>::value, "Integral type required.");
T ret;
stringstream ss(str);
ss >> ret;
if ( to_string(ret) != str)
throw invalid_argument("Can't convert " + str);
return ret;
}
Voici des exemples d'utilisation:
string str = "123";
int x = toIntegralType<int>(str); // x = 123
str = "123a";
x = toIntegralType<int>(str); // throws exception, because "123a" is not int
str = "1";
bool y = toIntegralType<bool>(str); // y is true
str = "0";
y = toIntegralType<bool>(str); // y is false
str = "00";
y = toIntegralType<bool>(str); // throws exception
Pourquoi ne pas simplement utiliser l'opérateur de sortie stringstream pour convertir une chaîne en un type intégral? Voici la réponse: Supposons qu'une chaîne contienne une valeur dépassant la limite du type intégral prévu. Par exemple, sous Wndows 64, int max est 2147483647 . Attribuons à une chaîne une valeur max int + 1: string str = "2147483648". Maintenant, lors de la conversion de la chaîne en un entier:
stringstream ss(str);
int x;
ss >> x;
x devient 2147483647, ce qui est définitivement une erreur: la chaîne "2147483648" n'était pas censée être convertie en int 2147483647. La fonction fournie toIntegralType détecte ces erreurs et lève une exception.
De http://www.cplusplus.com/reference/string/stoi/
// stoi example
#include <iostream> // std::cout
#include <string> // std::string, std::stoi
int main ()
{
std::string str_dec = "2001, A Space Odyssey";
std::string str_hex = "40c3";
std::string str_bin = "-10010110001";
std::string str_auto = "0x7f";
std::string::size_type sz; // alias of size_t
int i_dec = std::stoi (str_dec,&sz);
int i_hex = std::stoi (str_hex,nullptr,16);
int i_bin = std::stoi (str_bin,nullptr,2);
int i_auto = std::stoi (str_auto,nullptr,0);
std::cout << str_dec << ": " << i_dec << " and [" << str_dec.substr(sz) << "]\n";
std::cout << str_hex << ": " << i_hex << '\n';
std::cout << str_bin << ": " << i_bin << '\n';
std::cout << str_auto << ": " << i_auto << '\n';
return 0;
}
Sortie:
2001, une odyssée de l'espace: 2001 et [ une odyssée de l'espace]
40c3: 16579
-10010110001: -1201
0x7f: 127
ll toll(string a){
ll ret=0;
bool minus=false;
for(auto i:a){
if(i=='-'){ minus=true; continue; }
ret*=10;
ret+=(i-'0');
} if(minus) ret*=-1;
return ret;
# ll is defined as, #define ll long long int
# usage: ll a = toll(string("-1234"));
}
Version à une ligne: long n = strtol(s.c_str(), NULL, base);
.
(s
est la chaîne, et base
est une int
telle que 2, 8, 10, 16.)
Vous pouvez vous référer à ce lien pour plus de détails sur strtol
.
L'idée principale est d'utiliser strtol
function, qui est inclus dans cstdlib
.
Puisque strtol
traite uniquement avec le tableau char
, nous devons convertir string
en tableau char
. Vous pouvez vous référer à ce lien .
Un exemple:
#include <iostream>
#include <string> // string type
#include <bitset> // bitset type used in the output
int main(){
s = "1111000001011010";
long t = strtol(s.c_str(), NULL, 2); // 2 is the base which parse the string
cout << s << endl;
cout << t << endl;
cout << hex << t << endl;
cout << bitset<16> (t) << endl;
return 0;
}
qui produira:
1111000001011010
61530
f05a
1111000001011010