Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

struct dynamique contenant un tableau de string dynamique

8 réponses
Avatar
Erwann Thoraval
Bonjour,

Mon programme manipule beaucoup de chaines de caracteres (c`est pour
de la traduction automatique) et comme je ne veux pas m'embeter
tout le temps avec des char**, j'ai voulu creer un type
ensemble_de_phrases avec qq fonctions qui vont bien :

typedef struct
{
char** tab;
unsigned int nbElts;
}ensPhrases;

La structure est declaree comme ca :

ensPhrases *test;

Et je l'initialise comme ceci :

test = initEnsPhrases(test);

ensPhrases* initEnsPhrases(ensPhrases *ens)
{
ens = (ensPhrases*)malloc(sizeof(ensPhrases));
ens->tab = NULL;
ens->nbElts = 0;
return(ens);
}


Maintenant, lorsque je veux faire des insertions de phrases, je dois
allouer de la memoire pour le tableau contenu dans la structure. Mais
je pense qu'il faut egalement allouer de la memoire pour la structure.
En fait, vu que la structure est le contenant, je pense allouer de la
memoire pour la structure, et ensuite utiliser cette memoire pour
le tableau :

ensPhrases* inserEnsPhrases(ensPhrases* ens, char* texte)
{
unsigned int i;
i = ens->nbElts;
realloc(ens, (i + 1)*sizeof(char*));
ens->tab[i] = (char *)malloc(strlen(texte)*sizeof(char));
strcpy(ens->tab[i], texte);
ens->nbElts++;
}

Mais a l'execution, erreur de segmentation...

Je ne vois pas trop ce qu'il faudrait faire.

--
Erwann

8 réponses

Avatar
DINH Viêt Hoà

typedef struct
{
char** tab;
unsigned int nbElts;
}ensPhrases;

ensPhrases* inserEnsPhrases(ensPhrases* ens, char* texte)
{
unsigned int i;
i = ens->nbElts;
realloc(ens, (i + 1)*sizeof(char*));


tu veux sans doute faire :
ens->tab = realloc(ens->tab, (i + 1));

par contre, n'oublie pas vérifier les résultats de retour de malloc()
realloc(), etc

l'exemple que je t'ai donné est très mauvais, il faudrait faire en fait :

new_tab = realloc(ens->tab, i + 1);
if (new_tab == NULL) {
/* fail */
}
ens->tab = new_tab;

sans compter qu'il est plus judicieux de faire un (i * 2) avec
i > SEUIL >= 1 plutôt qu'un (i + 1)
Enfin il y en a qui préfèrent aussi (i * 3 / 2)

ens->tab[i] = (char *)malloc(strlen(texte)*sizeof(char));
strcpy(ens->tab[i], texte);
ens->nbElts++;
}


--
DINH V. Hoa,

"Parait-il que c'est ce que rechechent la majorité des djeunz. Il n'y a plus
aucun attrait pour les métiers scientifiques ni techniques. Ils veulent être
chanteur, acteur ou fonctionnaire. C'est désépérant..." -- Emmanuel Delahaye

Avatar
K. Ahausse
"Erwann Thoraval" <erwann.point.thoraval.at.atr.point.jp> a écrit dans le
message de news:
ensPhrases* inserEnsPhrases(ensPhrases* ens, char* texte)
{
unsigned int i;
i = ens->nbElts;
realloc(ens, (i + 1)*sizeof(char*));


ens->tab = realloc ( ens->tab, (i + 1)*sizeof(char*) ) ;

ens->tab[i] = (char *)malloc(strlen(texte)*sizeof(char));


ens->tab[i] = (char *) malloc( (strlen(texte) +1) *sizeof(char));

strcpy(ens->tab[i], texte);
ens->nbElts++;
}


Avatar
Yves ROMAN

Bonjour,

Mon programme manipule beaucoup de chaines de caracteres (c`est pour
de la traduction automatique) et comme je ne veux pas m'embeter
tout le temps avec des char**, j'ai voulu creer un type
ensemble_de_phrases avec qq fonctions qui vont bien :

typedef struct
{
char** tab;
unsigned int nbElts;
}ensPhrases;

La structure est declaree comme ca :

ensPhrases *test;

Et je l'initialise comme ceci :

test = initEnsPhrases(test);

ensPhrases* initEnsPhrases(ensPhrases *ens)
{
ens = (ensPhrases*)malloc(sizeof(ensPhrases));
ens->tab = NULL;
ens->nbElts = 0;
return(ens);
}


Pourquoi lui passer un parametre qui ne sert pas ?
test = initEnsPhrases();
ensPhrases* initEnsPhrases(void)
{
ensPhrases *ens = malloc(sizeof(*ens));
if ( ens != NULL )
{
ens->tab = NULL;
ens->nbElts = 0;
}
return(ens);
}


Maintenant, lorsque je veux faire des insertions de phrases, je dois
allouer de la memoire pour le tableau contenu dans la structure. Mais
je pense qu'il faut egalement allouer de la memoire pour la structure.
En fait, vu que la structure est le contenant, je pense allouer de la
memoire pour la structure, et ensuite utiliser cette memoire pour
le tableau :

ensPhrases* inserEnsPhrases(ensPhrases* ens, char* texte)
{
unsigned int i;
i = ens->nbElts;
realloc(ens, (i + 1)*sizeof(char*));
- realloc ne modifie pas son 1er parametre il faut utiliser son retour

- c'est ens->tab qu'il faut reallouer pas ens
char ** new_tab ;
new_tab = realloc(ens->tab, i+1) ;
if ( new_tab == NULL )
{
return ens /* dans ce cas un echec n'est pas visible */
}
ens->tab = new_tab ;

ens->tab[i] = (char *)malloc(strlen(texte)*sizeof(char));
strcpy(ens->tab[i], texte);
ens->nbElts++;


Ici il manque 1 caractère pour le '' final
if ((ens->tab[i] = malloc(strlen(texte)+1)) != NULL )
{
strcpy(ens->tab[i], texte);
ens->nbElts++;
}

Je suppose qu'il manque un return ens ;

}



Avatar
Yves ROMAN

char ** new_tab ;
new_tab = realloc(ens->tab, i+1) ;


OOps, mauvaise taille !
new_tab = realloc(ens->tab, (i+1)*sizeof(char*)) ;
ou
new_tab = realloc(ens->tab, (i+1)*sizeof(*new_tab)) ;

Avatar
Marc Boyer
In article , Yves ROMAN wrote:
char ** new_tab ;
new_tab = realloc(ens->tab, i+1) ;
if ( new_tab == NULL )
{
return ens /* dans ce cas un echec n'est pas visible */


sur ce coup, je conseillerais plutot un
return NULL
pour signifier au programme appelant l'echec de l'insertion.

if ((ens->tab[i] = malloc(strlen(texte)+1)) != NULL )
{
strcpy(ens->tab[i], texte);
ens->nbElts++;
}


else return NULL

pour la meme raison

Marc Boyer
--
La contractualisation de la recherche, c'est me donner de l'argent pour
faire ce que je ne sais pas faire, que je fais donc mal, pendant que ce
que je sais faire, je le fais sans moyens...

Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', "Erwann Thoraval"
<erwann.point.thoraval.at.atr.point.jp> wrote:

Mon programme manipule beaucoup de chaines de caracteres (c`est pour
de la traduction automatique) et comme je ne veux pas m'embeter
tout le temps avec des char**, j'ai voulu creer un type
ensemble_de_phrases avec qq fonctions qui vont bien :

typedef struct
{
char** tab;
unsigned int nbElts;
}ensPhrases;


Louable initiative. Le bon type pour une taille d'objet ou indice est size_t.

typedef struct
{
char** tab;
size_t nbElts;
}
ensPhrases;

La structure est declaree comme ca :

ensPhrases *test;


Tu veux dire 'Un pointeur de ce type est défini comme ca'

Et je l'initialise comme ceci :

test = initEnsPhrases(test);


Pour créer l'objet, ça ne sert à rien de passer 'test'.

ensPhrases *test = initEnsPhrases();

ensPhrases* initEnsPhrases(ensPhrases *ens)
{
ens = (ensPhrases*)malloc(sizeof(ensPhrases));
ens->tab = NULL;
ens->nbElts = 0;
return(ens);
}


Comme souvent, beaucoup de complications pour rien, et des choses
essentielles oubliées.

#include <stdlib.h>
...
ensPhrases* initEnsPhrases(void)
{
ensPhrases *ens = malloc(sizeof *ens);
if(ens != NULL)
{
ens->tab = NULL;
ens->nbElts = 0;
}
return ens;
}

Pour les détails :

http://mapage.noos.fr/emdel/notes.htm#malloc

Maintenant, lorsque je veux faire des insertions de phrases, je dois
allouer de la memoire pour le tableau contenu dans la structure. Mais
je pense qu'il faut egalement allouer de la memoire pour la structure.


La mémoire pour la structure est déjà allouée par initEnsPhrases().

En fait, vu que la structure est le contenant, je pense allouer de la
memoire pour la structure, et ensuite utiliser cette memoire pour
le tableau :

ensPhrases* inserEnsPhrases(ensPhrases* ens, char* texte)
{
unsigned int i;
i = ens->nbElts;
realloc(ens, (i + 1)*sizeof(char*));
ens->tab[i] = (char *)malloc(strlen(texte)*sizeof(char));
strcpy(ens->tab[i], texte);
ens->nbElts++;
}

Mais a l'execution, erreur de segmentation...


Normal, tu fais n'importe quoi! Dommage, ça avait bien commencé. En fait,
c'est presque ça.

Je ne vois pas trop ce qu'il faudrait faire.


void inserEnsPhrases (ensPhrases* ens, char const * texte)
{
size_t const i = ens->nbElts;
ensPhrases* p = realloc (ens->tab, (i + 1) * sizeof * ens->tab);

if (p != NULL)
{
ens->tab = p;
ens->tab[i] = malloc(strlen (texte) + 1);
strcpy(ens->tab[i], texte);
ens->nbElts++;
}
}

Details ici:

http://mapage.noos.fr/emdel/notes.htm#realloc

--
-ed- get my email here: http://marreduspam.com/ad672570
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?libÉ9
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', "K. Ahausse"
wrote:

ens->tab = realloc ( ens->tab, (i + 1)*sizeof(char*) ) ;


Pourquoi pas de cast?

ens->tab[i] = (char *) malloc( (strlen(texte) +1) *sizeof(char));


Pourquoi pas un cast?

realloc() peut échouer. Lire la FAQ.
sizeof (char) vait 1 par définition.

--
-ed- get my email here: http://marreduspam.com/ad672570
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?libÉ9
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', Emmanuel Delahaye wrote:

ens->tab[i] = (char *) malloc( (strlen(texte) +1) *sizeof(char));


Pourquoi pas un cast?


Pourquoi un cast?

Zut, mon effet tombe à l'eau. Je me rendors...

--
-ed- get my email here: http://marreduspam.com/ad672570
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?libÉ9
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/