59 votes

Concaténer des chaînes en C, quelle méthode est la plus efficace?

Je suis tombé sur ces deux méthodes pour concaténer des chaînes de caractères:

Partie commune:

char* first= "First";
char* second = "Second";
char* both = malloc(strlen(first) + strlen(second) + 2);

Méthode 1:

strcpy(both, first);
strcat(both, " ");
strcat(both, second);

Méthode 2:

sprintf("%s %s", first, second);

Dans les deux cas, le contenu de both serait "First Second".

Je voudrais savoir lequel est le plus efficace (j'ai effectuer plusieurs opérations de concaténation), ou si vous connaissez une meilleure façon de le faire.

Merci pour votre temps.

EDIT: Dans le premier cas, l'espace pourrait avoir été à l'intérieur de l'une des chaînes.

73voto

Christoph Points 64389

Pour la lisibilité, j'irais avec

 char * s = malloc(snprintf(NULL, 0, "%s %s", first, second) + 1);
sprintf(s, "%s %s", first, second);
 

Si votre plate-forme prend en charge les extensions GNU, vous pouvez également utiliser asprintf() :

 char * s = NULL;
asprintf(&s, "%s %s", first, second);
 

Si vous êtes bloqué par le runtime MS C, vous devez utiliser _scprintf() pour déterminer la longueur de la chaîne résultante:

 char * s = malloc(_scprintf("%s %s", first, second) + 1);
sprintf(s, "%s %s", first, second);
 

Ce qui suit sera probablement la solution la plus rapide:

 size_t len1 = strlen(first);
size_t len2 = strlen(second);

char * s = malloc(len1 + len2 + 2);
memcpy(s, first, len1);
s[len1] = ' ';
memcpy(s + len1 + 1, second, len2 + 1); // includes terminating null
 

23voto

Ned Batchelder Points 128913

Ne vous souciez pas de l'efficacité: rendez votre code lisible et maintenable. Je doute que la différence entre ces méthodes ait de l'importance dans votre programme.

19voto

Andrew Bainbridge Points 1533

Voici quelques folie pour vous, en fait, je suis allé et l'a mesuré. Bloody hell, imaginez que. Je crois que j'ai quelques résultats significatifs.

J'ai utilisé un dual core P4, fonctionnant sous Windows, en utilisant mingw gcc 4.4, la construction avec "gcc toto.c -o foo.exe -std=c99 -Wall-O2".

J'ai testé la méthode 1 et la méthode 2 de l'original post. D'abord gardé le malloc en dehors de l'indice de référence de la boucle. Méthode 1 était de 48 fois plus rapide que la méthode 2. Bizarrement, retrait -O2 à partir de la commande de construction fait l'exe résultant 30% plus vite (n'ont pas cherché à savoir pourquoi encore).

Ensuite, j'ai ajouté un malloc et free à l'intérieur de la boucle. Qui a ralenti la méthode 1 par un facteur de 4.4. Méthode 2 ralentie par un facteur de 1,1.

Donc, malloc + strlen + gratuit NE dominent PAS le profil assez pour faire éviter sprintf la peine.

Voici le code que j'ai utilisé (à part les boucles ont été mis en œuvre avec < au lieu de != mais qui a fait déborder le rendu HTML de ce post):

void a(char *first, char *second, char *both)
{
    for (int i = 0; i != 1000000 * 48; i++)
    {
        strcpy(both, first);
        strcat(both, " ");
        strcat(both, second);
    }
}

void b(char *first, char *second, char *both)
{
    for (int i = 0; i != 1000000 * 1; i++)
        sprintf(both, "%s %s", first, second);
}

int main(void)
{
    char* first= "First";
    char* second = "Second";
    char* both = (char*) malloc((strlen(first) + strlen(second) + 2) * sizeof(char));

    // Takes 3.7 sec with optimisations, 2.7 sec WITHOUT optimisations!
    a(first, second, both);

    // Takes 3.7 sec with or without optimisations
    //b(first, second, both);

    return 0;
}

6voto

size_t lf = strlen(first);
size_t ls = strlen(second);

char *both = (char*) malloc((lf + ls + 2) * sizeof(char));

strcpy(both, first);

both[lf] = ' ';
strcpy(&both[lf+1], second);

2voto

Jay Conrod Points 12375

Ils devraient être à peu près les mêmes. La différence ne va pas avoir d'importance. J'irais avec sprintf car cela nécessite moins de code.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X