C # a une fonction de syntaxe où vous pouvez concaténer de nombreux types de données sur une seule ligne.
string s = new String();
s += "Hello world, " + myInt + niceToSeeYouString;
s += someChar1 + interestingDecimal + someChar2;
Quel serait l'équivalent en C ++? Pour autant que je sache, vous devrez tout faire sur des lignes séparées car il ne prend pas en charge plusieurs chaînes / variables avec l'opérateur +. C'est correct, mais cela n'a pas l'air aussi soigné.
string s;
s += "Hello world, " + "nice to see you, " + "or not.";
Le code ci-dessus produit une erreur.
c++
string
compiler-errors
concatenation
Nick Bolton
la source
la source
char *
pointeurs les uns aux autres. C'est ce qui génère l'erreur - car la somme des pointeurs n'a pas de sens. Comme indiqué ci-dessous, transformez au moins le 1er opérande en anstd::string
, et il n'y a aucune erreur.Réponses:
Jetez un œil à cet article du gourou de la semaine de Herb Sutter: Les formateurs de cordes de Manor Farm
la source
std::string s = static_cast<std::ostringstream&>(std::ostringstream().seekp(0) << "HelloWorld" << myInt << niceToSeeYouString).str();
std::stringstream ss; ss << "Hello, world, " << myInt << niceToSeeYouString; std::string s = ss.str();
est à peu près une ligneEn 5 ans, personne ne l'a mentionné
.append
?la source
s.append("One"); s.append(" line");
s.append("One").append(" expression");
Peut-être devrais -je modifier l'original pour utiliser la valeur de retour de cette façon?s
sur une ligne différente dans le code C # équivalent et dans son code C ++ non compilant. Son C ++ désiré ests += "Hello world, " + "nice to see you, " + "or not.";
qui peut être écrits.append("Hello world, ").append("nice to see you, ").append("or not.");
append
est qu'il fonctionne également lorsque les chaînes contiennent des caractères NUL.Ces littéraux de tableau de caractères ne sont pas des chaînes C ++ std :: strings - vous devez les convertir:
Pour convertir des ints (ou tout autre type streamable), vous pouvez utiliser un boost lexical_cast ou fournir votre propre fonction:
Vous pouvez maintenant dire des choses comme:
la source
string("Hello world")
sont effectuées viaoperator+()
défini dans la classestring
. S'il n'y a pas d'string
objet dans l'expression, la concaténation devient une simple somme de pointeurs charchar*
.Votre code peut être écrit sous la forme 1 ,
... mais je doute que ce soit ce que vous recherchez. Dans votre cas, vous recherchez probablement des flux:
1 " peut être écrit comme ": cela ne fonctionne que pour les chaînes littérales. La concaténation est effectuée par le compilateur.
la source
const char smthg[] = "smthg"
: / Est-ce un bogue?#define
votre chaîne pour contourner cela, bien que cela pose ses propres problèmes.L'utilisation de littéraux définis par l'utilisateur C ++ 14 et
std::to_string
le code devient plus facile.Notez que la concaténation de littéraux de chaîne peut être effectuée au moment de la compilation. Retirez simplement le fichier
+
.la source
std::literals::string_literals
concept, pas au concept UDL.Pour offrir une solution plus globale: Une fonction
concat
peut être implémentée pour réduire la solution «classique» basée sur un flux de chaînes à une seule instruction . Il est basé sur des modèles variadiques et une transmission parfaite.Usage:
La mise en oeuvre:
la source
En C ++ 20, vous pourrez faire:
Jusque-là, vous pouvez faire de même avec la bibliothèque {fmt} :
Avertissement : je suis l'auteur de {fmt}.
la source
boost :: format
ou std :: stringstream
la source
Le problème réel était que la concaténation de littéraux de chaîne avec
+
échoue en C ++:En C ++ (également en C), vous concaténez des chaînes littérales en les plaçant simplement les unes à côté des autres:
Cela a du sens, si vous générez du code dans des macros:
... une macro simple qui peut être utilisée comme ça
( démo en direct ... )
ou, si vous insistez pour utiliser les
+
littéraux de chaîne for (comme déjà suggéré par underscore_d ):Une autre solution combine une chaîne et un
const char*
pour chaque étape de concaténationla source
sprintf
est bien sûr une option, mais il existe également std :: stringstream qui évite les problèmes de tampons sous-dimensionnés.la source
Vous auriez à définir operator + () pour chaque type de données que vous voudriez concéder à la chaîne, mais comme l'opérateur << est défini pour la plupart des types, vous devez utiliser std :: stringstream.
Merde, battu de 50 secondes ...
la source
std::string operator+(std::string s, int i){ return s+std::to_string(i); }
Si vous écrivez le
+=
, il ressemble presque à C #la source
Comme d'autres l'ont dit, le principal problème avec le code OP est que l'opérateur
+
ne concatène pasconst char *
; cela fonctionne avecstd::string
, cependant.Voici une autre solution qui utilise des lambdas C ++ 11 et
for_each
et permet de fournir unseparator
pour séparer les chaînes:Usage:
Il semble bien évoluer (linéairement), au moins après un test rapide sur mon ordinateur; voici un test rapide que j'ai écrit:
Résultats (millisecondes):
la source
Peut-être aimeriez-vous que ma solution "Streamer" le fasse vraiment en une seule ligne:
la source
Voici la solution one-liner:
Bien que ce soit un peu moche, je pense que c'est à peu près aussi propre que votre chat en C ++.
Nous convertissons le premier argument en a
std::string
et utilisons ensuite l'ordre d'évaluation (de gauche à droite) deoperator+
pour nous assurer que son opérande de gauche est toujours astd::string
. De cette manière, nous concaténons lestd::string
à gauche avec l'const char *
opérande à droite et retournons un autrestd::string
, en cascade l'effet.Note: il y a quelques options pour l'opérande de droite, y compris
const char *
,std::string
etchar
.C'est à vous de décider si le nombre magique est 13 ou 6227020800.
la source
Vous pouvez utiliser cet en-tête à cet égard: https://github.com/theypsilon/concat
Sous le capot, vous utiliserez un std :: ostringstream.
la source
Si vous souhaitez l'utiliser,
c++11
vous pouvez utiliser des chaînes littérales définies par l'utilisateur et définir deux modèles de fonctions qui surchargent l'opérateur plus pour unstd::string
objet et tout autre objet. Le seul piège est de ne pas surcharger les opérateurs plus destd::string
, sinon le compilateur ne sait pas quel opérateur utiliser. Vous pouvez le faire en utilisant le modèlestd::enable_if
detype_traits
. Après cela, les chaînes se comportent comme en Java ou C #. Voir mon exemple d'implémentation pour plus de détails.Code principal
Fichier c_sharp_strings.hpp
Incluez ce fichier d'en-tête dans tous les endroits où vous souhaitez avoir ces chaînes.
la source
Quelque chose comme ça fonctionne pour moi
la source
Sur la base des solutions ci-dessus, j'ai créé une classe var_string pour mon projet afin de me faciliter la vie. Exemples:
La classe elle-même:
Vous vous demandez toujours s'il y aura quelque chose de mieux en C ++?
la source
En c11:
cela vous permet de créer un appel de fonction comme ceci:
imprimera: numéro du message: 10
la source
vous pouvez également "étendre" la classe de chaîne et choisir l'opérateur que vous préférez (<<, &, |, etc ...)
Voici le code utilisant l'opérateur << pour montrer qu'il n'y a pas de conflit avec les flux
note: si vous décommentez s1.reserve (30), il n'y a que 3 requêtes d'opérateur new () (1 pour s1, 1 pour s2, 1 pour reserve; vous ne pouvez pas réserver au moment du constructeur malheureusement); sans réserve, s1 doit demander plus de mémoire à mesure qu'elle grandit, donc cela dépend du facteur de croissance de l'implémentation de votre compilateur (le mien semble être 1,5, 5 appels new () dans cet exemple)
la source
Stringstream avec une simple macro de préprocesseur utilisant une fonction lambda semble bien:
puis
la source
Cela fonctionne pour moi:
Production:
la source
const
ou (si le stockage nul est une exigence) unenum
serait?Avez-vous essayé d'éviter le + =? à la place, utilisez var = var + ... cela a fonctionné pour moi.
la source
#include <iostream.h> // string
#include <system.hpp> // ansiString