Bonsoir,
Je travaille en ce moment sur un sujet qui traite d'une implémentation assez spéciale des chaînes de caractères en liste chaînée (appelée lstring). Une chaîne structurée en liste est en fait une liste chaînée de tableaux de caractères terminés par '\0'. On alloue les tableaux dynamiquement pour contenir exactement exactement le nombre de caractères nécessaires. On représente une chaîne vide par une liste vide et non par un élément qui contiendrait un tableau représentant la chaîne vide "".
Il est demandé d'implémenter des procédures d'initialisation, affichage, destruction, obtention de la taille, ajout d'une chaîne de caractères classique à la fin d'une lstring, obtention d'un caractère à partir de son indice, recherche d'un motif de caractères....
J'ai pour ma part des soucis avec l'ajout d'une string et l'obtention de la taille d'une lstring.
Ci-dessous mon fichier d'en-tête:
Ma procédure d'initialisation:
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 #ifndef LSTRING__H #define LSTRING__H #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct Cellule{ char *chaine; struct Cellule *suivante; } Cellule; typedef Cellule *lstring; bool initialiser(lstring *lstr, const char src[]); /* Initialiser une lstring à partir d'une chaine ou d'un pointeur NULL */ bool est_vide(lstring lstr); /* Tester si une lstring est vide */ void afficher(lstring lstr); /* Afficher une lstring (avec un retour à la ligne à la fin) */ void detruire(lstring *lstr); /* Detruire une lstring */ size_t taille(lstring lstr); /* Obtenir la taille d'une lstring */ bool ajouter(lstring *lstr, const char src[]); /* Ajouter une chaîne de caractères classique à la fin d'une lstring */ char obtenir(lstring lstr, size_t indice); /* Obtenir un caractère dans une lstring à partir de son indice */ bool motif(lstring lstr, const char s[]); /* Chercher si un motif est présent dans une lstring */ bool supprimer(lstring *lstr, size_t inf, size_t max); /* Supprimer une sous-partie d'une lstring comprise entre deux indices */ #endif
Ma procédure taille:
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 bool initialiser(lstring *lstr, const char src[]){ if (src==NULL || strcmp(src,"")==0){ *lstr=NULL; return true; } else{ (*lstr)=malloc(sizeof(**lstr)); if (*lstr){ (*lstr)->chaine=malloc((strlen(src)+1)*sizeof(char)); if ((*lstr)->chaine){ strcpy((*lstr)->chaine, src); return true; } else{ free(*lstr); (*lstr)=NULL; fprintf(stderr, "Mémoire insuffisante\n"); return false; } }else{ fprintf(stderr, "Mémoire insuffisante\n"); return false; } } }
La procédure qui permet d'obtenir un caractère suivant son indice dans la lstring:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 size_t taille(lstring lstr){ size_t resultat=0; Cellule *curseur=lstr; while (curseur!=NULL){ resultat+= strlen(curseur->chaine); curseur=curseur->suivante; } return resultat; }
Et ma procédure d'ajout qui pose à priori des soucis dans mon code:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 char obtenir(lstring lstr, size_t indice){ /* A optimiser */ //assert(indice<taille(lstr)); Cellule *curseur=lstr; size_t taille_cumule=strlen(curseur->chaine); while (curseur!=NULL && indice>=taille_cumule){ curseur=curseur->suivante; taille_cumule+=strlen(curseur->chaine); } return curseur->chaine[strlen(curseur->chaine)-(taille_cumule-indice)]; }
Pour résumer cette dernière procédure. Si la liste n'est pas vide (autrement on ne fait rien), je déclare un pointeur sur cellule (curseur) qui me permettra de parcourir la liste jusqu'à la dernière cellule, arrivée à celle-ci, j'alloue une nouvelle cellule pointée par "nouvelle" où je copie la chaîne à ajouter. Je relie finalement cette nouvelle cellule à la précédente, pointée par curseur, et je boucle la liste par NULL.
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 bool ajouter(lstring *lstr, const char src[]){ if (src!=NULL || strcmp(src,"")==0) /* Si la liste est vide, on ne fait rien! */ return true; else{ Cellule *curseur=*lstr; while(curseur->suivante!=NULL){ curseur=curseur->suivante; } Cellule *nouvelle=malloc(sizeof(*nouvelle)); if (nouvelle){ nouvelle->chaine=malloc(sizeof(char)*strlen(src)); if (nouvelle->chaine){ strcpy(nouvelle->chaine,src); nouvelle->suivante=NULL; curseur->suivante=nouvelle; return true; }else{ fprintf(stderr,"Mémoire insuffisante\n"); return false; } }else{ fprintf(stderr,"Mémoire insuffisante\n"); return false; } } }
Là où ça marche pas c'est dans mes tests. Je déclare une lstring avec un seul élément "abc", je rajoute une autre chaîne "defg" en utilisant ma procédure ajouter mais la taille renvoyé avec la procédure correspondante est toujours égale à 3 (p-e le problème vient-il de ce SP!).
Egalement, quand j'essaie d'obtenir le caractère d'indice 3 (i.e: 'd') j'ai une segmentation fault.
Au final, le problème peut venir de n'importe où.
Merci d'éclairer ma lanterne.
Cordialement,
Partager