Як з'єднати два рядки в C?


141

Як додати два рядки?

Я спробував name = "derp" + "herp";, але сталася помилка:

Експресія повинна мати інтегральний або enum тип

Відповіді:


184

C не підтримує рядки, якими є деякі інші мови. Рядок на C - це лише вказівник на масив, charякий закінчується першим нульовим символом. У C. немає оператора конкатенації рядків.

Використовуйте strcatдля об'єднання двох рядків. Ви можете використовувати наступну функцію для цього:

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

Це не найшвидший спосіб зробити це, але ви не повинні турбуватися про це зараз. Зауважте, що функція повертає абонент, що виділив блок пам'яті, що купується, і передає право власності на цю пам'ять. Це відповідальність абонента перед freeпам'яттю, коли вона більше не потрібна.

Викличте функцію так:

char* s = concat("derp", "herp");
// do things with s
free(s); // deallocate the string

Якщо вас не турбує продуктивність, ви хочете уникати багаторазового сканування вхідних буферів, шукаючи нульовий термінатор.

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

Якщо ви плануєте зробити багато роботи з рядками, то вам може бути краще використовувати іншу мову, яка має підтримку рядків першого класу.


1
Маленький біт: код може зробити копію першої частини рядка останньою, а потім return memcpy(result, s1, len1);. Хоча мікрооптимізація чи принаймні трохи гольфу з кодом, такі потенційні вдосконалення основних операцій із струнами можуть мати значення з огляду на їх високе використання.
chux

2
Невелике покращення продуктивності першої версії за допомогою stpcpy, яка повертає вказівник на кінець першого рядка:strcpy(stpcpy(result, s1), s2);
Даніель

17
#include <stdio.h>

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

1
Він також працює для макросів у c, що варто відзначити
Abe Fehr

15

Девід Геффернан пояснив це питання у своїй відповіді, і я написав удосконалений код. Дивись нижче.

Родова функція

Ми можемо написати корисну варіативну функцію для об'єднання будь-якої кількості рядків:

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

Вихід:

  // Empty line
a
ab
abc

Прибирати

Зауважте, що вам слід звільнити виділену пам'ять, коли вона стане непотрібною, щоб уникнути витоків пам'яті:

char *str = concat(2,"a","b");
println(str);
free(str);

3
Аргументи для висловлення зворотні. Їх слід рахувати, то розмір. Ви дістаєтесь тут, завдяки мультиплікаційній ідентичності, оскільки розмір (char) визначений як 1.
Енді

Поміркуйте int len-> size_t lenяк size_tце правильний тип коду "розмір". Також // room for NULL-> // room for null character NULLмає на увазі нульовий покажчик.
chux

9

Я припускаю, що вам це потрібно для разових речей. Я припускаю, що ви розробник ПК.

Скористайтеся стеком, Лука. Використовуйте його всюди. Не використовуйте Танос / безкоштовно для невеликих розподілів, коли - небудь .

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

Якщо 10 КБ на рядок буде недостатньо, додайте нуль до розміру і не турбуйте, - вони все одно звільнять свою стекову пам'ять в кінці області.


1
Це було б більш чітко виражено якsnprintf(result, sizeof result, "%s %s %s", s1, s2, s3);
ММ

8

Ви повинні використовувати strcat, або краще, strncat. Google it (ключове слово - "об'єднати").


8
Остерігайтеся: strncat()це надзвичайно складна функція правильно використовувати. Швидко, не дивлячись на посібник, яку довжину ви вказуєте strncat()? Якщо ви сказали "довжина буфера", ви просто добре продемонстрували мою думку. Він має контр-інтуїтивно зрозумілий інтерфейс, і коли у вас є достатня кількість даних, щоб безпечно їх використовувати, вам не потрібно використовувати функцію в першу чергу - є інші, швидші та ефективніші альтернативи (наприклад, strcpy()або memmove()), які можуть бути використані замість цього. Насправді все, що завгодно питання "що я повинен використовувати", strncat()- це не відповідь.
Джонатан Леффлер

5

Ви не можете додавати рядкові літерали на зразок цього у C. Ви повинні створити буфер розміром рядкового літералу один + рядковий літерал два + байт для нульового символу завершення та скопіювати відповідні літерали в цей буфер, а також переконатися, що він недійсний . Або ви можете використовувати такі функції, як бібліотека strcat.


3

Без розширення 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;
}

Як варіант із розширенням 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;
}

Докладнішу інформацію див. У програмі malloc , free та asprintf .


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

З'єднайте струни

Об’єднання будь-яких двох рядків на C може бути зроблено принаймні 3 способи: -

1) Копіюючи рядок 2 до кінця рядка 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) Копіюючи рядок 1 і рядок 2 до рядка 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) За допомогою функції 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

У C насправді у вас немає рядків як загального об'єкта першого класу. Ви повинні керувати ними як масивами символів, а це означає, що ви повинні визначити, як ви хочете керувати своїми масивами. Один із способів - це звичайні змінні, наприклад, розміщені в стеку. Інший спосіб - динамічно розподілити їх, використовуючиmalloc .

Після сортування ви можете скопіювати вміст одного масиву в інший, щоб об'єднати два рядки, використовуючи strcpyабоstrcat .

Сказавши це, у C є поняття "рядкові літерали", які є рядками, відомими під час компіляції. При їх використанні вони будуть масивом символів, розміщеним у пам'яті лише для читання. Однак можливо об'єднати два рядкові літерали, записавши їх поруч, як у "foo" "bar", що створить буквений рядок "foobar".


0

використовуючи 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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.