Bonjour, j'ai 2 nombres ayant comme type std::string. Y a t-il un moyen de les additionner, par exemple en surchargeant l'operateur + ?
merci.
Version imprimable
Bonjour, j'ai 2 nombres ayant comme type std::string. Y a t-il un moyen de les additionner, par exemple en surchargeant l'operateur + ?
merci.
Salut,
Etrange comme formulation mais soit !Citation:
j'ai 2 nombres ayant comme type std::string
Il est tout a fait possible de le faire. Je te laisse aller sur google et taper un truc du genre "C++ surcharge des operateurs" tu verras de suite comment ca fonctionne et quelles possibiltes cela t'offre.
Bon courage
J'ai dejà essayer de surcharger l'operateur + mais sans succes. J'ai regardé un peu sur le net, et pareil.
un indice?
Voilà ce que j'avais tenté...
Et ça serait encore mieux si ça pouvait me retourner le resultat sous forme de std::string.Code:
1
2
3
4
5
6 int operator & +(std::string nb1, std::string nb2) { int res; res=nb1+nb2; return res; }
merci
???Citation:
Voilà ce que j'avais tenté...
Code :
int operator & +(std::string nb1, std::string nb2)
{
int res;
res=nb1+nb2;
return res;
}
Outre les fautes de logique et de syntaxe, pourquoi surcharger cet operateur si c pour mettre a l'interieur :
avec nb1 et nb2 string !!! :DCode:res=nb1+nb2;
Sinon dans la doc de la classe string du C++ (tout premier endroit ou il est tres utils de chercher en cas de pb) :
http://www.cppreference.com/cppstrin...operators.html
Tous les operateurs utiles dont + sont deja definis :P
Ben je sais pas, moi ça me semblais logique ce que j'avais fait :aie:
Mais, j'ai pas compris comment faire avec ce qui est dans la doc.
Il y a bien ça:
Mais je suppose que si je passe en parametre: 2 et 6 ça va me retourner 26, et non 8...Code:string operator+(const string& s1, const string& s2 );
Oula ... :cry:
2 : int
6 : int
"2" : string, char*, ... ca depend
si tu fais "2"+"6" ca doit probablement marcher ;)
A revoir les bases des types de donnees C++ :D
hello,
je vois pas trop ce que tu veux faire mais peut être que ça peut t'aider:
http://www.cplusplus.com/reference/c...dlib/atoi.html
atoi Convert string to integer (function)
atol Convert string to long integer (function)
atof Convert string to double (function)
strtol Convert string to long integer (function)
Salut à tous !
Personnellement, je me pose la question de la pertinence de représenter des chiffres sous forme de chaînes de caractères. À mon avis, il faut revoir la conception.
Sinon, au niveau des chaînes de caractères, l'opérateur d'addition est surchargé et effectue une concaténation. Ainsi, le programme suivant :
Retourne sur la sortie standard la chaine « abcdef. »Code:
1
2
3
4
5
6
7
8
9
10 #include <string> #include <iostream> int main (int argc, char **argv) { const std::string chaine1 = "abc"; const std::string chaine2 = "def"; std::cout << chaine1 + chaine2 << std::endl; return 0; } // main
Pour convertir une chaîne de caractères en entier, il existe deux méthodes en C++. La première vient du C, elle consiste à utiliser la fonction atoi de la bibliothèque standard C :
Le code précédent retourne « 14 » sur la sortie standard.Code:
1
2
3
4
5
6
7
8
9
10 #include <string> #include <iostream> #include <cstd> int main (int argc, char **argv) { const std::string chaine = "12"; const int entier = std::atoi(chaine) + 2; std::cout << entier << std::endl; } // main
La deuxième méthode consiste à utiliser un flux sur une chaîne de caractères :
Ce code également affiche « 14 » sur la sortie standard.Code:
1
2
3
4
5
6
7
8
9
10
11
12 #include <string> #include <iostream> #include <sstream> int main (int argc, char **argv) { std::string chaine = "12"; std::istringstream ist (chaine); int entier; ist >> entier; std::cout << entier + 2 << std::endl; } // main
Pour surcharger l'opérateur d'addition, tu peux faire ça :
Mais je te déconseille cette approche. À mon avis il faut revoir la façon dont tu stockes tes données.Code:
1
2
3
4
5
6
7
8
9 #include <string> #include <cstd> // ... int operator + (const std::string &chaine1, const std::string &chaine2) { return std::atoi(chaine1) + std::atoi(chaine2); } // int operator + (const std::string &, const std::string &)
À bientôt.
Le Farfadet Spatial
...Où les fonction convertir_en_int et convertir_en_string restent à déterminer...Code:
1
2
3
4
5
6
7 std::string operator+(std::string nb1, std::string nb2) { int res = convertir_en_int(nb1) + convertir_en_int(nb2); return convertir_en_string(res); }
Cela dit, c'est curieux de redéfinir cet opérateur pour les std::string alors qu'il existe deja.
Du coup tu ne pourras plus faire quelque chose du genre :
Edit : grilléCode:
1
2
3
4
5 std::string a = "chaine alpha1"; std::string b = "chaine alpha2"; a + b;
Salut à tous !
Je suis bien d'accord.
Ceci, en revanche, n'est pas tout à fait exacte. Si jamais l'opérateur d'addition est surchargé de la façon que j'ai proposée, alors ceci :Citation:
Du coup tu ne pourras plus faire quelque chose du genre :
Code:
1
2
3
4
5 std::string a = "chaine alpha1"; std::string b = "chaine alpha2"; a + b;
Affichera sur la sortie standard : « 122 = 14. »Code:
1
2
3
4
5
6 const std::string chaine1 = "12"; const std::string chaine2 = "2"; const std::string chaine3 = chaine1 + chaine2; const int entier = chaine1 + chaine2; std::cout << chaine3 << " = " << entier << std::endl;
Par contre, le compilateur indiquera une ambiguïté au moment de la compilation pour le code suivant :
À bientôt.Code:
1
2
3
4 const std::string chaine1 = "12"; const std::string chaine2 = "2"; std::cout << chaine1 + chaine2 << std::endl;
Le Farfadet Spatial
Sans doute qu'il récupère les valeurs d'un flux externe. Un fichier par exemple.
La meilleure solution consiste à procéder en 2 étapes:
1/ on transforme la chaine de caractères en int (et s'il vous plait, arêtez avec atoi et autres joyeusetés du C, nous sommes sur un forum c++). La solution est, une fois de plus, dans la faq: ici
2/ additionner les deux entiers.
Mais koala va vous expliquer tout ça en détail ;)
edit: quant à la surcharge de d'addition de string, elle est à proscrire définitivement pour plusieurs raisons, et notamment pour la simple et bonne raison que l'on ne pourra plus concaténer des strings avec l'operateur +.
edit2:
As-tu testé? Non. Si l'operateur + est surchargé comme tu le dis, string3 = string1 + string2 ne compilera pas.Citation:
Envoyé par farfadet spatial
Salut,
Il faut commencer par convertir chaque chaine en entier.
La classe stringstream est là pour t'y aider ;)
Je ne crois vraiment pas que la surcharge de l'opérateur + soit réellement conseillée...
L'idéal serait plutôt, selon moi, de créer une classe personnelle qui se chargera de la transformation "transparente" de la chaine de caractères en entier, et utilisera directement la valeur convertie, avec éventuellement les opérateurs + et - ;)
Horreur et calamité...
les fonctions ato* sont à éviter autant que possible, comme c'est le cas de toutes les fonctions issues directement du C.
Le C++ est un langage qui fournit énormément de possibilités plus sécurisantes à l'emploi que la grosse majorité des fonctions héritées du C, et il est donc fortement recommandé de leur préférer à chaque fois les possibilités C++.
Dans le cas qui nous intéresse, les *stringstream sont pleinement qualifiés pour effectuer le travail.
Ainsi, un simple code du genre de
fera parfaitement l'affaire ;) (requière un #include <sstream> avant la déclaration de "ss" ;))Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 int additionne(const std::string& i1, const std::string& i2) { /* déclare un flux de conversion */ std::stringstream ss; /* introduit les valeurs sous forme de chaines dans le flux de conversion */ ss<<s1<<" "<<s2; int op1; int op2; if(!(ss>>op1>>op2)) { /* ce qu'il faut faire si l'une des chaines n'est pas compatible avec * les nombres entiers */ } /* renvoie l'addition des deux opérandes récupérés. */ return op1+op2; }
Merci pour toutes vos réponses. Je vais essayer tout ça. Et pour répondre à certains qui se demandent pourquoi je dois faire ça, c'est que j'ai des variables qui prennent leur valeurs dans le contenu d'un fichier texte.
ex:
Le fichier texte:
Et dans mon code j'ai une variable std::string saQuantité a laquelle j'affecte la quantité (en string) lu dans le fichier texte.Code:
1
2
3 Nom: toto Année: 2001 Quantité: 6
Mais par la suite je peux avoir besoin d'additionner deux quantités. Voilà pourquoi.
Merci encore.
Bonjour,
Personnellement je ne suis pas tout à fait d'accord avec le fait de ne pas utiliser atoi.
Le comportement de la fonction atoi est décrit ici, et l'on peut voir qu'il se comporte aussi surement qu'un stringstream.
Et utiliser la fonction atoi est beaucoup plus léger que de créer une classe, d'allouer la chaine de caractères de la classe dynamiquement, de copier tous les caractères dans la stringstream, et d'utiliser un flux pour convertir en int.
Code:
1
2
3
4 int additionne(const std::string& i1, const std::string& i2) { return atoi(i1.c_str())+atoi(i2.c_str()); }
Pour moi la première fonction est préférable à tous points de vue. Les classes de la STL sont très utiles, mais je ne vois aucune raison valable de ne pas utiliser certaines fonctions du C pur, quand c'est plus pratique, plus court, et plus performant.Code:
1
2
3
4
5
6
7
8 int additionne(const std::string& i1, const std::string& i2) { std::stringstream ss; ss<<s1<<" "<<s2; int op1 = 0; int op2 = 0; return op1+op2; }
Salut à tous !
Oui, c'est bien pour ça que je pense et visiblement je ne suis pas le seul, qu'il ne vaut mieux pas enregistrer l'entier dans une chaîne, mais utiliser un flux. Peut-être n'ai-je pas été assez clair.
Au temps pour moi : je viens de le tester avec gcc et ça ne fonctionne pas, en effet.Citation:
Envoyé par r0d
etCitation:
Envoyé par r0d
Ah ! Ben flûte, alors... Il va falloir que j'arrête d'utiliser les fonctions de cmath, sous prétexte que c'est du C... Ça tombe mal, j'en ai besoin tous les jours.Citation:
Envoyé par koala01
Je suis bien d'accord d'une part que trop souvent on trouve un mélange de C et C++ imbuvable, généralement peu efficace et de toute façon difficile à lire et à maintenir. Et ceci est on ne peut plus vrai :
Et oui, nous sommes bien d'accord, lorsqu'on lit les données dans un fichier, les flux sont une bien meilleure solution, car plus sécurisés et permettant beaucoup plus de traitements de manière simple et élégante et que les fonctions de la bibliothèque standard C.Citation:
Envoyé par koala01
Cela dit, la bibliothèque standard C a été encapsulée pour être utilisée proprement en C++ et parfois c'est une solution propre, efficace et élégante. Par exemple, lorsque dans ma ligne de commande, j'attends en deuxième argument un entier, il n'y a aucun problème pour écrire :
Plutôt que de faire un flux sur une chaîne, qui demande tout de même un peu plus de travail, tout ça pour un unique entier...Code:
1
2 int val = atoi(argv[2]);
À bientôt.
Le Farfadet Spatial
Ce qu'il y a, c'est que la grosse majorité des cas où tu va avoir besoin de convertir un entier en une chaine et vice-versa (voire un objet en chaine), c'est dans un contexte de flux...
Ce sera parce que tu voudra lire ou écrire dans un fichier, ou parce que tu voudra envoyer ou recevoir les données au travers d'un système quelconque de transmission, basé sur la transmission de caractères.
Dés lors, il semble tout de suite logique de passer par des flux, et le flux de conversion stringstream (i ou o selon le cas) est un prétendant des plus logique ;)
Salut à tous !
Dans la majorité des cas, oui, mais pas toujours... Sachons avoir un peu de souplesse (je dis ça pour moi aussi) ! D'autant que, comme le fait remarquer Coyotte504, les fonctions ato* ne sont pas moins sécurisées que des flux, juste beaucoup moins versatiles.
Cela dit, maintenant, nous savons que Nyko17 est en train de lire un fichier, donc, en effet, nous pouvons lui donner ce judicieux conseil : utilise des flux, sacrebleu !
À bientôt.
Le Farfadet Spatial
J'ai encore un petit problème:
Voici l'en-tête de mon fichier:
Voici la fonction concernée:Code:
1
2
3
4
5 #include <sstream> #include <iostream> #include <list> #include <fstream>
Et les erreurs:Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 std::string ListeVins::convertiEnIntetAjoute(std::string & Qt1, std::string & Qt2) { std::istringstream iss( Qt1 ); //ici int laQt1; iss >> laQt1; std::istringstream iss( Qt2 ); // et là int laQt2; iss >> laQt2; int res= laQt1 + laQt2; std::ostringstream oss; oss << res; std::string result = oss.str(); return result; }
ici: erreur: 'std::istringstream iss' previously declared here
là: erreur: redeclaration of 'std::istringstream iss'
Salut,
ça veut juste dire que tu utilises deux fois le même nom pour tes variables.
haha quel bougre d'âne je fais! Vive moi :yaisse2:
ou pas...:aie:
La raison principale est la sémantique.
Reprenons dans l'ordre tes arguments:
- plus pratique
c'est, à mon avis, une interprétation personnelle. J'ai l'habitude d'utiliser les flux, et pour moi, par le fait même de cette habitude, il m'est plus pratique d'utiliser les flux.
- plus court
c'est un argument valable, mais il ne se suffit pas à lui-même. Souvent, à vouloir faire du code très court il en devient illisible. Dans le cas d'un code qui génère le même asm, je préfère un code d'une ligne de plus et plus lisible, plus sémantiquement correct, qu'un code de une ligne moins explicite.
- plus performant
il faut bien comprendre que dans 99% des questions posées sur ce forum, et dans 80% du code professionnellement écrit chaque jours, les performances ne sont pas importante. Malgrès que ce soit une problématique passionnante, je crois il ne faut pas se focaliser là-dessus (sauf exception - sans mauvais jeu de mot ;) ).
En revanche, ce qui me parait plus important, c'est la sémantique. Conserver une bonne sémantique permet de:
1/ Bien utiliser et comprendre les concepts du langage qu'on utilise.
2/ Fournir aux gens qui vont lire nos sources (souvent nous-même) un code lisible et cohérent.
3/ Améliorer la modularité de son code sans avoir même à y penser. Le concept même de modularité (en ingénierie générale, pas seulement en développement logiciel) est né sur la notion de standard. En respectant les standard, on se place de fait, sans même y penser, dans un cadre de modularité.
Un exemple concret pour ce 3eme point qui peut paraître un argument fumeux "philosophique" bref, bidon:
En utilisant les flux pour ses conversions et pour la lecture de son fichier, cet utilisateur se serait sans doute rendu compte qu'il pouvait (comme l'a noté Le Farfadet Spatial) directement lire ses données en tant qu'entiers, et non en tant que chaines de caractères. Et là on y gagne à tous les niveaux (taille du code, performance, sémantique, modularité, maintenabilité...)
Il ne faut pas non plus être extrêmiste, mais le respect des standards et de la philosophie du langage qu'on utilise me parait bon dans le sens où cela résous, sans même qu'on ait besoin d'y penser, beaucoup de problèmes. Cet argumentaire est valable pour bien d'autres points (const conformité, encapsulation, etc...)
That's my point.
Salut à tous !
Bon, cela ne fait pas longtemps que j'interviens sur ce forum, donc vous ne me connaissez pas encore, aussi vous préviens-je : j'aime la philosophie. Cela dit, je pense que je n'en rajouterais pas beaucoup plus, dans la mesure où j'ai l'impression que nous disons un peu tous la même chose.
Tout à fait d'accord.
Pareil, je te rejoins complètement.Citation:
- plus court
c'est un argument valable, mais il ne se suffit pas à lui-même. Souvent, à vouloir faire du code très court il en devient illisible. Dans le cas d'un code qui génère le même asm, je préfère un code d'une ligne de plus et plus lisible, plus sémantiquement correct, qu'un code de une ligne moins explicite.
C'est tellement vrai !Citation:
- plus performant
il faut bien comprendre que dans 99% des questions posées sur ce forum, et dans 80% du code professionnellement écrit chaque jours, les performances ne sont pas importante. Malgrès que ce soit une problématique passionnante, je crois il ne faut pas se focaliser là-dessus (sauf exception - sans mauvais jeu de mot ;) ).
Mon travail, c'est la modélisation. C'est-à-dire que je fais du calcul massif sur ordinateurs : autant dire sans doute une des branches de l'informatique qui est la plus friande de performances (1 % de performances en plus peut faire gagner parfois jusqu'à quelques jours et les calculateurs sont mutualisés). Pourtant, les codes de calculs contiennent assez peu de gros bricolages pour gagner des cycles. D'autant moins que les compilateurs modernes font d'excellentes optimisations, souvent meilleures que ce que peut faire un être humain et le font mieux si le code est proche de l'algorithme, plutôt que de comprendre plein de choses bizarroïdes.
Certes, mais dans le cas particulier suivant, cette solution :Citation:
En revanche, ce qui me parait plus important, c'est la sémantique. Conserver une bonne sémantique permet de:
1/ Bien utiliser et comprendre les concepts du langage qu'on utilise.
2/ Fournir aux gens qui vont lire nos sources (souvent nous-même) un code lisible et cohérent.
3/ Améliorer la modularité de son code sans avoir même à y penser. Le concept même de modularité (en ingénierie générale, pas seulement en développement logiciel) est né sur la notion de standard. En respectant les standard, on se place de fait, sans même y penser, dans un cadre de modularité.
Est-elle moins lisible, modulaire et plus éloignée des concepts du C++ que celle là :Code:
1
2 const int valeur = std::atoi(argv[1]);
Je ne le pense pas. En plus, dans le deuxième cas, on perd la possibilité de déclarer « valeur » comme étant constant, ce qui est pourtant est une pratique qui a beaucoup d'intérêt.Code:
1
2
3
4
5 const std::string chaine = argv[1]; std::istringstream ist (chaine); int valeur; ist >> valeur;
En effet.Citation:
Il ne faut pas non plus être extrêmiste, mais le respect des standards et de la philosophie du langage qu'on utilise me parait bon dans le sens où cela résous, sans même qu'on ait besoin d'y penser, beaucoup de problèmes. Cet argumentaire est valable pour bien d'autres points (const conformité, encapsulation, etc...)
And you've got one !Citation:
That's my point.
À bientôt.
Le Farfadet Spatial
Re-salut à tous !
Pour essayer d'être un peu ordonné, je fais un deuxième message, cette fois vraiment directement lié au problème de Nyko17.
Au delà du problème d'utiliser plusieurs fois le même nom de variable, ce que tu as bien évidemment corrigé, je pense que tu fais toujours fausse route. Cette idée d'ajouter des entiers stockés sous forme de chaînes de caractères est conceptuellement bancale : soit on a une chaîne de caractère, soit un entier, mais lorsque l'on fait un amalgame entre les deux, alors le typage devient incertain et c'est la source de nombreuses bogues.
À mon avis, il faut que tu abandonnes complètement l'idée d'avoir des chaînes que tu ne convertirais qu'à l'occasion. Au contraire, je te conseille de lire ton fichier ligne par ligne et que tu stockes le résultat à l'aide de quelque chose de ce genre :
Ainsi, tu peux tester le format de chaque ligne de ton fichier. Si dans l'une des lignes du fichier tu trouves la sous-chaîne « Quantité: » alors stocke la valeur de quantité dans un entier. Quelque chose dans ce goût :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include <fstream> #include <string> #include <sstream> // ... std::ifstream fichier (nomFichier); if (file.bad()) throw InvalidFile (); std::string chaine; // ... while (file) { std::getline(fichier, chaine); if (file.bad()) throw InvalidFile (); // ... } // ...
Ainsi, « quantite » est vraiment un entier et fini les bricolages.Code:
1
2
3
4
5
6
7
8
9
10
11 // ... if (chaine.find("Quantité:") != npos) { std::istringstream iss (chaine); std::string temp; int quantite; iss >> temp >> quantite; } // ...
À bientôt.
Le Farfadet Spatial
Ca marcherait si j'enregistrais les infos de cette manière dans le fichier:
mais je les enregistre de celle là:Code:
1
2
3 nom: toto année: 2000 quantité: 2
Donc je ne peux pas chercher la chaine "quantité:".Code:
1
2
3 toto 2000 2
Je pourrais donc revoir la façon dont j'enregistre les infos mais j'ai des délais à respecter pour rendre mon projet, et je suis pas en avance, donc je vais rester sur la methode avec sstream qui a l'air de marcher.
Mais merci de l'info ;)
Salut à tous !
Mais alors, c'est encore plus simple ! Point n'est besoin de changer la façon de stocker tes données ! Lis tes données par trois :
C'est tellement plus simple, plus rapide, plus C++, plus performant, plus sécurisé, etc., que je ne vois même pas pourquoi faire autrement !Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 // ... #include <fstream> #include <string> // ... std::ifstream fichier (nomFichier); // ... while (fichier) { // ... std::string label; int date, quantite; fichier >> label >> date >> annee; // ... } // ...
À bientôt.
Le Farfadet Spatial
Pourquoi dans ce cas ne pas faire ainsi?
Code:
1
2
3
4
5
6
7
8
9 string nom; int annee; int quantite; ifstream f("monfichier"); getline(f, nom); f >> annee; f >> quantite;
Salut à tous !
Tu n'es pas encore assez rapide, petit scarabée !
Sinon, tu oublies juste un champs, donc ça risque de ne pas bien se passer : il faut aussi enregistrer le label. D'autant qu'il doit sans doute l'utiliser. Cela dit, nous avons la même idée...
À bientôt.
Le Farfadet Spatial
Salut, ma variable "nom" correspond à ton label.
Ne vaut-il mieux pas utiliser getline pour le nom, dans le cas où il y a un espace?