concatenação const char *

116

Preciso concatenar dois caracteres const como estes:

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

Como posso fazer isso?

Eu recebi esses char*s de uma biblioteca de terceiros com uma interface C, então não posso simplesmente usar em seu std::stringlugar.

Anthoni Caldwell
fonte
6
Estou confuso - o questionador original escreveu a tag "c ++" - então alguém a removeu. Qual é o estado de coisas para esta questão? O código C ++ é permitido?
Johannes Schaub - litb
1
@Johannes: Essa é uma pergunta melhor xD.
Prasoon Saurav
Observe também que a pergunta original NÃO se referia a C - eu removi essa tag.
Troquei o tag C ++ para C porque o OP aceita uma resposta que utiliza matrizes na pilha e strcpye strcatchamadas, pensei que fazia sentido para alterar as tags.
Gregory Pakosz
7
Adicionadas tags C e C ++. Como o OP explica em um comentário, ele está escrevendo código C ++, mas chamando uma biblioteca que usa uma interface C. A questão é relevante em ambos os idiomas.
jalf

Respostas:

110

No seu exemplo, um e dois são ponteiros char, apontando para constantes char. Você não pode alterar as constantes char apontadas por esses ponteiros. Então, qualquer coisa como:

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

não funciona. Em vez disso, você deve ter uma variável separada (array char) para armazenar o resultado. Algo assim:

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.
codadicto
fonte
7
que tal char * result; resultado = calloc (strlen (um) + strlen (dois) +1, sizeof (char)); e ENTÃO o strcpy + strcat?
luiscubal
3
@luiscubal: Sim, também funcionaria ... apenas use um (char *) cast, já que calloc retorna void *
codaddict
5
O problema com esta resposta é o tamanho do array codificado. É um péssimo hábito de adquirir, especialmente se você não sabe o tamanho "um" e "dois".
Paul Tomblin
1
No primeiro exemplo, strcpy(one,two);deveria ser strcat(one,two);(não que isso o torne correto, como você corretamente apontou).
Alok Singhal
1
o que dizer sprintf(dest,"%s%s",one,two)e esquecer a cópia?
mês de
81

O modo C:

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

O jeito C ++:

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

A forma de tempo de compilação:

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

const char* buf = concat(one, two);
Idan K
fonte
31

Se você estiver usando C ++, por que não usa em std::stringvez de strings de estilo C?

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

std::string three= one+two;

Se você precisar passar esta string para uma função C, simplesmente passe three.c_str()

Prasoon Saurav
fonte
7
Porque estou usando uma biblioteca que foi codificada em C, então as funções retornam const char *
Anthoni Caldwell
1
@AnthoniCaldwell: Obrigado pela risada. Eu não podia por causa da pressure.:D trabalho
Rick2047
Parece que é hora de um novo emprego? ...
Máx.
20

Usando std::string:

#include <string>

std::string result = std::string(one) + std::string(two);
Gregory Pakosz
fonte
10
A segunda chamada explícita do construtor não é necessária
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()

Atualizado: alterado string total = string(one) + string(two); para string total( string(one) + two );por motivos de desempenho (evita a construção da coluna dois e total temporário da coluna)

// string total(move(move(string(one)) + two));  // even faster?
Pedro Reis
fonte
@iburidu você mediu isso? E as situações em que a segurança supera o desempenho? (São situações comuns)
Sqeaky
3
@Sqeaky Não há absolutamente nenhuma situação em que isso seja mais seguro do que qualquer outra solução, mas é SEMPRE mais lento do que uma solução de tempo de compilação, invocando o comportamento de tempo de execução e quase certamente invocando a alocação de memória.
Alice
8

Mais um exemplo:

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

Mas, a menos que você especificamente não queira ou não possa usar a biblioteca padrão C ++, usar std::stringé provavelmente mais seguro.

stakx - não contribui mais
fonte
1
Se o OP não pode usar C ++, ele não pode usar new. E se ele pode usar, ele deve usar std::string, como você diz.
Alok Singhal
5

Parece que você está usando C ++ com uma biblioteca C e, portanto, precisa trabalhar com const char * .

Eu sugiro envolvê-los const char *em std::string:

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

Em primeiro lugar, você deve criar algum espaço de memória dinâmica. Então, você pode apenas strcat as duas cordas nele. Ou você pode usar a classe c ++ "string". O jeito C da velha escola:

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

Novo jeito C ++

  std::string three(one);
  three += two;
Paul Tomblin
fonte
por que você precisa de memória dinâmica?
Luca Matteis
4
-1 pra mim, primeiro com o C-way vc precisa usar malloc e free. Então, mesmo se você fizer algo novo, deve-se excluir [] e não excluir.
Naveen
A biblioteca que estou usando é codificada em C, não C ++, portanto, todas as funções retornam const char * não string.
Anthoni Caldwell
1
@Naveen, a tag dizia "C ++". Se você não pode usar new e delete, então ele não deveria ter usado a tag C ++.
Paul Tomblin
5

Se você não sabe o tamanho das strings, pode fazer algo assim:

#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;
}
Iraklis Moutidis
fonte
3

Você pode usar strstream. Está formalmente obsoleto, mas ainda é uma ótima ferramenta se você precisa trabalhar com strings C, eu acho.

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

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

Isso escreverá onee, twoem seguida, no fluxo e acrescentará um terminador \0usando std::ends. No caso de ambas as strings acabarem escrevendo exatamente 99caracteres - então nenhum espaço seria deixado para escrever \0- nós escrevemos um manualmente na última posição.

Johannes Schaub - litb
fonte
A suspensão de uso não deve importar muito. Mesmo que seja removido de uma versão futura do padrão, não é muito trabalhoso reimplementar em seu próprio namespace.
Steve Jessop
@Steve, de fato :) E escrever sua própria streambufsaída direcionando para um buffer de char usado com ostreamnão é muito difícil também.
Johannes Schaub - litb
3
const char* one = "one";
const char* two = "two";
char result[40];
sprintf(result, "%s%s", one, two);
Jagannath
fonte
0

Conectar dois ponteiros char constantes sem usar o comando strcpy na alocação dinâmica de memória:

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;
Edin Jašarević
fonte