Bonjour à tous.

Je n'ai pas fait de C depuis quelques années et pour des raisons scolaires je dois m'y remettre .

On me demande dans un exercice de trier un tas de mot selon l'ordre lexicographique.
La résolution de l'exercice ne me pose pas de soucis en lui même, c'est assez bateau.

Mais c'est plus sur le point de vue de la propreté du code que j'ai des doutes ainsi que sur les fuites de mémoire et de possible accès hors bornes dans les tableaux (putain de C quoi ....) . Valgrind m'affiche divers choses, mais je ne sais jamais à quoi me fier dans ses rapports car de ce que je m'en rappelle, il lui arrivait de rater le coche sur certains codes.

Bref, voici le code (un peu long, pas très dur, compile bien avec -Wall et -pedantic)

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
 
#define CAPACITY 25
typedef char** tab2Dchar;
typedef char* string;
/*====================================*/
 
void clean_stdin(void)
{
    int c;
 
    do {
        c = getchar();
    } while (c != '\n' && c != EOF);
}
 
void doubler_taille(string* t,int* n)
{
 
  string tmp = realloc (*t,
               2*(*n) * sizeof(*tmp));
      if (tmp != NULL)
      {
         *t = tmp;
     *n=2*(*n);
      }
      else
      {
         /* l'ancien bloc est valide, mais il n'a pas ete agrandi */
      }
}
 
/*Vise a recupérer un mot caractère par caractère et à le  renvoyer dans une chaine
(qui sera au final plus grande que le mot)
*/
 
string recup_mot()
{
 
      string tmp=malloc(CAPACITY*sizeof(*tmp));
      char c=getchar();
      int size=CAPACITY;
      int j=0;
 
      while(c!='\n')
      {
        tmp[j]=c;
    j++;
    c=getchar();
 
    /*Si on arrive au bout de tmp à la taille actuelle
      sans être a la fin de l'input, on agrandit tmp*/
    if(j==size-1)
    {
      doubler_taille(&tmp,&size);      
    }
 
      }
      /*Car on veut remplacer  \n par \0 dans tmp*/
      tmp[j]='\0';
      return tmp;
}
 
void lecture(tab2Dchar* mots,int n)
{
 
  int i=0;
  string tmp=NULL;
 
  /*pre affectation pour les n mots à trier*/
  *mots=malloc(n*sizeof(char*));
 
  for(;i<n;++i)
  {
 
      tmp=recup_mot();
      /*A ce stade, tmp contient le i-eme mot mais est trop long*/      
      (*mots)[i]=malloc(strlen(tmp)*sizeof(*tmp));
      strcpy((*mots)[i],tmp);
      free(tmp);
  }
}
 
void liberer(tab2Dchar* mots,int n)
{
    int i=0;
    for (; i < n; ++i)
    {
    free((*mots)[i]);
    }
    free(*mots);
}
/*========================================================
permet d'échanger 2 mots a et b en faisant les allocations/desallocations necessaires
*/
void swap_mots(string* a,string* b)
{
    int sizea=strlen(*a);
    int sizeb=strlen(*b);
 
    string tmp=malloc(sizea*sizeof(*a));
    strcpy(tmp,*a);
 
    free(*a);
    *a=malloc(sizeb*sizeof(*b));
    strcpy(*a,*b);
 
    free(*b);
    *b=malloc(sizea*sizeof(*a));
    strcpy(*b,tmp);
 
    free(tmp);
}
 
/*
 
Trouve l'index ou se situe la valeur minimale de tab (tableau de taille n) de tab+a à tab[n-1]
*/
int min_tab(const tab2Dchar tab,int a,int n)
{
  int index=a;
  int i=a+1;
  for (; i < n; ++i)
    {
    if(strcmp(tab[i],tab[index])<0)
    {
      index=i;
    }
    }
      return index;
}
 
/*
tri par insertion classique
*/
void tri_insertion(tab2Dchar tab,int n)
{
  int i=0;
  int index=0;
  for (; i < n; ++i)
    {
      index=min_tab(tab,i,n);
      swap_mots(&tab[index],&tab[i]);
    }
}
 
void afficher(const tab2Dchar mots, int n)
{
    int i=0;
    for (i = 0; i < n; ++i)
    {
    printf("%s|",mots[i]);
    }
    printf("\n");
}
/*=====================================*/
 int main(int argc, char *argv[])
 {
   int n=0;
   tab2Dchar mots=NULL;
 
   printf("Nombre de mots à trier : "); scanf("%d",&n);
   clean_stdin(); /*scanf et fget ne font pas bon ménage, besoin de purger stdin*/
 
   lecture(&mots,n);
 
   afficher(mots,n);
   tri_insertion(mots,n);
   afficher(mots,n);
 
   liberer(&mots,n);
 
  return 0;
}
SI vous pouviez me dire ce que vous en pensez. Merci.

PS/ Je sais que scanf même pour des entiers c'est moyen mais là je vais au plus direct, c'est pas le but de l'exo ....

Edit / il manquait des const dans le code