Cで2つの文字列を連結するにはどうすればよいですか?


141

2つの文字列を追加するにはどうすればよいですか?

私は試しましたname = "derp" + "herp";が、エラーが発生しました:

式は整数型または列挙型でなければなりません

回答:


184

Cは、他の一部の言語が持っている文字列をサポートしていません。Cの文字列はchar、最初のnull文字で終了する配列へのポインタにすぎません。Cには文字列連結演算子はありません。

strcat2つの文字列を連結するために使用します。これを行うには、次の関数を使用できます。

#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ターミネーターを探すのを避けたいでしょう。

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-モニカを2016年

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 が彼の回答で問題を説明し、私は改良されたコードを書きました。下記参照。

ジェネリック関数

任意の数の文字列を連結するための便利な可変関数を書くことができます:

#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の引数は逆です。それらは次にサイズを数える必要があります。sizeof(文字)が1になるように定義されているのであなたは、ここでそれを乗法アイデンティティのおかげで逃げる
アンディ・

「サイズ」コードの正しいタイプであるint len-> size_t lenを検討してくださいsize_t。また、// room for NULL-> // room for null character NULLはnullポインタを意味します。
chux-モニカを2016年

9

一回限りのものに必要だと思います。あなたがPC開発者であると仮定します。

スタック、ルークを使用してください。どこでもそれを使用してください。、小さな割り当てのための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、より良い、またはstrncat。グーグルそれ(キーワードは「連結」です)。


8
注意:strncat()正しく使用するのは非常に難しい関数です。マニュアルを見ずにすばやく、どのくらいの長さを指定しstrncat()ますか?「バッファの長さ」と言ったら、私のポイントをうまく示しただけです。直感に反するインターフェースがあり、それを安全に使用するのに十分なデータがある場合、そもそも関数を使用する必要はありません。使用できる他の、より速く、より効率的な代替手段(strcpy()またはなどmemmove())があります。代わりに。「何を使うべきか」という質問はほとんど何でもstrncat()答えではありません。
Jonathan Leffler、2015

5

Cでそのような文字列リテラルを追加することはできません。文字列リテラル1 +文字列リテラル2 + null終了文字のバイトのサイズのバッファーを作成し、対応するリテラルをそのバッファーにコピーして、null終了であることを確認する必要があります。または、のようなライブラリ関数を使用できます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;
}

詳細については、mallocfreeasprintfを参照してください。


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の任意の2つの文字列を連結するには、少なくとも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では、汎用のファーストクラスオブジェクトとして、実際には文字列はありません。それらを文字の配列として管理する必要があります。つまり、配列の管理方法を決定する必要があります。1つの方法は、通常の変数、たとえばスタックに配置することです。別の方法は、を使用して動的に割り当てることmallocです。

並べ替えが完了したら、配列の内容を別の配列にコピーして、strcpyまたはを使用して2つの文字列を連結できstrcatます。

そうは言っても、Cには「文字列リテラル」の概念があります。これは、コンパイル時に既知の文字列です。使用すると、読み取り専用メモリに配置された文字配列になります。ただし、のように2つの文字列リテラルを隣り合わせに記述することで連結"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.