Làm thế nào để tôi nối hai chuỗi trong C?


141

Làm thế nào để tôi thêm hai chuỗi?

Tôi đã thử name = "derp" + "herp";, nhưng tôi gặp lỗi:

Biểu thức phải có loại tích phân hoặc enum

Câu trả lời:


184

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 freevớ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.


1
Bit nhỏ: mã có thể thực hiện sao chép phần đầu tiên của chuỗi sau đó 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.
chux - Tái lập Monica

2
Cải thiện hiệu suất nhỏ của phiên bản đầu tiên bằng cách sử dụng stpcpy, trả về một con trỏ đến cuối chuỗi đầu tiên:strcpy(stpcpy(result, s1), s2);
Daniel

17
#include <stdio.h>

int main(){
    char name[] =  "derp" "herp";
    printf("\"%s\"\n", name);//"derpherp"
    return 0;
}

1
Nó cũng hoạt động cho các macro trong c, đáng chú ý
Abe Fehr

15

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.

Một hàm chung

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

Sử dụng

#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

Dọn dẹp

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

3
Các đối số để calloc là lạc hậu. Họ nên được tính sau đó kích thước. Bạn thoát khỏi nó ở đây nhờ vào danh tính nhân, vì sizeof (char) được xác định là 1.
Andy

Xem xét int len-> size_t lennhư size_tlà loại đúng cho mã "kích thước". Ngoài ra // room for NULL-> // room for null character NULLngụ ý con trỏ null.
chux - Phục hồi Monica

9

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.


1
Điều này sẽ được thể hiện rõ ràng hơn nhưsnprintf(result, sizeof result, "%s %s %s", s1, s2, s3);
MM

8

Bạn nên sử dụng strcat, hoặc tốt hơn , strncat. Google nó (từ khóa là "nối").


8
Cẩn thận: 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.
Jonathan Leffler

5

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.


3

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

Xem malloc , miễn phíasprintf để biết thêm chi tiết.


2
#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);
}

2

Dây nối

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

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 strcpyhoặ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.


0

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