C'de iki dizeyi nasıl birleştirebilirim?


141

İki dizeyi nasıl eklerim?

Denedim name = "derp" + "herp";, ama bir hata aldım:

İfadenin integral veya enum tipi olması gerekir

Yanıtlar:


184

C, diğer bazı dillerin sahip olduğu dizeler için desteğe sahip değildir. C'deki bir dize char, ilk null karakterle sonlandırılan bir diziye yalnızca bir göstericidir . C'de dize birleştirme operatörü yok.

strcatİki dizeyi birleştirmek için kullanın . Bunu yapmak için aşağıdaki işlevi kullanabilirsiniz:

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

Bunu yapmanın en hızlı yolu bu değil, ama şimdi bunun için endişelenmemelisin. İşlevin, arayana bir yığın bellek ayrılmış bloğu döndürdüğünü ve bu belleğin sahipliğini aktardığını unutmayın. freeArtık ihtiyaç duyulmadığında , arayan kişinin hafızaya sorumluluğu vardır .

İşlevi şu şekilde çağırın:

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

Performanstan rahatsız olsaydınız, boş sonlandırıcıyı arayan giriş arabelleklerini tekrar tekrar taramaktan kaçınmak istersiniz.

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

Dizelerle çok fazla iş yapmayı planlıyorsanız, dizeler için birinci sınıf desteğe sahip farklı bir dil kullanmaktan daha iyi olabilirsiniz.


1
Küçük bit: kod, dizenin ilk bölümünün kopyasını son olarak yapabilir return memcpy(result, s1, len1);. Her ne kadar bir mikro optimizasyon veya en azından biraz kod golf olsa da, temel dizi işlemlerindeki bu tür potansiyel iyileştirmeler yüksek kullanımları göz önüne alındığında değere sahip olabilir.
chux - Monica'yı eski durumuna getir

2
stpcpyİlk dizenin sonuna bir işaretçi döndüren ilk sürümün küçük performans artışı :strcpy(stpcpy(result, s1), s2);
Daniel

17
#include <stdio.h>

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

1
Ayrıca dikkat
çekmeye

15

David Heffernan konuyu cevabında açıkladı ve ben geliştirilmiş kodu yazdım. Aşağıya bakınız.

Genel bir işlev

İstediğiniz sayıda dizeyi birleştirmek için yararlı bir varyasyon işlevi yazabiliriz :

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

kullanım

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

Çıktı:

  // Empty line
a
ab
abc

Temizlemek

Bellek sızıntılarını önlemek için ayrılan belleği gereksiz hale geldiğinde boşaltmanız gerektiğini unutmayın:

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

3
Calloc için argümanlar geriye dönüktür. Sayıları sonra boyutu olmalıdır. Sizeof (char) 1 olarak tanımlandığından, çarpımsal kimlik sayesinde buradan kurtulursunuz.
Andy

"Size" kodu için doğru türü olduğu gibi int len-> düşünün . Ayrıca -> boş gösterici anlamına gelir. size_t lensize_t// room for NULL// room for null character NULL
chux - Monica'yı eski durumuna getir

10

Bir kereye mahsus şeyler için ihtiyacınız olduğunu varsayacağım. Bir PC geliştiricisi olduğunuzu varsayacağım.

Yığını kullan, Luke. Her yerde kullanın. , Malloc / küçük tahsisleri için ücretsiz kullanmayın hiç .

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

Dize başına 10 KB yeterli olmazsa, boyuta sıfır ekleyin ve rahatsız etmeyin - yine de kapsamların sonunda yığın belleklerini serbest bırakırlar.


1
Bu daha açık bir şekilde ifade edilebilirsnprintf(result, sizeof result, "%s %s %s", s1, s2, s3);
MM

8

Kullanmalısın strcatya da daha iyisi strncat. Google it (anahtar kelime "birleştiriliyor").


8
Dikkat: strncat()doğru kullanmak son derece zor bir işlevdir. Hızla, kılavuza bakmadan, hangi uzunlukta belirtmeyi seçersiniz strncat()? Eğer "tamponun uzunluğu" derseniz, benim açımdan gayet güzel bir örnek verdiniz. Karşı sezgisel bir arayüze sahiptir ve güvenli bir şekilde kullanmak için yeterli veriye sahipseniz, işlevi ilk etapta kullanmanız gerekmez - kullanılabilecek başka, daha hızlı ve daha verimli alternatifler ( strcpy()veya gibi memmove()) vardır. yerine. Hemen hemen 'ne kullanmalıyım' sorusu ne olursa olsun strncat(), cevap değil.
Jonathan Leffler

5

C'de olduğu gibi dize değişmezleri ekleyemezsiniz . Boş sonlandırma karakteri için dize değişmez bir + dize değişmez iki + bir bayt boyutunda bir arabellek oluşturmalı ve karşılık gelen değişmezleri bu ara belleğe kopyalamanız ve ayrıca boş bırakıldığından emin olmanız gerekir. . Veya gibi kütüphane işlevlerini kullanabilirsiniz strcat.


3

GNU uzantısı olmadan:

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

Alternatif olarak GNU uzantısı ile:

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

Daha fazla bilgi için malloc , free ve asprintf'e bakınız.


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

Dizeleri Birleştir

C'de herhangi iki dizeyi birleştirmek en az 3 yolla yapılabilir: -

1) Dize 2'yi Dize 1'in sonuna kopyalayarak

#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) Dize 1 ve dize 2'yi dize 3'e kopyalayarak

#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 () fonksiyonunu kullanarak

#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'de, genel bir birinci sınıf nesne olarak dizeleriniz gerçekten yoktur. Bunları karakter dizileri olarak yönetmelisiniz, yani dizilerinizi nasıl yönetmek istediğinizi belirlemeniz gerekir. Bunun bir yolu normal değişkenlerdir, örneğin yığına yerleştirilir. Başka bir yol, bunları kullanarak dinamik olarak ayırmaktırmalloc .

Bunu sıraladıktan sonra, strcpyveya kullanarak iki dizeyi birleştirmek için bir dizinin içeriğini diğerine kopyalayabilirsiniz.strcat .

Bunu söyledikten sonra, C derleme zamanında bilinen dizeler olan "dizi değişmezleri" kavramına sahiptir. Kullanıldığında, salt okunur belleğe yerleştirilmiş bir karakter dizisi olacaktır. Bununla birlikte, iki dize değişmezini "foo" "bar", "foobar" dize değerini oluşturacak şekilde, olduğu gibi yan yana yazarak birleştirmek mümkündür .


0

memcpy kullanma

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);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.