const karakter * birleştirme


116

İki const karakterini şu şekilde birleştirmem gerekiyor:

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

Bunu nasıl yapabilirim?

Bu s’leri char*C arayüzlü bir üçüncü taraf kitaplığından geçiriyorum, bu yüzden std::stringbunun yerine kullanamıyorum .


6
Kafam karıştı - orijinal sorgulayıcı "c ++" etiketi yazdı - sonra başka biri onu kaldırdı. Bu sorunun durumu nedir? C ++ koduna izin verilir mi?
Johannes Schaub -

1
@Johannes: Bu daha iyi bir soru xD.
Prasoon Saurav

Ayrıca, orijinal sorunun C ile ilgili OLMADIĞINI unutmayın - Bu etiketi kaldırdım.

C ++ etiketini C olarak değiştirdim çünkü OP yığın strcpyve strcatçağrılarda dizileri kullanan bir yanıtı kabul etti , etiketleri değiştirmenin mantıklı olduğunu düşündüm.
Gregory Pakosz

7
C ve C ++ etiketleri eklendi. OP'nin bir yorumda açıkladığı gibi, C ++ kodu yazıyor, ancak C arayüzü kullanan bir kitaplık arıyor. Soru her iki dilde de geçerlidir.
jalf

Yanıtlar:


110

Örnekte bir ve iki karakter sabitleri işaret ederek, Char noktalar şunlardır. Bu işaretçilerle gösterilen karakter sabitlerini değiştiremezsiniz. Yani şöyle bir şey:

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

çalışmayacak. Bunun yerine sonucu tutmak için ayrı bir değişkene (karakter dizisi) sahip olmalısınız. Bunun gibi bir şey:

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
peki ya char * sonucu; sonuç = calloc (strlen (bir) + strlen (iki) +1, sizeof (char)); ve SONRA strcpy + strcat?
luiscubal

3
@luiscubal: Evet, bu da işe yarar ... calloc void * döndürdüğü için bir (char *) cast kullanın
codaddict

5
Bu yanıtla ilgili sorun, sabit kodlanmış dizi boyutudur. Bu, içine girmek için gerçekten kötü bir alışkanlıktır, özellikle "bir" ve "iki" nin ne büyüklükte olduğunu bilmiyorsanız.
Paul Tomblin

1
İlk örnekte, strcpy(one,two);olması gerektiği strcat(one,two);(değil o doğru işaret olarak, bu düzeltmek yapar).
Alok Singhal

1
peki sprintf(dest,"%s%s",one,two)ve kopyayı unut?
mpen

81

C yolu:

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

C ++ yolu:

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

Derleme zamanı yolu:

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

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

31

C ++ kullanıyorsanız, neden std::stringC tarzı dizeler yerine kullanmıyorsunuz ?

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

std::string three= one+two;

Bu dizeyi bir C işlevine iletmeniz gerekiyorsa, three.c_str()


7
Çünkü C ile kodlanmış bir kitaplık kullanıyorum, böylece işlevler const char * döndürür
Anthoni Caldwell

1
@AnthoniCaldwell: Güldüğün için teşekkürler. İş baskısı yüzünden yapamadım.
D

Yeni bir iş için zamanı gelmiş gibi görünüyor? ...
Fazla

20

Kullanarak std::string:

#include <string>

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

10
İkinci açık yapıcı çağrısı gerekli değil
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()

Güncel: değişmiş string total = string(one) + string(two); için string total( string(one) + two );(dize iki ve geçici dize toplam yapımını önler) performans nedenleriyle

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

@iburidu ölçtün mü? Peki ya güvenliğin performanstan üstün olduğu durumlar? (Bunlar yaygın durumlardır)
Sqeaky

3
@Sqeaky Bunun başka herhangi bir çözümden daha güvenli olduğu kesinlikle hiçbir durum yoktur, ancak çalışma zamanı davranışını çağırarak ve neredeyse kesin olarak bellek tahsisini çağırarak, HER ZAMAN bir derleme zamanı çözümünden daha yavaştır.
Alice

8

Bir örnek daha:

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

Ancak C ++ standart kitaplığını özellikle istemediğiniz veya kullanamadığınız sürece, kullanmak std::stringmuhtemelen daha güvenlidir.


1
OP, C ++ kullanamazsa, kullanamaz new. Ve eğer kullanabiliyorsa std::string, dediğin gibi kullanmalı .
Alok Singhal

5

Görünüşe göre bir C kitaplığı ile C ++ kullanıyorsunuz ve bu nedenle const char * .

O sarma öneririz const char *içine std::string:

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

5

Her şeyden önce, biraz dinamik hafıza alanı yaratmalısınız. O zaman iki dizgiyi içine dizebilirsiniz. Veya c ++ "string" sınıfını kullanabilirsiniz. Eski usul C yöntemi:

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

Yeni C ++ yolu

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

neden dinamik belleğe ihtiyacınız var?
Luca Matteis

4
-1 benim için, önce C-yolu ile malloc ve ücretsiz kullanmanız gerekiyor. Daha sonra yenisini yapsanız bile, [] silinmeli ve silinmemelidir.
Naveen

Kullandığım kitaplık C ++ değil C kodludur, bu nedenle tüm işlevler const char * değil string döndürür.
Anthoni Caldwell

1
@Naveen, etiket "C ++" dedi. Yeni kullanamıyorsanız ve silemiyorsanız, C ++ etiketini kullanmamış olması gerekir.
Paul Tomblin

5

Dizelerin boyutunu bilmiyorsanız, şöyle bir şey yapabilirsiniz:

#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

Kullanabilirsiniz strstream . Resmi olarak kullanımdan kaldırıldı, ancak C dizeleriyle çalışmanız gerekiyorsa yine de harika bir araç, bence.

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

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

Bu daha onesonra twoakışa yazacak ve \0kullanarak bir sonlandırma ekleyecektir std::ends. Her iki dizenin de 99karakterleri tam olarak yazması durumunda - bu nedenle yazıya boşluk bırakılmaz \0- son konuma manuel olarak bir tane yazarız.


Kullanımdan kaldırma çok önemli olmamalı. Standardın gelecekteki bir sürümünden kaldırılmış olsa bile, kendi ad alanınızda yeniden uygulamak o kadar da zor değildir.
Steve Jessop

@Steve, gerçekten :) Ve streambufkullanılan bir char tamponuna kendi yönlendirme çıktınızı yazmak ostreamda çok zor değil.
Johannes Schaub -

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

0

Dinamik bellek ayırmasında strcpy komutunu kullanmadan iki sabit karakter göstericisinin bağlanması:

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;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.