การต่อ const char *


116

ฉันต้องการเชื่อมอักขระ const สองตัวเข้าด้วยกันดังนี้:

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

ฉันจะทำอย่างนั้นได้อย่างไร?

ฉันส่งผ่านสิ่งเหล่านี้char*มาจากไลบรารีของบุคคลที่สามที่มีอินเทอร์เฟซ C ดังนั้นฉันจึงไม่สามารถใช้std::stringแทนได้


6
ฉันสับสน - ผู้ถามเดิมเขียนแท็ก "c ++" แล้วมีคนอื่นลบออก คำถามนี้มีสถานะเป็นอย่างไร อนุญาตรหัส C ++ หรือไม่
Johannes Schaub - litb

1
@ โจฮันเนส: นั่นเป็นคำถามที่ดีกว่า xD
Prasoon Saurav

โปรดทราบว่าคำถามเดิมไม่ได้อ้างถึง C - ฉันได้ลบแท็กนั้นแล้ว

ฉันเปลี่ยนแท็ก C ++ เป็น C เนื่องจาก OP ยอมรับคำตอบที่ใช้อาร์เรย์บนสแต็กและstrcpyและการstrcatโทรฉันคิดว่าเหมาะสมที่จะเปลี่ยนแท็ก
Gregory Pakosz

7
เพิ่มแท็กC และ C ++ ตามที่ OP อธิบายในความคิดเห็นเขากำลังเขียนโค้ด C ++ แต่เรียกไลบรารีที่ใช้อินเทอร์เฟซ C คำถามมีความเกี่ยวข้องในทั้งสองภาษา
jalf

คำตอบ:


110

ในตัวอย่างของคุณหนึ่งและสองคือตัวชี้ถ่านที่ชี้ไปที่ค่าคงที่ของถ่าน คุณไม่สามารถเปลี่ยนค่าคงที่ถ่านที่ชี้โดยพอยน์เตอร์เหล่านี้ สิ่งที่ชอบ:

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

จะไม่ทำงาน. แต่คุณควรมีตัวแปรแยกต่างหาก (อาร์เรย์ถ่าน) เพื่อเก็บผลลัพธ์ สิ่งนี้:

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
แล้วถ่าน * ผลลัพธ์ล่ะ; ผลลัพธ์ = calloc (strlen (หนึ่ง) + strlen (สอง) +1, sizeof (ถ่าน)); แล้ว strcpy + strcat?
luiscubal

3
@luiscubal: ใช่มันก็ใช้ได้เหมือนกัน ... แค่ใช้ (ถ่าน *) แคสต์เพราะแคลอคส่งคืนโมฆะ *
codaddict

5
ปัญหาของคำตอบนี้คือขนาดอาร์เรย์แบบฮาร์ดโค้ด นั่นเป็นนิสัยที่แย่มากที่จะเข้ามาโดยเฉพาะอย่างยิ่งถ้าคุณไม่รู้ว่า "หนึ่ง" และ "สอง" มีขนาดเท่าใด
Paul Tomblin

1
ในตัวอย่างแรกstrcpy(one,two);ควรจะเป็นstrcat(one,two);(ไม่ใช่ที่ที่จะทำให้มันถูกต้องตามที่คุณได้อย่างถูกต้องชี้ให้เห็น)
Alok Singhal

1
สิ่งที่เกี่ยวกับsprintf(dest,"%s%s",one,two)และลืมสำเนา?
mpen

82

วิธี C:

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

วิธี C ++:

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

วิธีรวบรวมเวลา:

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

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

31

หากคุณใช้ C ++ ทำไมคุณไม่ใช้std::stringแทนสตริงสไตล์ C

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

std::string three= one+two;

หากคุณต้องการส่งสตริงนี้ไปยังฟังก์ชัน C ให้ส่งผ่าน three.c_str()


8
เนื่องจากฉันใช้ไลบรารีที่เข้ารหัส C ดังนั้นฟังก์ชันจึงส่งคืน const char *
Anthoni Caldwell

1
@AnthoniCaldwell: ขอบคุณสำหรับเสียงหัวเราะ ฉันทำไม่ได้เพราะความกดดันในการทำงาน
D

ดูเหมือนว่าจะถึงเวลาสำหรับงานใหม่แล้วหรือ ...
สูงสุด

20

ใช้std::string:

#include <string>

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

11
ไม่จำเป็นต้องมีการเรียกตัวสร้างที่ชัดเจนครั้งที่สอง
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()

อัปเดต:เปลี่ยน string total = string(one) + string(two); เป็นstring total( string(one) + two );เหตุผลด้านประสิทธิภาพ (หลีกเลี่ยงการสร้างสตริงสองและสตริงรวมชั่วคราว)

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

@iburidu คุณวัดหรือยัง? แล้วสถานการณ์ที่ความปลอดภัยสำคัญกว่าประสิทธิภาพ? (เป็นสถานการณ์ทั่วไป)
Sqeaky

3
@Sqeaky ไม่มีสถานการณ์ใดที่ปลอดภัยไปกว่าโซลูชันอื่น ๆ แต่จะช้ากว่าโซลูชันเวลาคอมไพล์เสมอโดยการเรียกใช้ลักษณะการทำงานของรันไทม์รวมถึงการเรียกใช้การจัดสรรหน่วยความจำ
Alice

8

อีกหนึ่งตัวอย่าง:

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

แต่ถ้าคุณไม่ต้องการหรือไม่สามารถใช้ไลบรารีมาตรฐาน C ++ โดยเฉพาะการใช้งานstd::stringอาจปลอดภัยกว่า


1
หาก OP ไม่สามารถใช้ภาษา C ++ newเขาไม่สามารถใช้ และถ้าเขาใช้ได้เขาก็ควรใช้std::stringอย่างที่คุณพูด
Alok Singhal

5

ดูเหมือนว่าคุณกำลังใช้ C ++ กับไลบรารี C ดังนั้นคุณจึงต้องทำงานด้วย const char *และดังนั้นคุณจำเป็นต้องทำงานร่วมกับ

ฉันขอแนะนำให้ห่อสิ่งเหล่านี้const char *เป็นstd::string:

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

5

ก่อนอื่นคุณต้องสร้างพื้นที่หน่วยความจำแบบไดนามิก จากนั้นคุณก็สามารถ strcat ทั้งสองสตริงเข้าไปได้ หรือคุณสามารถใช้คลาส "string" c ++ ทาง C ของโรงเรียนเก่า:

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

วิธีใหม่ของ C ++

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

ทำไมคุณถึงต้องการหน่วยความจำแบบไดนามิก
Luca Matteis

4
-1 สำหรับฉันอันดับแรกด้วย C-way คุณต้องใช้ malloc และฟรี จากนั้นแม้ว่าคุณจะทำใหม่ก็ควรลบ [] และไม่ลบ
Naveen

ไลบรารีที่ฉันใช้อยู่นั้นเข้ารหัสเป็น C ไม่ใช่ C ++ ดังนั้นฟังก์ชันทั้งหมดจึงส่งคืน const char * ไม่ใช่สตริง
Anthoni Caldwell

1
@Naveen แท็กกล่าวว่า "C ++" หากคุณไม่สามารถใช้ใหม่และลบได้แสดงว่าเขาไม่ควรใช้แท็ก C ++
Paul Tomblin

5

หากคุณไม่ทราบขนาดของสตริงคุณสามารถทำสิ่งนี้ได้:

#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

คุณสามารถใช้strstream. เลิกใช้งานอย่างเป็นทางการแล้ว แต่ก็ยังเป็นเครื่องมือที่ยอดเยี่ยมหากคุณต้องการทำงานกับสตริง C ฉันคิดว่า

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

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

นี้จะเขียนoneแล้วtwoเข้าไปในกระแสและผนวกยุติการใช้\0 std::endsในกรณีที่สตริงทั้งสองสามารถเขียน99อักขระได้ตรงกัน- ดังนั้นจะไม่มีช่องว่างเหลือสำหรับการเขียน\0เราจะเขียนด้วยตนเองที่ตำแหน่งสุดท้าย


การเลิกใช้งานไม่ควรมีความสำคัญมากเกินไป แม้ว่าจะถูกลบออกจากเวอร์ชันมาตรฐานในอนาคต แต่ก็ไม่ได้เป็นเรื่องที่ควรทำมากนักที่จะนำมาใช้ใหม่ในเนมสเปซของคุณเอง
Steve Jessop

@ สตีฟแน่นอน :) และการเขียนstreambufเอาต์พุตกำกับของคุณเองไปยังถ่านบัฟเฟอร์ที่ใช้กับostreamก็ไม่ยากเช่นกัน
Johannes Schaub - litb


0

การเชื่อมต่อตัวชี้ค่าคงที่สองตัวโดยไม่ใช้คำสั่ง strcpy ในการจัดสรรหน่วยความจำแบบไดนามิก:

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;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.