const char * ghép


116

Tôi cần ghép hai ký tự const như sau:

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

Làm thế nào tôi có thể đi về làm điều đó?

Tôi được chuyển qua các char*thư viện này từ thư viện của bên thứ ba với giao diện C vì vậy tôi không thể đơn giản sử dụng std::stringthay thế.


6
Tôi bối rối - người hỏi ban đầu đã viết thẻ "c ++" - sau đó người khác đã xóa nó. Tình trạng của câu hỏi này là gì? Mã C ++ có được phép không?
Julian Schaub - litb

1
@Johannes: Đó là một câu hỏi hay hơn xD.
Prasoon Saurav

Cũng lưu ý rằng câu hỏi ban đầu KHÔNG đề cập đến C - Tôi đã xóa thẻ đó.

Tôi đã chuyển thẻ C ++ sang C vì OP chấp nhận câu trả lời sử dụng mảng trên ngăn xếp strcpystrcatcác cuộc gọi, tôi nghĩ rằng điều đó hợp lý để thay đổi các thẻ.
Gregory Pakosz

7
Đã thêm thẻ C C ++. Như OP giải thích trong một bình luận, anh ta đang viết mã C ++, nhưng gọi một thư viện sử dụng giao diện C. Câu hỏi có liên quan trong cả hai ngôn ngữ.
jalf

Câu trả lời:


110

Trong ví dụ của bạn, mộthai là con trỏ char, trỏ đến hằng số char. Bạn không thể thay đổi các hằng số char được chỉ ra bởi các con trỏ này. Vì vậy, bất cứ điều gì như:

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

sẽ không làm việc. Thay vào đó, bạn nên có một biến riêng (mảng char) để giữ kết quả. Một cái gì đó như thế này:

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
những gì về kết quả char *; result = calloc (strlen (one) + strlen (hai) +1, sizeof (char)); và THEN các strcpy + strcat?
luiscubal

3
@luiscubal: Có, nó cũng sẽ hoạt động ... chỉ cần sử dụng một (char *) cast, vì calloc trả về void *
codaddict

5
Vấn đề với câu trả lời này là kích thước mảng mã hóa cứng. Đó là một thói quen thực sự xấu, đặc biệt là nếu bạn không biết kích cỡ "một" và "hai" là gì.
Paul Tomblin

1
Trong ví dụ đầu tiên, strcpy(one,two);nên strcat(one,two);(không phải điều đó làm cho nó đúng, như bạn chỉ ra một cách chính xác).
Alok Singhal

1
Thế còn sprintf(dest,"%s%s",one,two)và quên bản sao?
mở

81

Cách C:

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

Cách C ++:

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

Cách biên dịch thời gian:

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

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

31

Nếu bạn đang sử dụng C ++, tại sao bạn không sử dụng std::stringthay vì chuỗi kiểu C?

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

std::string three= one+two;

Nếu bạn cần truyền chuỗi này đến hàm C, chỉ cần truyền three.c_str()


7
Bởi vì tôi đang sử dụng một thư viện được mã hóa bằng C nên các hàm trả về const char *
Anthoni Caldwell

1
@AnthoniCaldwell: Cảm ơn đã cười. Tôi không thể vì áp lực công việc
.: D

Nghe có vẻ như đã đến lúc cho một công việc mới? ...
Tối đa

20

Sử dụng std::string:

#include <string>

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

10
Cuộc gọi nhà xây dựng rõ ràng thứ hai là không cần thiết
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()

Đã cập nhật: thay đổi string total = string(one) + string(two); thành string total( string(one) + two );vì lý do hiệu suất (tránh xây dựng chuỗi hai và tổng chuỗi tạm thời)

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

@iburidu bạn đã đo chưa? Điều gì về các tình huống mà an toàn hơn hẳn hiệu suất? (Chúng là những tình huống phổ biến)
Sqeaky

3
@Sqeaky Hoàn toàn không có tình huống nào an toàn hơn bất kỳ giải pháp nào khác, nhưng nó LUÔN chậm hơn giải pháp thời gian biên dịch, bằng cách gọi hành vi thời gian chạy cũng như gần như chắc chắn gọi cấp phát bộ nhớ.
Alice

8

Một ví dụ nữa:

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

Nhưng trừ khi bạn đặc biệt không muốn hoặc không thể sử dụng thư viện chuẩn C ++, sử dụng std::stringcó thể an toàn hơn.


1
Nếu OP không thể sử dụng C ++, anh ta không thể sử dụng new. Và nếu anh ta có thể sử dụng nó, anh ta nên sử dụng std::string, như bạn nói.
Alok Singhal

5

Có vẻ như bạn đang sử dụng C ++ với thư viện C và do đó bạn cần phải làm việc với const char *.

Tôi đề nghị gói chúng const char *vào std::string:

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

5

Trước hết, bạn phải tạo một số không gian bộ nhớ động. Sau đó, bạn có thể strcat hai chuỗi vào nó. Hoặc bạn có thể sử dụng lớp "chuỗi" c ++. Cách C trường họ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ách C ++ mới

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

Tại sao bạn cần bộ nhớ động?
Luca Matteis

4
-1 đối với tôi, đầu tiên với C-way bạn cần sử dụng malloc và miễn phí. Sau đó, ngay cả khi bạn làm mới thì cũng nên xóa [] và không xóa.
Naveen

Thư viện tôi đang sử dụng được mã hóa trong C không phải C ++ nên tất cả các hàm trả về const char * không phải là chuỗi.
Anthoni Caldwell

1
@Naveen, thẻ nói "C ++". Nếu bạn không thể sử dụng mới và xóa, thì anh ta không nên sử dụng thẻ C ++.
Paul Tomblin

5

Nếu bạn không biết kích thước của chuỗi, bạn có thể làm một cái gì đó như thế này:

#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

Bạn có thể sử dụng strstream. Nó chính thức bị phản đối, nhưng nó vẫn là một công cụ tuyệt vời nếu bạn cần làm việc với các chuỗi C, tôi nghĩ vậy.

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

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

Điều này sẽ viết onevà sau đó twovào luồng và nối thêm \0bằng cách sử dụng std::ends. Trong trường hợp cả hai chuỗi có thể kết thúc việc viết chính xác các 99ký tự - vì vậy sẽ không còn khoảng trống nào để viết \0- chúng tôi viết một chuỗi thủ công ở vị trí cuối cùng.


Khấu hao không nên quan trọng quá nhiều. Ngay cả khi nó bị xóa khỏi phiên bản tương lai của tiêu chuẩn, thì việc thực hiện lại trong không gian tên của bạn cũng không quá nhiều.
Steve Jessop

@Steve, thực sự :) Và việc viết streambufđầu ra trực tiếp của riêng bạn vào bộ đệm char được sử dụng ostreamcũng không quá khó.
Julian Schaub - litb

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

0

Kết nối hai con trỏ char không đổi mà không sử dụng lệnh strcpy trong cấp phát bộ nhớ động:

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;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.