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
| /** Teste le retour de realloc et quitte le programme si besoin */
void * xrealloc(void * prec, size_t len)
{
void *ret = realloc(prec, len);
if(!ret) /* Equivaut à if(ret == NULL) */
exit(0);
return ret;
}
/** Copie n caractère de str dans une nouvelle chaine alloué dynamiquement, et renvoie cette chaine */
char * mstrndup(const char *str, size_t n)
{
char *ret = malloc((n+1) * sizeof(char));
if (!ret)
exit(0);
strncpy(ret, str, n); /* Copie n caractère de str dans n */
ret[n] = 0; /* 0 == '\0' */
return ret;
}
/** Compte le nombre de mot dans str (un mot correspond à une suite de lettre et s'arrête dès qu'un caractère autre est rencontré */
size_t count_word(const char *str)
{
size_t n = 0;
int a;
while (*str) /* Equivaut à while(*str != '\0') */
{
a = 0; /* Cette variable sert à indiquer si au moins une lettre a été trouvé (pour éviter les lignes vides) */
while (!isspace((unsigned char) *str) && *str) str++, a = 1;
if (a) n++;
while (isspace((unsigned char) *str) && *str) str++;
}
return n;
}
/** copie les mots de la chaine str dans le tableau de chaine de caractère tab */
void get_word(char **tab, const char *str)
{
const char* p = str;
int a, i = 0;
/* Le fonctionnement est le même que pour la fonction count_word mais ici on enregistre la chaien dans un tableau. On pourrait le faire en une seule
fonction mais il faudrai à chaque fois réallouer de la mémoire et ce n'est pas très propre */
while (*str)
{
a = 0;
while (!isspace((unsigned char) *p) && *p) p++, a = 1;
if (a)
tab[i++] = mstrndup(str, p-str); /* Si on a trouvé un mot, on met dans tab[i] le mot (la suite de lettre trouvé) et on incrémente i.
p-str correspond à la taille du mot, c'est l'adresse du caractère suivant le dernier caractère moins l'adresse du premier caractère */
while (isspace((unsigned char) *p) && *p) p++;
str = p;
}
}
/** Compare deux tableaux de mots, renvoie 1 si ces tableaux sont identiques sans tenir compte de l'ordre ni du nombre de mot, 0 sinon (En fait, il renvoie 1
si chaque ligne de t1 existe dans t2) */
int compareline(char **t1, size_t size1, char **t2, size_t size2)
{
int ret = 1;
size_t i, j;
int a;
/* Pour chaque ligne de t1, on compare avec chaque ligne de t2. Si à un moment on ne trouve pas la ligne, alors les tableaux ne sont pas identiques */
for (i = 0; i < size1; i++)
{
a = 0;
for (j = 0; j < size2; j++)
if (!strcmp(t1[i], t2[j]))
{
a = 1;
break; /* Dès que la ligne est trouvé, on peux arrêter de comparer pour cette valeur du tableau */
}
if (!a)
{
ret = 0;
break; /* Dès qu'une ligne manque, on peux arrêter la comparaison */
}
}
return ret;
}
/** Compare deux chaines de caractère, si comparesize vaut 1 alors la première doit contenir la seconde, et renvoie 1 si elles sont identiques sans tenir
compte de l'ordre des mots */
int is_same(const char *s1, const char *s2, int comparesize)
{
char **t1, **t2;
size_t size1 = count_word(s1), size2 = count_word(s2);
int ret = 0;
if (!comparesize || (size1 > size2)) /* Si comparesize vaut 0, on ne compare pas la taille, si comparesize vaut 1 alors il faut que size1 > size 2 */
{
t1 = malloc(size1 * sizeof(char*));
t2 = malloc(size2 * sizeof(char*));
if (t1 && t2)
{
get_word(t1, s1);
get_word(t2, s2);
ret = comparesize? compareline(t2, size2, t1, size1) : compareline(t1, size1, t2, size2);
free_tab(t1, size1), free_tab(t2, size2);
}
else
exit(0);
}
return ret;
} |
Partager