Questions pour un malloc sur (char *) et sur (char **)

Résolu/Fermé
Utilisateur anonyme - Modifié par orinym le 19/12/2013 à 07:07
 Utilisateur anonyme - 20 déc. 2013 à 08:39
Bonjour,
Je me posais une question relative aux allocations dynamiques avec les pointeurs sur pointeurs.

Je dois réaliser une fonction prenant en paramètres un
(char const*)
et un
(char)
, et renvoyant un
(char **)
.
voici son prototype :
char **ft_strsplit(char const *s, char c)
le
(char c)
est en fait un élément séparateur que je dois utiliser pour fragmenter le (char const *s) passé en paramètre en une suite de (char *) que contiendra le
(char **)
renvoyé.

Je me posais cependant une question quant aux allocations que je vais devoir effectuer (avec
malloc
).

Si je comprends bien le
(char **)
renvoyé par la fonction contiendra en fait l'ensemble des adresses sur les petits bouts de chaînes extraits du (char const *s).

Je vais donc au début de ma fonction créer un
(char **result)
que je renverrai à la fin.
Seulement, à chaque fois que je vais ajouter l'adresse d'un
(char *)
à
result
, devrai-je lui allouer en plus la taille d'une adresse (d'un pointeur donc) ou la taille du
char *
que j'ajoute
?

De plus je n'ai le droit qu'aux fonctions
malloc
et
free
. Ce qui signifie que je ne peux pas utiliser
realloc
, je devrai donc en faire l'équivalent.
Faire un
free
puis un
malloc
sur un pointeur écrase les données que l'ont avait avec le
malloc
?
Ce qui signifie que je dois faire une copie de ces données pour les réinsérer après avoir agrandi mon
result
?

Merci d'avance pour votre aide.

1 réponse

fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 844
19 déc. 2013 à 07:33
Bonjour,
Pas besoin de realloc(), ni de free() sauf pour la libération des zones mémoires finales.
Je te donne les 3 étapes importantes pour construire ta fonction :
1/ on compte le nombre de séparateur dans la chaîne pour en déduire le nombre de lignes de ton tableau 2d => malloc() sur la première dimension du char**

2/ pour chacune de tes cases, tu comptes le nombre de caractère jusqu'au prochain séparateur pour en déduire la taille de la case du tableau 2d => malloc() sur l'élément courant de ton char **.

3/ Toujours pour chacune de tes cases, tu recopies les caracteres de la chaine dans ton char ** => strncpy() pour spécifier le nombre de caractères à recopier.

Noublie pas une fonction de liberation des zones allouees par malloc().
Et attention pour les malloc(), il ne faut pas oublier le caractère final \0.

Voila tu as assez delements pour créer ta fonction de split().

Cdlt,
0
Bonjour,

Tout d'abord merci pour ta réponse.
Cependant ce n'est pas un algorithme pour ma fonction que je cherche, je trouverai tout seul sans problème, mais une réponse à cette question que je reformule ici :

La mémoire allouée à mon
char **result;
devra-t-elle être égale à la mémoire prise par les pointeurs (juste les adresses) ou à ce que je pointe avec ces pointeurs?

par exemple si mon result contient :
char *s1="truc";
char *s2="bidule";

on aura
result[1] = s1;
et
result[2] = s2;

seulement voilà :
La taille de result sera-t-elle égale à la taille de deux adresses (s1 + s2), ou à la taille de la chaîne commençant à s1 plus la taille de la chaîne commençant à s2?

J'ai juste besoin de cette info :) Si fais comme on me dit de faire je réaliserai peut-être la fonction sans avoir besoin d'apprendre d'avantage, mais je cherche justement à en apprendre d'avantage en me confrontant à ce problème, pas en le contournant. ;)

Mais merci!
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 844
19 déc. 2013 à 08:45
je trouverai tout seul sans problème,
Ok, mais vu que tu me semblais partir dans la mauvaise direction au vu de tes explications, j'ai préféré rectifier le tir...

On aura result[1] = s1; et result[2] = s2;
Non. Il faut plutôt recopier les données.

La taille de result sera-t-elle égale à la taille de deux adresses (s1 + s2), ou à la taille de la chaîne commençant à s1 plus la taille de la chaîne commençant à s2?
Ben j'y réponds dans mon post... Partie 1, je dis que c'est en fonction du nombre de séparateurs. Entre les séparateurs se sont des chaînes, donc, la taille de result doit être égale au nombre de chaînes (ici 2) multiplié par la taille d'un pointeur (sizeof char*).
0
"Ben j'y réponds dans mon post... Partie 1"
J'avais mal compris.
" la taille de result doit être égale au nombre de chaînes (ici 2) multiplié par la taille d'un pointeur (sizeof char*)."

C'est tout ce que je cherchais à savoir pour cette question-ci. Merci :)

Je peux faire comme tu dis mais je compterais alors plutôt le nombre de sous-chaînes :
Il peut y avoir plusieurs séparateurs accolés et il peut aussi y en avoir (ou non) en début et en fin de chaîne.

Par contre je ne pense pas que ma méthode soit mauvaise, plus compliquée à la rigueur.
Mais j'ai des contraintes au niveau des fonctions permises, et au niveau du volume de lignes de code.

De toute façon j'avais besoin d'éclaircir ce point. :) Grand merci.

Et sinon, le fait de free(), puis de refaire un malloc() sur un pointeur conserve-t-il les données?
à priori je dirais "pas forcément" puisque le malloc n'allouera pas forcément le même emplacement en mémoire, je me trompe?
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 844
19 déc. 2013 à 09:49
Il peut y avoir plusieurs séparateurs accolés et il peut aussi y en avoir (ou non) en début et en fin de chaîne.
Ben, s'il y a plusieurs séparateurs accolés, il faut les compter et créer des chaînes vides. Le nombre de sous-chaînes est donc lié au nombre de séparateurs.

Par contre je ne pense pas que ma méthode soit mauvaise, plus compliquée à la rigueur.
Si tu parles de result[1] = s1; et result[2] = s2; , ce n'est pas plus compliqué, au contraire. Mais c'est surtout impossible. Il ne faut pas oublier de ce que j'ai compris à ton énoncé que ta chaîne vaudra ch="coucou|ceci|est|un|test". Donc si tu fais result|0]=ch; tu récupéreras toute la chaîne (le séparateur n'est pas un '\0'). Et puis dès lors que ch sera modifié, result sera modifié...

Et sinon, le fait de free(), puis de refaire un malloc() sur un pointeur conserve-t-il les données?
Oui, les données sont conservées dans le heap. Mais malloc() ne pointera pas forcément vers le début de la zone.
puisque le malloc n'allouera pas forcément le même emplacement en mémoire
C'est, exactement ça. Mais pour ton exercice, tu n'as pas besoin de faire de malloc() après ton free().
0
Utilisateur anonyme
19 déc. 2013 à 14:36
je ne dois pas créer de chaîne vide

J'ai tout de même finalement choisit de partir sur ce genre de méthode, c'est plus simple au final. J'ai fait comme ceci pour calculer la taille du (char **) :
15static char     **ft_gentab(char const *s, char c)
16{
17 char **result;
18 int count1;
19 int count2;
20
21 count1 = 0;
22 count2 = 0;
23 while (s[count1] != '0')
24 {
25 if (s[count1] != c && s[count1] != '\0'
26 && (s[count1 + 1] == c || s[count1 + 1] == '\0'))
27 {
28 count2 = count2 + 1;
29 }
30 count1 = count1 + 1;
31 }
32 return ((char **) malloc(sizeof(char *) * (count2 + 1)));
33}

Je pense pouvoir me débrouiller pour la suite, merci :)
0