concaténation de caractères const *


116

J'ai besoin de concaténer deux caractères const comme ceux-ci:

const char *one = "Hello ";
const char *two = "World";

Comment pourrais-je faire ça?

Je suis passé ces char*s d'une bibliothèque tierce avec une interface C donc je ne peux pas simplement utiliser à la std::stringplace.


6
Je suis confus - le questionneur original a écrit la balise "c ++" - puis quelqu'un d'autre l'a supprimée. Quel est l'état des lieux de cette question? Le code C ++ est-il autorisé?
Johannes Schaub - litb

1
@Johannes: C'est une meilleure question xD.
Prasoon Saurav

Notez également que la question d'origine ne faisait PAS référence à C - j'ai supprimé cette balise.

J'ai changé la balise C ++ en C parce que l'OP a accepté une réponse qui utilise des tableaux sur la pile strcpyet les strcatappels, j'ai pensé que cela avait du sens de changer les balises.
Gregory Pakosz

7
Ajout de balises C et C ++. Comme l'explique l'OP dans un commentaire, il écrit du code C ++, mais appelle une bibliothèque qui utilise une interface C. La question est pertinente dans les deux langues.
jalf

Réponses:


110

Dans votre exemple, un et deux sont des pointeurs char, pointant vers des constantes char. Vous ne pouvez pas modifier les constantes char vers lesquelles pointent ces pointeurs. Donc quelque chose comme:

strcat(one,two); // append string two to string one.

ne fonctionnera pas. Au lieu de cela, vous devriez avoir une variable distincte (tableau de caractères) pour contenir le résultat. Quelque chose comme ça:

char result[100];   // array to hold the result.

strcpy(result,one); // copy string one into the result.
strcat(result,two); // append string two to the result.

7
qu'en est-il de char * result; result = calloc (strlen (un) + strlen (deux) +1, sizeof (char)); et ALORS le strcpy + strcat?
luiscubal

3
@luiscubal: Oui, cela fonctionnerait aussi ... utilisez simplement un (char *) cast, car calloc retourne void *
codaddict

5
Le problème avec cette réponse est la taille du tableau codé en dur. C'est une très mauvaise habitude à prendre, surtout si vous ne savez pas quelle taille "un" et "deux" sont.
Paul Tomblin

1
Dans le premier exemple, strcpy(one,two);devrait être strcat(one,two);(pas que cela le rend correct, comme vous le faites remarquer correctement).
Alok Singhal

1
qu'en est-il sprintf(dest,"%s%s",one,two)et oublier la copie?
mpen

81

La voie C:

char buf[100];
strcpy(buf, one);
strcat(buf, two);

La manière C ++:

std::string buf(one);
buf.append(two);

La méthode de compilation:

#define one "hello "
#define two "world"
#define concat(first, second) first second

const char* buf = concat(one, two);

31

Si vous utilisez C ++, pourquoi n'utilisez-vous pas à la std::stringplace des chaînes de style C?

std::string one="Hello";
std::string two="World";

std::string three= one+two;

Si vous devez passer cette chaîne à une fonction C, passez simplement three.c_str()


7
Parce que j'utilise une bibliothèque qui a été codée en C, donc les fonctions renvoient const char *
Anthoni Caldwell

1
@AnthoniCaldwell: Merci pour le rire. Je ne pouvais pas à cause de la pression de travail
.: D

On dirait qu'il est temps pour un nouvel emploi? ...
Max

20

Utilisation std::string:

#include <string>

std::string result = std::string(one) + std::string(two);

10
Le deuxième appel de constructeur explicite n'est pas nécessaire
sellibitze

17
const char *one = "Hello ";
const char *two = "World";

string total( string(one) + two );

// to use the concatenation as const char*, use:
total.c_str()

Mise à jour: changé string total = string(one) + string(two); en string total( string(one) + two );pour des raisons de performances (évite la construction de la chaîne deux et le total de la chaîne temporaire)

// string total(move(move(string(one)) + two));  // even faster?

@iburidu l'avez-vous mesuré? Qu'en est-il des situations où la sécurité prime sur la performance? (Ce sont des situations courantes)
Sqeaky

3
@Sqeaky Il n'y a absolument aucune situation où cela soit plus sûr que n'importe quelle autre solution, mais c'est TOUJOURS plus lent qu'une solution au moment de la compilation, en invoquant le comportement d'exécution ainsi qu'en invoquant presque certainement l'allocation de mémoire.
Alice

8

Encore un exemple:

// calculate the required buffer size (also accounting for the null terminator):
int bufferSize = strlen(one) + strlen(two) + 1;

// allocate enough memory for the concatenated string:
char* concatString = new char[ bufferSize ];

// copy strings one and two over to the new buffer:
strcpy( concatString, one );
strcat( concatString, two );

...

// delete buffer:
delete[] concatString;

Mais à moins que vous ne vouliez ou ne puissiez pas spécifiquement utiliser la bibliothèque standard C ++, l'utilisation std::stringest probablement plus sûre.


1
Si l'OP ne peut pas utiliser C ++, il ne peut pas utiliser new. Et s'il peut l'utiliser, il devrait l'utiliser std::string, comme vous le dites.
Alok Singhal

5

Il semble que vous utilisez C ++ avec une bibliothèque C et que vous devez donc travailler avec const char * .

Je suggère de les envelopper const char *dans std::string:

const char *a = "hello "; 
const char *b = "world"; 
std::string c = a; 
std::string d = b; 
cout << c + d;

5

Tout d'abord, vous devez créer un espace mémoire dynamique. Ensuite, vous pouvez simplement y insérer les deux chaînes. Ou vous pouvez utiliser la classe "string" c ++. La voie C à l'ancienne:

  char* catString = malloc(strlen(one)+strlen(two)+1);
  strcpy(catString, one);
  strcat(catString, two);
  // use the string then delete it when you're done.
  free(catString);

Nouvelle méthode C ++

  std::string three(one);
  three += two;

pourquoi avez-vous besoin de mémoire dynamique?
Luca Matteis

4
-1 pour moi, d'abord avec le C-way, vous devez utiliser malloc et free. Ensuite, même si vous en faites un nouveau, il devrait s'agir de delete [] et non de suppression.
Naveen

La bibliothèque que j'utilise est codée en C et non en C ++, donc toutes les fonctions renvoient const char * not string.
Anthoni Caldwell

1
@Naveen, la balise disait "C ++". Si vous ne pouvez pas utiliser new et delete, alors il n'aurait pas dû utiliser la balise C ++.
Paul Tomblin

5

Si vous ne connaissez pas la taille des chaînes, vous pouvez faire quelque chose comme ceci:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(){
    const char* q1 = "First String";
    const char* q2 = " Second String";

    char * qq = (char*) malloc((strlen(q1)+ strlen(q2))*sizeof(char));
    strcpy(qq,q1);
    strcat(qq,q2);

    printf("%s\n",qq);

    return 0;
}

3

Vous pouvez utiliser strstream. C'est formellement obsolète, mais c'est toujours un excellent outil si vous devez travailler avec des chaînes C, je pense.

char result[100]; // max size 100
std::ostrstream s(result, sizeof result - 1);

s << one << two << std::ends;
result[99] = '\0';

Cela écrira one, puis twodans le flux, et ajoutera une fin en \0utilisant std::ends. Au cas où les deux chaînes pourraient finir par écrire exactement des 99caractères - il ne resterait donc plus d'espace d'écriture \0- nous en écrivons une manuellement à la dernière position.


La dépréciation ne devrait pas avoir trop d'importance. Même si elle est supprimée d'une future version de la norme, la réimplémentation dans votre propre espace de noms n'est pas si compliquée.
Steve Jessop

@Steve, en effet :) Et écrire votre propre streambufsortie de direction dans un tampon de caractères utilisé avec ostreamn'est pas trop difficile non plus.
Johannes Schaub - litb

3
const char* one = "one";
const char* two = "two";
char result[40];
sprintf(result, "%s%s", one, two);

0

Connexion de deux pointeurs de caractères constants sans utiliser la commande strcpy dans l'allocation dynamique de la mémoire:

const char* one = "Hello ";
const char* two = "World!";

char* three = new char[strlen(one) + strlen(two) + 1] {'\0'};

strcat_s(three, strlen(one) + 1, one);
strcat_s(three, strlen(one) + strlen(two) + 1, two);

cout << three << endl;

delete[] three;
three = nullptr;
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.