135 votes

Concaténation de deux chaînes littérales

Je suis en train de lire Accelerated C++ de Koenig. Il écrit que "la nouvelle idée est que nous pouvons utiliser + pour concaténer une chaîne et un littéral de chaîne - ou, d'ailleurs, deux chaînes (mais pas deux littéraux de chaîne).

Bien, ça a du sens je suppose. Passons maintenant à deux exercices distincts destinés à éclairer cette question.

Les définitions suivantes sont-elles valables ?

const string hello = "Hello";

const string message = hello + ",world" + "!";

Maintenant, j'ai essayé d'exécuter ce qui précède et cela a fonctionné ! Donc j'étais content.

Puis j'ai essayé de faire l'exercice suivant ;

const string exclam = "!";

const string message = "Hello" + ",world" + exclam;

Cela n'a pas fonctionné. Je comprends maintenant que cela a quelque chose à voir avec le fait que l'on ne peut pas concaténer deux chaînes littérales, mais je ne comprends pas la différence sémantique entre la raison pour laquelle j'ai réussi à faire fonctionner le premier exemple (est-ce que ",world" et " !" ne sont pas deux chaînes littérales ? Cela n'aurait pas dû ne pas fonctionner ?

4 votes

const string message = "Hello" ",world" + exclam (par exemple, en omettant le premier + ) devrait fonctionner parfaitement.

1 votes

@Joe - Pourquoi quelqu'un voudrait-il écrire "Hello" + ", world!" quand vous pouvez faire "Hello, world!" . Comme d'habitude, C++ propose une solution simple et géniale à un problème perçu :-)

2 votes

@Bo La seule chose à laquelle je pense est que si vous utilisez une définition (#define)

156voto

James McNellis Points 193607
const string message = "Hello" + ",world" + exclam;

El + a une associativité de gauche à droite, donc l'expression équivalente entre parenthèses est :

const string message = (("Hello" + ",world") + exclam);

Comme vous pouvez le voir, les deux chaînes de caractères littéraux "Hello" y ",world" sont "ajoutés" en premier, d'où l'erreur.

L'une des deux premières chaînes concaténées doit être une std::string objet :

const string message = string("Hello") + ",world" + exclam;

Alternativement, vous pouvez forcer le second + à évaluer en premier en mettant cette partie de l'expression entre parenthèses :

const string message = "Hello" + (",world" + exclam);

Il est logique que votre premier exemple ( hello + ",world" + "!" ) fonctionne parce que le std::string ( hello ) est l'un des arguments de la fonction + . Ce + est évalué, le résultat est un std::string avec la chaîne de caractères concaténée, et l'objet std::string est ensuite concaténée avec le "!" .


Quant à pourquoi vous ne pouvez pas concaténer deux chaînes littérales en utilisant + c'est parce qu'un littéral de chaîne de caractères est juste un tableau de caractères (un const char [N] donde N est la longueur de la chaîne plus un, pour le terminateur nul). Lorsque vous utilisez un tableau dans la plupart des contextes, il est converti en un pointeur vers son élément initial.

Donc, quand vous essayez de faire "Hello" + ",world" ce que vous essayez vraiment de faire est d'ajouter deux const char* s ensemble, ce qui n'est pas possible (qu'est-ce que cela signifierait d'ajouter deux pointeurs ensemble ?) et si cela l'était, cela ne ferait pas ce que vous vouliez qu'il fasse.


Notez que vous puede concaténer des littéraux de chaîne en les plaçant l'un à côté de l'autre ; par exemple, les deux suivants sont équivalents :

"Hello" ",world"
"Hello,world"

C'est utile si vous avez une longue chaîne littérale que vous voulez répartir sur plusieurs lignes. Il doit s'agir de chaînes de caractères, cependant : cela ne fonctionnera pas avec const char* ou des pointeurs const char[N] les tableaux.

3 votes

Aussi, const string message = "Hello" + (",world"+exclam); fonctionnera également, en raison de la parenthèse explicite (est-ce un mot ?).

2 votes

Il pourrait être encore plus complet si vous expliquiez pourquoi le premier exemple fonctionne : const string message = ((hello + ",world") + "!");

0 votes

Merci ! Je soupçonnais que cela avait quelque chose à voir avec l'associativité gauche-droite, mais je n'en étais pas sûr et cette différence sémantique n'avait pas beaucoup de sens pour moi. J'apprécie la réponse !

9voto

Yochai Timmer Points 19802

Vous devez toujours faire attention à types .

Bien qu'ils semblent tous être des cordes, "Hello" y ",world" sont littéraux .

Et dans votre exemple, exclam est un std::string objet.

Le C++ dispose d'une surcharge d'opérateur qui prend un fichier std::string et y ajoute une autre chaîne de caractères. Lorsque vous concaténer un std::string avec un littéral, il effectuera le casting approprié pour le littéral.

Mais si vous essayez de concaténer deux littéraux, le compilateur ne sera pas capable de trouver un opérateur qui prend deux littéraux.

0 votes

Ver std::operator+ qui propose des surcharges pour concaténer un fichier std::string avec un autre std::string un tableau de caractères ou un seul caractère.

9voto

Juraj Blaho Points 8134

Votre deuxième exemple ne fonctionne pas car il n'y a pas de operator + pour deux chaînes littérales. Notez qu'un littéral de chaîne n'est pas de type string mais il est de type const char * . Votre deuxième exemple fonctionnera si vous le révisez comme suit :

const string message = string("Hello") + ",world" + exclam;

2voto

Stephen Points 993

Dans le cas 1, à cause de l'ordre des opérations, on obtient.. :

(hello + ", world") + " !" qui se résout en hello + " !" et finalement en hello

Dans le cas 2, comme James l'a noté, vous obtenez :

("Hello" + ", world") + exclam qui est la concat de 2 chaînes littérales.

J'espère que c'est clair :)

2voto

Péter Török Points 72981

La différence entre une chaîne (ou pour être précis, std::string ) et un caractère littéral est que pour ce dernier il n'y a pas de + opérateur défini. C'est pourquoi le deuxième exemple échoue.

Dans le premier cas, le compilateur peut trouver un operator+ avec le premier argument étant un string et le second un caractère littéral ( const char* ) donc il l'a utilisé. Le résultat de cette opération est à nouveau un string il répète donc le même tour de passe-passe lorsqu'il ajoute "!" à ce sujet.

0 votes

Pour être pédant, les littéraux de caractères hacer ont + défini, mais pas avec deux char* termes. Sinon, l'arithmétique des pointeurs ne fonctionnerait pas :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X