Vous ne pouvez généralement pas dire qu'ils viennent avec une pénalité de performance, je pense. Pensez à ce qui se passe quand juste avant vous avez un cin >> num ;. L'utilisateur devrait taper très rapidement (rly jon skeet like) pour ne jamais remarquer que lexical_cast en millisecondes est plus lent :) Cela dit, je crois qu'il y a des tâches où lexical_cast est juste trop performant :)
Johannes Schaub - litb
3
Pour cette solution, que fait le :: devant atof ()? De quoi a-t-il besoin pour être là?
sivabudh
4
@ShaChris Parce que je veux m'assurer que j'utilise la fonction atof de l'espace de noms global.
TimW
1
dépend de la locale actuelle
nmr
104
La bibliothèque standard (C ++ 11) offre la fonctionnalité souhaitée avec std::stod:
std::string s ="0.6"
std::wstring ws ="0.7"double d = std::stod(s);double dw = std::stod(ws);
Généralement pour la plupart des autres types de base, voir <string> . Il existe également de nouvelles fonctionnalités pour les chaînes C. Voir<stdlib.h>
J'aime cette solution, mais il semble que ce soit uniquement à partir de C ++ 11. Donc pas disponible sur mon SDK.
pamplemousse_mk2
C'est formidable de savoir que le comité des normes C ++ a ajouté cela. ostringstreamen soi était tout simplement trop long à taper, et encore moins à utiliser ..
bobobobo
4
Pour les floats (comme demandé dans la question que j'ai trouvée avec google en tapant "c ++ string to float"), il faut utiliser std :: stof.
Étienne
1
Juste une note que cela peut lever des exceptions: std :: invalid_argument (si la conversion a échoué) std :: out_of_range (si hors de la plage)
Jason Doucette
3
Attention l'acheteur, cela dépend de la localisation actuelle.
Merci, ça marche ... Mais c'est une question pour moi: pourquoi mon code ne fonctionne pas.
Max Frai
2
@Johannes Schaub: Basé sur ADL, il pourrait tout aussi bien avoir, les définitions d'utilisation plus ce qu'il utilise réellement apporteront probablement un grand nombre d'éléments std. De plus, lexical_cast est incroyablement lent, donc pas de +1 de ma part.
Une fonctionnalité intéressante de boost :: lexical_cast est la gestion des erreurs. Si une conversion échoue, une exception est levée:try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
Semjon Mössinger
Pour être plus précis, utilisez catch ( boost::bad_lexical_cast const& err )pour attraper l'exception.
Semjon Mössinger
14
Vous pouvez utiliser std :: stringstream:
#include<sstream>#include<string>template<typename T>
T StringToNumber(const std::string& numberAsString){
T valor;
std::stringstream stream(numberAsString);
stream >> valor;if(stream.fail()){
std::runtime_error e(numberAsString);throw e;}return valor;}
Euh, alors vous pensez que boost :: lexical_cast a une interface terrible, n'est-ce pas? Regardez la réponse de stefanB! Boost fait de même.
kirsche40
@ kirsche40 Cela semble être une bonne alternative pour les personnes qui n'ont pas déjà de dépendances avec Boost (créer une liaison avec Boost uniquement pour convertir une chaîne std :: string en nombres est un peu exagéré!)
Jean-Philippe Jodoin
@ JEan-Phillippe Jodiun J'ai répondu à un commentaire maintenant supprimé, où quelqu'un a recommandé Boost. Je suis conscient que Boost est la plupart du temps exagéré. D'ailleurs, depuis un certain temps maintenant, l'utilisation de Boost est limitée aux compilateurs "plus récents". Les projets plus anciens ne peuvent pas utiliser Boost. Par exemple, ASIO dépend fortement des fonctionnalités C ++ 11 comme std :: addressof, ce qui le rend totalement inutile pour les compilateurs C ++ 98 / C ++ 03. À mon humble avis, lorsque le projet a commencé, il était l'intention de Boost de fournir de nouvelles fonctionnalités «standardisées» pour les anciennes versions de compilateur ... :-(
kirsche40
10
Oui, avec une distribution lexicale. Utilisez un stringstream et l'opérateur <<, ou utilisez Boost, ils l'ont déjà implémenté.
Votre propre version pourrait ressembler à:
template<typename to,typename from>to lexical_cast(from const&x){
std::stringstream os;
to ret;
os << x;
os >> ret;return ret;}
Remarque: boost :: lexical_cast lève une exception, vous devez donc être prêt à y faire face lorsque vous passez une valeur non valide, essayez de passer une chaîne ("xxx")
Réponse non valide, comment savoir que la valeur stockée dans num est en fait un nombre à virgule flottante valide? vous ne vérifiez pas le type de retour de sscanf, cela ressemble à un style de codage MS.
1
Cette réponse se confirme dans vos commentaires. Je soupçonne profondément que vous n’affichez pas correctement le résultat.
J'ai eu exactement la même chose qui m'est arrivée une fois. J'ai passé une journée entière à essayer de comprendre pourquoi j'obtenais une mauvaise valeur dans un int 64 bits, pour découvrir que printf ignorait le deuxième octet. Vous ne pouvez pas simplement passer une valeur 64 bits dans printf comme un int.
Je n'utilise pas printf pour voir les résultats ... Et j'utilise cette valeur pour définir l'opacité de la fenêtre, et ma fenêtre est totalement transparente, donc la valeur est 0.
Max Frai
1
La méthode C ++ 11 consiste à utiliser std :: stod et std :: to_string. Les deux fonctionnent dans Visual Studio 11.
Quant à savoir pourquoi atof()ne fonctionne pas dans la question initiale: le fait qu'elle soit doublée me rend suspect. Le code ne doit pas être compilé sans #include <stdlib.h>, mais si le cast a été ajouté pour résoudre un avertissement de compilation, il atof()n'est pas correctement déclaré. Si le compilateur suppose qu'il atof()renvoie un int, le cast résoudra l'avertissement de conversion, mais cela ne fera pas reconnaître la valeur de retour comme un double.
#include<stdlib.h>#include<string>...
std::string num ="0.6";double temp = atof(num.c_str());
Vous ne voulez pas Boost lexical_cast pour la chaîne <-> virgule flottante de toute façon. Ce sous-ensemble de cas d'utilisation est le seul ensemble pour lequel le boost est systématiquement pire que les anciennes fonctions - et ils ont essentiellement concentré tous leurs échecs là-bas, car leurs propres résultats de performances montrent des performances 20-25X PLUS LENT que l'utilisation de sscanf et printf pour de telles conversions.
Google vous-même. boost :: lexical_cast peut gérer quelque chose comme 50 conversions et si vous excluez celles impliquant des # virgules flottantes, c'est aussi bon ou meilleur que les alternatives évidentes (avec l'avantage supplémentaire d'avoir une seule API pour toutes ces opérations). Mais apportez des flotteurs et c'est comme le Titanic frappant un iceberg en termes de performances.
Les anciennes fonctions str-> double dédiées peuvent toutes faire 10000 analyses en quelque chose comme 30 ms (ou mieux). lexical_cast prend environ 650 ms pour faire le même travail.
Chaîne indépendante des paramètres régionaux à doubler (séparateur décimal toujours '.')
Détection d'erreur si la conversion de chaîne échoue
Ma solution (utilise la fonction Windows _wcstod_l):
// string to convert. Note: decimal seperator is ',' here
std::wstring str = L"1,101";// Use this for error detectionwchar_t* stopString;// Create a locale for "C". Thus a '.' is expected as decimal separatordouble dbl = _wcstod_l(str.c_str(),&stopString, _create_locale(LC_ALL,"C"));if(wcslen(stopString)!=0){// ... error handling ... we'll run into this because of the separator}
HTH ... m'a pris assez de temps pour arriver à cette solution. Et j'ai toujours le sentiment de ne pas en savoir assez sur la localisation des cordes et tout ça ...
Réponses:
Le fait-il pour moi, c'est une syntaxe C ++ valide pour convertir une chaîne en double.
Vous pouvez le faire avec le stringstream ou boost :: lexical_cast mais ceux-ci viennent avec une pénalité de performance.
Ahaha vous avez un projet Qt ...
Remarque supplémentaire:
si les données d'entrée sont a
const char*
, ceQByteArray::toDouble
sera plus rapide.la source
La bibliothèque standard (C ++ 11) offre la fonctionnalité souhaitée avec
std::stod
:Généralement pour la plupart des autres types de base, voir
<string>
. Il existe également de nouvelles fonctionnalités pour les chaînes C. Voir<stdlib.h>
la source
ostringstream
en soi était tout simplement trop long à taper, et encore moins à utiliser ..Le casting lexical est très agréable.
la source
try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
catch ( boost::bad_lexical_cast const& err )
pour attraper l'exception.Vous pouvez utiliser std :: stringstream:
Usage:
la source
Oui, avec une distribution lexicale. Utilisez un stringstream et l'opérateur <<, ou utilisez Boost, ils l'ont déjà implémenté.
Votre propre version pourrait ressembler à:
la source
Vous pouvez utiliser boost lexical cast:
Remarque: boost :: lexical_cast lève une exception, vous devez donc être prêt à y faire face lorsque vous passez une valeur non valide, essayez de passer une chaîne ("xxx")
la source
Si vous ne voulez pas faire glisser tout le boost, utilisez
strtod(3)
from<cstdlib>
- il renvoie déjà un double.Les sorties:
Pourquoi atof () ne fonctionne pas ... sur quelle plate-forme / compilateur êtes-vous?
la source
J'ai eu le même problème sous Linux
Ça marche.
la source
la source
Cette réponse se confirme dans vos commentaires. Je soupçonne profondément que vous n’affichez pas correctement le résultat.
J'ai eu exactement la même chose qui m'est arrivée une fois. J'ai passé une journée entière à essayer de comprendre pourquoi j'obtenais une mauvaise valeur dans un int 64 bits, pour découvrir que printf ignorait le deuxième octet. Vous ne pouvez pas simplement passer une valeur 64 bits dans printf comme un int.
la source
La méthode C ++ 11 consiste à utiliser std :: stod et std :: to_string. Les deux fonctionnent dans Visual Studio 11.
la source
Quant à savoir pourquoi
atof()
ne fonctionne pas dans la question initiale: le fait qu'elle soit doublée me rend suspect. Le code ne doit pas être compilé sans#include <stdlib.h>
, mais si le cast a été ajouté pour résoudre un avertissement de compilation, ilatof()
n'est pas correctement déclaré. Si le compilateur suppose qu'ilatof()
renvoie un int, le cast résoudra l'avertissement de conversion, mais cela ne fera pas reconnaître la valeur de retour comme un double.devrait fonctionner sans avertissement.
la source
Plutôt que de faire glisser Boost dans l'équation, vous pouvez conserver votre chaîne (temporairement) en tant que
char[]
et l'utilisersprintf()
.Mais bien sûr, si vous utilisez de toute façon Boost, ce n'est vraiment pas trop un problème.
la source
Vous ne voulez pas Boost lexical_cast pour la chaîne <-> virgule flottante de toute façon. Ce sous-ensemble de cas d'utilisation est le seul ensemble pour lequel le boost est systématiquement pire que les anciennes fonctions - et ils ont essentiellement concentré tous leurs échecs là-bas, car leurs propres résultats de performances montrent des performances 20-25X PLUS LENT que l'utilisation de sscanf et printf pour de telles conversions.
Google vous-même. boost :: lexical_cast peut gérer quelque chose comme 50 conversions et si vous excluez celles impliquant des # virgules flottantes, c'est aussi bon ou meilleur que les alternatives évidentes (avec l'avantage supplémentaire d'avoir une seule API pour toutes ces opérations). Mais apportez des flotteurs et c'est comme le Titanic frappant un iceberg en termes de performances.
Les anciennes fonctions str-> double dédiées peuvent toutes faire 10000 analyses en quelque chose comme 30 ms (ou mieux). lexical_cast prend environ 650 ms pour faire le même travail.
la source
Mon problème:
Ma solution (utilise la fonction Windows _wcstod_l):
HTH ... m'a pris assez de temps pour arriver à cette solution. Et j'ai toujours le sentiment de ne pas en savoir assez sur la localisation des cordes et tout ça ...
la source