Comment concaténer deux chaînes en C?

141

Comment ajouter deux chaînes?

J'ai essayé name = "derp" + "herp";, mais j'ai eu une erreur:

L'expression doit être de type intégral ou enum

Levi H
la source

Réponses:

184

C ne prend pas en charge les chaînes que certains autres langages ont. Une chaîne en C est juste un pointeur vers un tableau chardont se termine par le premier caractère nul. Il n'y a pas d'opérateur de concaténation de chaîne dans C.

Utilisez strcatpour concaténer deux chaînes. Vous pouvez utiliser la fonction suivante pour le faire:

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

Ce n'est pas le moyen le plus rapide de le faire, mais vous ne devriez pas vous en soucier maintenant. Notez que la fonction renvoie un bloc de mémoire allouée au tas à l'appelant et transmet la propriété de cette mémoire. C'est la responsabilité de l'appelant à freela mémoire lorsqu'elle n'est plus nécessaire.

Appelez la fonction comme ceci:

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

Si vous êtes gêné par les performances, vous voudrez éviter d'analyser à plusieurs reprises les tampons d'entrée à la recherche du terminateur nul.

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

Si vous prévoyez de travailler beaucoup avec des chaînes, vous feriez peut-être mieux d'utiliser un autre langage prenant en charge les chaînes de manière de premier ordre.

David Heffernan
la source
1
Petit peu: le code pourrait faire la copie de la première partie de la chaîne en dernier et ensuite return memcpy(result, s1, len1);. Bien qu'il s'agisse d'une micro-optimisation ou au moins d'un peu de code golfique, de telles améliorations potentielles sur les opérations de base sur les cordes peuvent avoir une valeur étant donné leur grande utilisation.
chux
2
Petite amélioration des performances de la première version utilisant stpcpy, qui renvoie un pointeur vers la fin de la première chaîne:strcpy(stpcpy(result, s1), s2);
Daniel
17
#include <stdio.h>

int main(){
    char name[] =  "derp" "herp";
    printf("\"%s\"\n", name);//"derpherp"
    return 0;
}
BLUEPIXY
la source
1
Cela fonctionne également pour les macros en c, ce qui vaut la peine d'être noté
Abe Fehr
15

David Heffernan a expliqué le problème dans sa réponse et j'ai écrit le code amélioré. Voir ci-dessous.

Une fonction générique

Nous pouvons écrire une fonction variadique utile pour concaténer n'importe quel nombre de chaînes:

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

Usage

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

Production:

  // Empty line
a
ab
abc

Nettoyer

Notez que vous devez libérer la mémoire allouée lorsque cela devient inutile pour éviter les fuites de mémoire:

char *str = concat(2,"a","b");
println(str);
free(str);
mmdemirbas
la source
3
Les arguments de calloc sont inversés. Ils doivent être comptés puis taille. Vous vous en tirez ici grâce à l'identité multiplicative, puisque sizeof (char) est défini comme étant 1.
Andy
Considérez int len-> size_t lencomme size_tc'est le bon type pour le code "taille". Aussi // room for NULL-> // room for null character NULLimplique le pointeur nul.
chux
10

Je suppose que vous en avez besoin pour des choses ponctuelles. Je suppose que vous êtes un développeur PC.

Utilisez la pile, Luke. Utilisez-le partout. Ne pas utiliser malloc / gratuit pour les petites allocations, jamais .

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

Si 10 Ko par chaîne ne suffisent pas, ajoutez un zéro à la taille et ne vous inquiétez pas, - ils libéreront de toute façon leur mémoire de pile à la fin des étendues.


la source
1
Cela serait plus clairement exprimé commesnprintf(result, sizeof result, "%s %s %s", s1, s2, s3);
MM
8

Vous devez utiliser strcat, ou mieux, strncat. Google it (le mot-clé est "concaténation").

orlp
la source
8
Attention: strncat()c'est une fonction diaboliquement difficile à utiliser correctement. Rapidement, sans regarder le manuel, quelle longueur spécifiez-vous strncat()? Si vous avez dit "la longueur du tampon", vous venez de bien démontrer mon point de vue. Il a une interface contre-intuitive et lorsque vous avez suffisamment de données pour l'utiliser en toute sécurité, vous n'avez pas besoin d'utiliser la fonction en premier lieu - il existe d'autres alternatives plus rapides et plus efficaces (telles que strcpy()ou memmove()) qui pourraient être utilisées au lieu. Quasiment quelle que soit la question de «que dois-je utiliser», ce strncat()n'est pas la réponse.
Jonathan Leffler
5

Vous ne pouvez pas ajouter de littéraux de chaîne comme celui en C. Vous devez créer un tampon de taille de chaîne littérale un + chaîne littérale deux + un octet pour le caractère de terminaison nul et copier les littéraux correspondants dans ce tampon et également vous assurer qu'il est terminé par null . Ou vous pouvez utiliser des fonctions de bibliothèque comme strcat.

Mahesh
la source
3

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

Alternativement avec l'extension 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;
}

Voir malloc , gratuit et asprintf pour plus de détails.

Peter Mortensen
la source
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);
}
user2870383
la source
2

Concaténer les chaînes

La concaténation de deux chaînes en C peut être effectuée d'au moins 3 façons: -

1) En copiant la chaîne 2 à la fin de la chaîne 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) En copiant la chaîne 1 et la chaîne 2 dans la chaîne 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) En utilisant la fonction 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;
}
Paurav Shah
la source
0

En C, vous n'avez pas vraiment de chaînes, en tant qu'objet générique de première classe. Vous devez les gérer comme des tableaux de caractères, ce qui signifie que vous devez déterminer comment vous souhaitez gérer vos tableaux. Une solution consiste à utiliser des variables normales, par exemple placées sur la pile. Une autre façon est de les attribuer dynamiquement en utilisant malloc.

Une fois que vous avez trié, vous pouvez copier le contenu d'un tableau dans un autre, pour concaténer deux chaînes en utilisant strcpyou strcat.

Cela dit, C a le concept de "chaînes littérales", qui sont des chaînes connues au moment de la compilation. Lorsqu'ils sont utilisés, ils seront un tableau de caractères placé en mémoire morte. Il est cependant possible de concaténer deux chaînes littérales en les écrivant l'une à côté de l'autre, comme dans "foo" "bar", ce qui créera la chaîne littérale "foobar".

Lindydancer
la source
0

en utilisant 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);
Khalegh Salehi
la source