Câu trả lời:
C không có sự hỗ trợ cho các chuỗi mà một số ngôn ngữ khác có. Một chuỗi trong C chỉ là một con trỏ tới một mảng char
được kết thúc bởi ký tự null đầu tiên. Không có toán tử nối chuỗi trong C.
Sử dụng strcat
để nối hai chuỗi. Bạn có thể sử dụng chức năng sau để làm điều đó:
#include <stdlib.h>
#include <string.h>
char* concat(const char *s1, const char *s2)
{
char *result = malloc(strlen(s1) + strlen(s2) + 1); // +1 for the null-terminator
// in real code you would check for errors in malloc here
strcpy(result, s1);
strcat(result, s2);
return result;
}
Đây không phải là cách nhanh nhất để làm điều này, nhưng bạn không nên lo lắng về điều đó ngay bây giờ. Lưu ý rằng hàm trả về một khối bộ nhớ được phân bổ heap cho người gọi và chuyển quyền sở hữu bộ nhớ đó. Đó là trách nhiệm của người gọi đối free
với bộ nhớ khi không còn cần thiết.
Gọi hàm như thế này:
char* s = concat("derp", "herp");
// do things with s
free(s); // deallocate the string
Nếu bạn thực sự bị làm phiền bởi hiệu suất thì bạn sẽ muốn tránh quét liên tục các bộ đệm đầu vào đang tìm kiếm bộ kết thúc null.
char* concat(const char *s1, const char *s2)
{
const size_t len1 = strlen(s1);
const size_t len2 = strlen(s2);
char *result = malloc(len1 + len2 + 1); // +1 for the null-terminator
// in real code you would check for errors in malloc here
memcpy(result, s1, len1);
memcpy(result + len1, s2, len2 + 1); // +1 to copy the null-terminator
return result;
}
Nếu bạn đang dự định thực hiện nhiều công việc với các chuỗi thì bạn có thể tốt hơn bằng cách sử dụng một ngôn ngữ khác có hỗ trợ hạng nhất cho chuỗi.
stpcpy
, trả về một con trỏ đến cuối chuỗi đầu tiên:strcpy(stpcpy(result, s1), s2);
David Heffernan đã giải thích vấn đề này trong câu trả lời của anh ấy và tôi đã viết mã cải tiến. Xem bên dưới.
Chúng ta có thể viết một hàm matrixdic hữu ích để nối bất kỳ số chuỗi nào:
#include <stdlib.h> // calloc
#include <stdarg.h> // va_*
#include <string.h> // strlen, strcpy
char* concat(int count, ...)
{
va_list ap;
int i;
// Find required length to store merged string
int len = 1; // room for NULL
va_start(ap, count);
for(i=0 ; i<count ; i++)
len += strlen(va_arg(ap, char*));
va_end(ap);
// Allocate memory to concat strings
char *merged = calloc(sizeof(char),len);
int null_pos = 0;
// Actually concatenate strings
va_start(ap, count);
for(i=0 ; i<count ; i++)
{
char *s = va_arg(ap, char*);
strcpy(merged+null_pos, s);
null_pos += strlen(s);
}
va_end(ap);
return merged;
}
#include <stdio.h> // printf
void println(char *line)
{
printf("%s\n", line);
}
int main(int argc, char* argv[])
{
char *str;
str = concat(0); println(str); free(str);
str = concat(1,"a"); println(str); free(str);
str = concat(2,"a","b"); println(str); free(str);
str = concat(3,"a","b","c"); println(str); free(str);
return 0;
}
Đầu ra:
// Empty line
a
ab
abc
Lưu ý rằng bạn nên giải phóng bộ nhớ được phân bổ khi không cần thiết để tránh rò rỉ bộ nhớ:
char *str = concat(2,"a","b");
println(str);
free(str);
int len
-> size_t len
như size_t
là loại đúng cho mã "kích thước". Ngoài ra // room for NULL
-> // room for null character
NULL
ngụ ý con trỏ null.
Tôi sẽ cho rằng bạn cần nó cho những thứ một lần. Tôi sẽ cho rằng bạn là nhà phát triển PC.
Sử dụng ngăn xếp, Luke. Sử dụng nó ở mọi nơi. Đừng sử dụng malloc / miễn phí cho các khoản phân bổ nhỏ, bao giờ hết .
#include <string.h>
#include <stdio.h>
#define STR_SIZE 10000
int main()
{
char s1[] = "oppa";
char s2[] = "gangnam";
char s3[] = "style";
{
char result[STR_SIZE] = {0};
snprintf(result, sizeof(result), "%s %s %s", s1, s2, s3);
printf("%s\n", result);
}
}
Nếu 10 KB mỗi chuỗi sẽ không đủ, hãy thêm số 0 vào kích thước và đừng bận tâm - dù sao họ cũng sẽ giải phóng bộ nhớ ngăn xếp của mình ở cuối phạm vi.
snprintf(result, sizeof result, "%s %s %s", s1, s2, s3);
Bạn nên sử dụng strcat
, hoặc tốt hơn , strncat
. Google nó (từ khóa là "nối").
strncat()
là một chức năng khó sử dụng chính xác. Nhanh chóng, không cần nhìn vào hướng dẫn, bạn chỉ định độ dài là strncat()
bao nhiêu? Nếu bạn nói "chiều dài của bộ đệm", bạn chỉ cần chứng minh quan điểm của tôi một cách độc đáo. Nó có giao diện phản trực quan và khi bạn có đủ dữ liệu để sử dụng một cách an toàn, bạn không cần sử dụng chức năng này ngay từ đầu - có những cách khác, nhanh hơn và hiệu quả hơn (như strcpy()
hoặc memmove()
) có thể được sử dụng thay thế. Gần như bất cứ câu hỏi nào về 'tôi nên sử dụng cái gì', strncat()
không phải là câu trả lời.
Bạn không thể thêm chuỗi ký tự như thế trong C. Bạn phải tạo bộ đệm có kích thước chuỗi ký tự một + chuỗi ký tự hai + một byte cho ký tự kết thúc null và sao chép các ký tự tương ứng vào bộ đệm đó và cũng đảm bảo rằng nó bị hủy . Hoặc bạn có thể sử dụng các chức năng thư viện như strcat
.
Không có phần mở rộng GNU:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char str1[] = "First";
const char str2[] = "Second";
char *res;
res = malloc(strlen(str1) + strlen(str2) + 1);
if (!res) {
fprintf(stderr, "malloc() failed: insufficient memory!\n");
return EXIT_FAILURE;
}
strcpy(res, str1);
strcat(res, str2);
printf("Result: '%s'\n", res);
free(res);
return EXIT_SUCCESS;
}
Ngoài ra với phần mở rộng GNU:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char str1[] = "First";
const char str2[] = "Second";
char *res;
if (-1 == asprintf(&res, "%s%s", str1, str2)) {
fprintf(stderr, "asprintf() failed: insufficient memory!\n");
return EXIT_FAILURE;
}
printf("Result: '%s'\n", res);
free(res);
return EXIT_SUCCESS;
}
#include <string.h>
#include <stdio.h>
int main()
{
int a,l;
char str[50],str1[50],str3[100];
printf("\nEnter a string: ");
scanf("%s",str);
str3[0]='\0';
printf("\nEnter the string which you want to concat with string one: ");
scanf("%s",str1);
strcat(str3,str);
strcat(str3,str1);
printf("\nThe string is %s\n",str3);
}
Nối hai chuỗi bất kỳ trong C có thể được thực hiện theo ít nhất 3 cách: -
1) Bằng cách sao chép chuỗi 2 vào cuối chuỗi 1
#include <stdio.h>
#include <string.h>
#define MAX 100
int main()
{
char str1[MAX],str2[MAX];
int i,j=0;
printf("Input string 1: ");
gets(str1);
printf("\nInput string 2: ");
gets(str2);
for(i=strlen(str1);str2[j]!='\0';i++) //Copying string 2 to the end of string 1
{
str1[i]=str2[j];
j++;
}
str1[i]='\0';
printf("\nConcatenated string: ");
puts(str1);
return 0;
}
2) Bằng cách sao chép chuỗi 1 và chuỗi 2 sang chuỗi 3
#include <stdio.h>
#include <string.h>
#define MAX 100
int main()
{
char str1[MAX],str2[MAX],str3[MAX];
int i,j=0,count=0;
printf("Input string 1: ");
gets(str1);
printf("\nInput string 2: ");
gets(str2);
for(i=0;str1[i]!='\0';i++) //Copying string 1 to string 3
{
str3[i]=str1[i];
count++;
}
for(i=count;str2[j]!='\0';i++) //Copying string 2 to the end of string 3
{
str3[i]=str2[j];
j++;
}
str3[i]='\0';
printf("\nConcatenated string : ");
puts(str3);
return 0;
}
3) Bằng cách sử dụng hàm strcat ()
#include <stdio.h>
#include <string.h>
#define MAX 100
int main()
{
char str1[MAX],str2[MAX];
printf("Input string 1: ");
gets(str1);
printf("\nInput string 2: ");
gets(str2);
strcat(str1,str2); //strcat() function
printf("\nConcatenated string : ");
puts(str1);
return 0;
}
Trong C, bạn không thực sự có các chuỗi, như là một đối tượng hạng nhất chung. Bạn phải quản lý chúng dưới dạng các mảng ký tự, điều đó có nghĩa là bạn phải xác định cách bạn muốn quản lý mảng của mình. Một cách là các biến thông thường, ví dụ như được đặt trên ngăn xếp. Một cách khác là phân bổ chúng một cách linh hoạt bằng cách sử dụng malloc
.
Khi bạn đã sắp xếp xong, bạn có thể sao chép nội dung của một mảng sang mảng khác, để nối hai chuỗi bằng strcpy
hoặc strcat
.
Phải nói rằng, C có khái niệm "chuỗi ký tự", là các chuỗi được biết đến tại thời điểm biên dịch. Khi được sử dụng, chúng sẽ là một mảng ký tự được đặt trong bộ nhớ chỉ đọc. Tuy nhiên, có thể ghép hai chuỗi ký tự bằng cách viết chúng cạnh nhau, như trong "foo" "bar"
, sẽ tạo ra chuỗi "foobar" theo nghĩa đen.
sử dụng memcpy
char *str1="hello";
char *str2=" world";
char *str3;
str3=(char *) malloc (11 *sizeof(char));
memcpy(str3,str1,5);
memcpy(str3+strlen(str1),str2,6);
printf("%s + %s = %s",str1,str2,str3);
free(str3);
return memcpy(result, s1, len1);
. Mặc dù tối ưu hóa vi mô hoặc ít nhất một chút về chơi gôn mã, những cải tiến tiềm năng như vậy đối với các hoạt động chuỗi cơ bản có thể có giá trị khi sử dụng cao.