const char * concatenation


116

Ho bisogno di concatenare due caratteri const come questi:

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

Come potrei farlo?

Ho ricevuto questi messaggi char*da una libreria di terze parti con un'interfaccia C, quindi non posso semplicemente usarli std::string.


6
Sono confuso - l'interrogante originale ha scritto il tag "c ++" - poi qualcun altro lo ha rimosso. Qual è lo stato delle cose per questa domanda? Il codice C ++ è consentito?
Johannes Schaub - litb

1
@Johannes: Questa è una domanda migliore xD.
Prasoon Saurav

Nota anche che la domanda originale NON si riferiva a C: ho rimosso quel tag.

Ho cambiato il tag C ++ in C perché l'OP ha accettato una risposta che utilizza array sullo stack strcpye strcatchiamate, ho pensato che avesse senso cambiare i tag.
Gregory Pakosz

7
Aggiunti tag C e C ++. Come spiega l'OP in un commento, sta scrivendo codice C ++, ma chiamando una libreria che utilizza un'interfaccia C. La domanda è rilevante in entrambe le lingue.
jalf

Risposte:


110

Nel tuo esempio uno e due sono puntatori char, che puntano a costanti char. Non è possibile modificare le costanti char puntate da questi puntatori. Quindi qualcosa come:

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

non funzionerà. Invece dovresti avere una variabile separata (array di caratteri) per contenere il risultato. Qualcosa come questo:

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
che dire del risultato char *; risultato = calloc (strlen (uno) + strlen (due) +1, sizeof (char)); e ALLORA lo strcpy + strcat?
luiscubal

3
@luiscubal: Sì, anche questo funzionerebbe ... usa solo un cast (char *), poiché calloc restituisce void *
codaddict

5
Il problema con questa risposta è la dimensione dell'array hardcoded. È davvero una brutta abitudine da prendere, soprattutto se non sai che taglia sono "uno" e "due".
Paul Tomblin

1
Nel primo esempio, strcpy(one,two);dovrebbe essere strcat(one,two);(non che questo lo renda corretto, come hai correttamente sottolineato).
Alok Singhal

1
che ne dici sprintf(dest,"%s%s",one,two)e dimenticare la copia?
mpen

81

Il modo C:

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

Il modo in C ++:

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

Il modo in fase di compilazione:

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

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

31

Se stai usando C ++, perché non usi std::stringinvece delle stringhe in stile C?

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

std::string three= one+two;

Se devi passare questa stringa a una funzione C, passa semplicemente three.c_str()


7
Perché sto usando una libreria che è stata codificata in C, quindi le funzioni restituiscono const char *
Anthoni Caldwell

1
@AnthoniCaldwell: grazie per la risata. Non ho potuto a causa della pressione del
lavoro.:D

Sembra il momento per un nuovo lavoro? ...
Max

20

Utilizzando std::string:

#include <string>

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

10
La seconda chiamata esplicita del costruttore non è necessaria
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()

Aggiornato: modificato string total = string(one) + string(two); in string total( string(one) + two );per motivi di prestazioni (evita la costruzione della stringa due e il totale temporaneo della stringa)

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

@iburidu l'hai misurato? E le situazioni in cui la sicurezza ha la meglio sulle prestazioni? (Sono situazioni comuni)
Sqeaky

3
@Sqeaky Non ci sono assolutamente situazioni in cui questa è più sicura di qualsiasi altra soluzione, ma è SEMPRE più lenta di una soluzione in fase di compilazione, invocando il comportamento di runtime e quasi certamente invocando l'allocazione della memoria.
Alice

8

Un altro esempio:

// 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;

Ma a meno che tu non voglia o non puoi usare specificamente la libreria standard C ++, l'uso std::stringè probabilmente più sicuro.


1
Se l'OP non può usare C ++, non può usare new. E se può usarlo, dovrebbe usarlo std::string, come dici tu.
Alok Singhal

5

Sembra che tu stia usando C ++ con una libreria C e quindi devi lavorare con const char *.

Suggerisco di avvolgerli const char *in std::string:

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

5

Prima di tutto, devi creare uno spazio di memoria dinamico. Quindi puoi semplicemente inserire le due corde in esso. Oppure puoi usare la classe c ++ "string". Il modo C della vecchia scuola:

  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);

Nuovo modo in C ++

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

perché hai bisogno della memoria dinamica?
Luca Matteis

4
-1 per me, prima con il C-way devi usare malloc e free. Quindi, anche se fai di nuovo, dovresti eliminare [] e non eliminare.
Naveen

La libreria che sto usando è codificata in C non C ++, quindi tutte le funzioni restituiscono const char * not string.
Anthoni Caldwell

1
@Naveen, il tag diceva "C ++". Se non puoi usare new ed delete, allora non avrebbe dovuto usare il tag C ++.
Paul Tomblin

5

Se non conosci la dimensione delle stringhe, puoi fare qualcosa del genere:

#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

Puoi usare strstream. È formalmente deprecato, ma è ancora un ottimo strumento se devi lavorare con le stringhe C, penso.

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

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

Questo scriverà onee poi twonel flusso e aggiungerà un termine \0using std::ends. Nel caso in cui entrambe le stringhe potessero finire per scrivere esattamente 99caratteri, quindi non rimarrebbe spazio per la scrittura \0, ne scriviamo uno manualmente nell'ultima posizione.


La deprecazione non dovrebbe importare troppo. Anche se viene rimosso da una versione futura dello standard, non è molto lavoro da reimplementare nel proprio spazio dei nomi.
Steve Jessop

@Steve, infatti :) E anche scrivere il proprio streambufoutput di indirizzamento su un buffer di caratteri usato con ostreamnon è troppo difficile.
Johannes Schaub - litb

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

0

Collegamento di due puntatori a caratteri costanti senza utilizzare il comando strcpy nell'allocazione dinamica della memoria:

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;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.