ฉันจะเชื่อมสองสายเข้าด้วยกันใน C ได้อย่างไร


141

ฉันจะเพิ่มสองสายได้อย่างไร

ฉันพยายามname = "derp" + "herp";แต่ฉันพบข้อผิดพลาด:

การแสดงออกจะต้องมีประเภทหนึ่งหรือ enum

คำตอบ:


184

C ไม่มีการรองรับสตริงที่บางภาษาอื่นมี สตริงใน C เป็นเพียงตัวชี้ไปยังอาร์เรย์ของcharที่จะถูกยกเลิกโดยตัวละคร null แรก ไม่มีตัวดำเนินการเรียงต่อสตริงใน 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

หากคุณเกิดความรำคาญจากการทำงานคุณควรหลีกเลี่ยงการสแกนบัฟเฟอร์อินพุตซ้ำ ๆ เพื่อค้นหา null-terminator

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 - Reinstate Monica

2
การปรับปรุงประสิทธิภาพเล็กน้อยของรุ่นแรกโดยใช้stpcpyซึ่งจะส่งกลับตัวชี้ไปยังจุดสิ้นสุดของสตริงแรก:strcpy(stpcpy(result, s1), s2);
Daniel

17
#include <stdio.h>

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

1
นอกจากนี้ยังใช้งานได้กับมาโครใน c ซึ่งเป็นที่น่าสังเกต
Abe Fehr

15

David Heffernan อธิบายปัญหาในคำตอบของเขาและฉันเขียนรหัสที่ปรับปรุงแล้ว ดูด้านล่าง

ฟังก์ชั่นทั่วไป

เราสามารถเขียนฟังก์ชัน variadic ที่มีประโยชน์เพื่อเชื่อมสตริงจำนวนเท่าใดก็ได้:

#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
อาร์กิวเมนต์ของ calloc ย้อนกลับ พวกเขาควรจะนับขนาด คุณจะอยู่ห่างจากที่นี่ด้วยตัวตนแบบทวีคูณเนื่องจากขนาดของ (ถ่าน) ถูกกำหนดให้เป็น 1
Andy

พิจารณาint len-> size_t lenตามที่size_tเป็นประเภทที่ถูกต้องสำหรับรหัส "ขนาด" นอกจากนี้// room for NULL-> // room for null character NULLหมายถึงตัวชี้ null
chux - Reinstate Monica

10

ฉันจะสมมติว่าคุณต้องการมันสำหรับสิ่งเดียว ฉันจะถือว่าคุณเป็นนักพัฒนาพีซี

ใช้กองซ้อนลุค ใช้งานได้ทุกที่ อย่าใช้ malloc / ฟรีสำหรับการจัดสรรขนาดเล็กที่เคย

#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 KB ต่อสายอักขระไม่เพียงพอให้เพิ่มขนาดให้เป็นศูนย์และไม่ต้องกังวล - พวกมันจะปล่อยหน่วยความจำสแต็กที่ส่วนท้ายของขอบเขต


1
สิ่งนี้จะแสดงอย่างชัดเจนยิ่งขึ้นเมื่อsnprintf(result, sizeof result, "%s %s %s", s1, s2, s3);
MM

8

คุณควรใช้หรือดีกว่าstrcat strncatGoogle it (คำหลักคือ "การต่อข้อมูล")


8
ระวัง: strncat()เป็นฟังก์ชั่นที่กินเลือดออกยากที่จะใช้อย่างถูกต้อง อย่างรวดเร็วโดยไม่ต้องดูคู่มือคุณระบุความยาวstrncat()เท่าใด ถ้าคุณพูดว่า "ความยาวของบัฟเฟอร์" คุณแค่แสดงให้เห็นถึงจุดของฉันเป็นอย่างดี มันมีส่วนต่อประสานที่ใช้งานง่ายและเมื่อคุณมีข้อมูลเพียงพอที่จะใช้อย่างปลอดภัยคุณไม่จำเป็นต้องใช้ฟังก์ชั่นในตอนแรก - มีตัวเลือกอื่น ๆ ที่เร็วกว่าและมีประสิทธิภาพมากกว่า (เช่นstrcpy()หรือmemmove()) ที่สามารถใช้งานได้ แทน. สวยมากไม่ว่าคำถามของ 'ฉันควรใช้อะไร' strncat()ไม่ใช่คำตอบ
Jonathan Leffler

5

คุณไม่สามารถเพิ่มตัวอักษรสตริงเช่นเดียวกับใน C คุณต้องสร้างบัฟเฟอร์ขนาดของสตริงตัวอักษรหนึ่ง + สตริงตัวอักษรสอง + a ไบต์สำหรับอักขระการเลิกจ้างโมฆะและคัดลอกตัวอักษรที่สอดคล้องกับบัฟเฟอร์นั้นและตรวจสอบให้แน่ใจว่ามันถูกยกเลิกเป็นโมฆะ . strcatหรือคุณสามารถใช้ฟังก์ชั่นเช่นห้องสมุด


3

ไม่มี GNU extension:

#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 , ฟรีและ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อีกวิธีหนึ่งคือการจัดสรรแบบไดนามิกโดยใช้พวกเขา

เมื่อคุณได้ที่เรียงคุณสามารถคัดลอกเนื้อหาของหนึ่งอาร์เรย์อื่นเพื่อเชื่อมสองสตริงใช้หรือstrcpystrcat

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