Trier un tableau de chaine de caractère en C avec des pointeurs

Je suis un débutant en langage C, et j’essayais de trier un tableau de chaînes de caractères sans utiliser la méthode qsort. Voici le code :

#include <stdio.h>
#include <string.h>
void sort(char *tab[],int n)
{
    int i,j;
    char tmp[10]; 
    for (i=0;i<n-1;i++)
    {
        for (j=0;j<n-i-1;j++)
        {
            if ((strcmp (*(tab+j),*(tab+j+1)))>0)
            {
                strcpy (tmp, *(tab+j));
                strcpy (*(tab+j), *(tab+j+1));
                strcpy (*(tab+j+1), tmp);
                printf ("%s\n", tmp);
            }
        }
    }
}
int main()
{
    int i,n;
    char* tab[]={"emily","bob","alex"};
    n = sizeof(tab)/sizeof(*tab);
    printf ("Avant le tri: \n");
    for (i=0;i<n;i++)
    printf ("%s\n", *(tab+i));
    sort (tab,n);
    printf ("Après le tri: \n");
    for (i=0;i<n;i++)
    printf ("%s\n", *(tab+i));
    return 0;
}

Pourtant, il affiche seulement les chaînes de caractères avant le tri.

Qu’est-ce qui ne va pas ?

Vous avez un comportement non défini dans votre fonction de tri.

Il y a deux raisons à cela :

  1. Vous utilisez un tableau de pointeurs, et chaque pointeur pointe sur une chaîne littérale ;
  2. Vous utilisez strcpy pour copier le contenu entre les chaînes.

En C, tenter de modifier une chaîne littérale est un comportement non défini. Les chaînes littérales sont essentiellement en lecture seule. Notez qu’elles ne sont pas constantes, même s’il est toujours recommandé d’utiliser des pointeurs const.

Vous avez deux possibilités pour résoudre ce problème :

  1. Utiliser plutôt un tableau de tableaux :
char tab[][10] = { ... };

Le contenu des chaînes est alors modifiable, et vous pouvez utiliser strcpy.

  1. Vous pouvez également permutez les pointeurs :
char *tmp = tab[j];
tab[j] = tab[j + 1];
tab[j + 1] = tmp;

Le problème est que vous utilisez strcpy() avec des chaînes de caractères littérales, ce qui n’est pas autorisé. Si vous permutez les pointeurs, votre algorithme fonctionne parfaitement. Voici une version mise à jour de sort() :

void sort(char *ar[],int n)
{
    int i,j;
    char* tmp; 
    for (i=0;i<n-1;i++)
    {
        for (j=0;j<n-i-1;j++)
        {
            if (strcmp (tab[j], tab[j + 1] ) > 0)  // plus lisible qu'avant
            {
                tmp = tab[j];
                tab[j] = tab[j+1];
                tab[j+1] = tmp;
                printf ("%s\n", tmp);
            }
        }
    }
}

Merci, ça marche nickel :clap: