const char * penggabungan

116

Saya perlu menggabungkan dua karakter const seperti ini:

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

Bagaimana saya bisa melakukan itu?

Saya melewati ini char*dari perpustakaan pihak ketiga dengan antarmuka C jadi saya tidak bisa begitu saja menggunakannya std::string.

Anthoni Caldwell
sumber
6
Saya bingung - penanya asli menulis tag "c ++" - lalu orang lain menghapusnya. Bagaimana keadaan pertanyaan ini? Apakah kode C ++ diperbolehkan?
Johannes Schaub - litb
1
@Johannes: Itu pertanyaan yang lebih baik xD.
Prasoon Saurav
Perhatikan juga pertanyaan awal TIDAK merujuk ke C - Saya telah menghapus tag itu.
Saya mengganti tag C ++ ke C karena OP menerima jawaban yang menggunakan array pada stack dan strcpydan strcatpanggilan, saya pikir masuk akal untuk mengubah tag.
Gregory Pakosz
7
Menambahkan tag C dan C ++. Seperti yang dijelaskan OP dalam komentar, dia menulis kode C ++, tetapi memanggil pustaka yang menggunakan antarmuka C. Pertanyaannya relevan dalam kedua bahasa tersebut.
jalf

Jawaban:

110

Dalam contoh Anda, satu dan dua adalah pointer char, menunjuk ke konstanta char. Anda tidak dapat mengubah konstanta karakter yang ditunjukkan oleh petunjuk ini. Jadi apapun seperti:

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

tidak akan berfungsi. Sebagai gantinya Anda harus memiliki variabel terpisah (char array) untuk menampung hasilnya. Sesuatu seperti ini:

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.
codaddict
sumber
7
bagaimana dengan hasil * char; hasil = calloc (strlen (satu) + strlen (dua) +1, sizeof (char)); dan KEMUDIAN strcpy + strcat?
luiscubal
3
@luiscubal: Ya, itu juga akan berhasil ... cukup gunakan cast (char *), karena calloc mengembalikan void *
codaddict
5
Masalah dengan jawaban ini adalah ukuran array berkode keras. Itu adalah kebiasaan yang sangat buruk untuk dilakukan, terutama jika Anda tidak tahu berapa ukuran "satu" dan "dua" itu.
Paul Tomblin
1
Dalam contoh pertama, strcpy(one,two);seharusnya strcat(one,two);(bukan itu yang membuatnya benar, seperti yang Anda tunjukkan dengan benar).
Alok Singhal
1
bagaimana sprintf(dest,"%s%s",one,two)dan melupakan salinannya?
mpen
81

Cara C:

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

Cara C ++:

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

Cara waktu kompilasi:

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

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

Jika Anda menggunakan C ++, mengapa Anda tidak menggunakan std::stringstring gaya C?

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

std::string three= one+two;

Jika Anda perlu meneruskan string ini ke fungsi-C, cukup teruskan three.c_str()

Prasoon Saurav
sumber
7
Karena saya menggunakan perpustakaan yang dikodekan dalam C sehingga fungsi mengembalikan const char *
Anthoni Caldwell
1
@AnthoniCaldwell: Terima kasih atas tawanya. Saya tidak bisa karena tekanan pekerjaan.:D
Rick2047
Kedengarannya ini waktunya untuk pekerjaan baru? ...
Max
20

Menggunakan std::string:

#include <string>

std::string result = std::string(one) + std::string(two);
Gregory Pakosz
sumber
10
Panggilan konstruktor eksplisit kedua tidak diperlukan
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()

Diperbarui: diubah string total = string(one) + string(two); menjadi string total( string(one) + two );karena alasan kinerja (menghindari konstruksi string dua dan total string sementara)

// string total(move(move(string(one)) + two));  // even faster?
Pedro Reis
sumber
@iburidu apa kau sudah mengukurnya? Bagaimana dengan situasi di mana keselamatan mengalahkan kinerja? (Mereka adalah situasi umum)
Sqeaky
3
@Sqeaky Sama sekali tidak ada situasi di mana ini lebih aman daripada solusi lain, tetapi SELALU lebih lambat daripada solusi waktu kompilasi, dengan menjalankan perilaku runtime serta hampir pasti meminta alokasi memori.
Alice
8

Satu contoh lagi:

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

Tetapi kecuali Anda secara khusus tidak ingin atau tidak dapat menggunakan pustaka standar C ++, penggunaan std::stringmungkin lebih aman.

stakx - tidak lagi berkontribusi
sumber
1
Jika OP tidak bisa menggunakan C ++, dia tidak bisa menggunakan new. Dan jika dia bisa menggunakannya, dia harus menggunakan std::string, seperti yang Anda katakan.
Alok Singhal
5

Sepertinya Anda menggunakan C ++ dengan pustaka C dan oleh karena itu Anda perlu bekerja dengannya const char * .

Saya sarankan untuk membungkusnya const char *menjadi std::string:

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

Pertama-tama, Anda harus membuat beberapa ruang memori dinamis. Kemudian Anda bisa memasukkan dua string ke dalamnya. Atau Anda dapat menggunakan kelas "string" c ++. Cara C sekolah lama:

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

Cara C ++ baru

  std::string three(one);
  three += two;
Paul Tomblin
sumber
mengapa Anda membutuhkan memori dinamis?
Luca Matteis
4
-1 untuk saya, pertama dengan cara C Anda perlu menggunakan malloc dan gratis. Kemudian bahkan jika Anda melakukan yang baru maka itu harus di hapus [] dan bukan di hapus.
Naveen
Perpustakaan yang saya gunakan dikodekan dalam C bukan C ++ sehingga semua fungsi mengembalikan const char * bukan string.
Anthoni Caldwell
1
@Naveen, tag bertuliskan "C ++". Jika Anda tidak dapat menggunakan new and delete, maka dia seharusnya tidak menggunakan tag C ++.
Paul Tomblin
5

Jika Anda tidak mengetahui ukuran senar, Anda dapat melakukan sesuatu seperti ini:

#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
sumber
3

Anda bisa menggunakan strstream. Secara resmi sudah usang, tapi masih merupakan alat yang hebat jika Anda perlu bekerja dengan string C, saya kira.

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

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

Ini akan menulis onedan kemudian twoke aliran, dan menambahkan terminating \0menggunakan std::ends. Dalam kasus kedua string bisa berakhir menulis 99karakter persis - jadi tidak ada spasi yang tersisa untuk menulis \0- kita menulis satu secara manual di posisi terakhir.

Johannes Schaub - litb
sumber
Penghentian seharusnya tidak terlalu menjadi masalah. Meskipun itu dihapus dari versi standar yang akan datang, tidak banyak pekerjaan untuk menerapkan ulang di namespace Anda sendiri.
Steve Jessop
@ Steve, memang :) Dan menulis streambufoutput pengarahan Anda sendiri ke buffer char yang digunakan ostreamjuga tidak terlalu sulit.
Johannes Schaub - litb
3
const char* one = "one";
const char* two = "two";
char result[40];
sprintf(result, "%s%s", one, two);
Jagannath
sumber
0

Menghubungkan dua pointer char konstan tanpa menggunakan perintah strcpy dalam alokasi memori dinamis:

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ć
sumber