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

(newbye) exemple de tableaux variables de chaine de charactères

10 réponses
Avatar
unbewust
j'ai regarder sur le net quelques exemples de tableaux de chaines,
manque de pot il y a des erreurs...

donc je cherche un moyen pour cr=E9er un tableau de dimension variable
de chaines de caract=E8res elles-m=EAmes de dimensions variables...


en cr=E9ant, par exemple une stucture pour ce faire.

quelqu'un aurait des pistes ???

10 réponses

Avatar
AG
#include "stdlib.h"
#include "stdio.h"

char ** create_table(size_t tab_size, size_t chaine_size)
{
size_t i,j;
char ** tab=malloc(tab_size*sizeof*tab);
if(tab==NULL)
{
printf("Malloc failedn");
exit(EXIT_FAILURE);
}
for(i=0;i<tab_size;i++)
{
tab[i]=malloc(chaine_size*sizeof*tab[i]);
if(tab[i]==NULL)
{
printf("Malloc failedn");
/* libérer l'espace mémoire déjà allouée jusqu'ici */
for(j=i-1;j>=0;j--) free(tab[j]);
free(tab);
exit(EXIT_FAILURE);
}
}
return tab;
}

par exemple, mais ton cahier des charges n'est pas trés précis non plus,
alors...

AG.
Avatar
Charlie Gordon
"AG" a écrit dans le message de news:
f8v5af$ist$
#include "stdlib.h"
#include "stdio.h"


pas glop : il faut utiliser les <> pour les headers standard.
#include <stdio.h>
#include <stdlib.h>


char ** create_table(size_t tab_size, size_t chaine_size)


attention les size_t sont piegeux.

{
size_t i,j;


mauvaise idee : il vaut mieux utiliser des int ou des ssize_t, comme nous
l'allons voir ci-dessous.

char ** tab=malloc(tab_size*sizeof*tab);


pas tres lisible : tab_size * sizeof(*tab) bien que plus verbeux est plus
clair.

if(tab==NULL)
{
printf("Malloc failedn");
exit(EXIT_FAILURE);


pourquoi printf et exit ? return NULL est plus classique pour une fonction
utilitaire.

}
for(i=0;i<tab_size;i++)
{
tab[i]=malloc(chaine_size*sizeof*tab[i]);
if(tab[i]==NULL)
{
printf("Malloc failedn");
/* libérer l'espace mémoire déjà allouée jusqu'ici */


Bof : si on va faire exit, a quoi bon ?

for(j=i-1;j>=0;j--) free(tab[j]);


BOUM ! si i vaut 0, j vaut MAX_UINT qui est >= 0 et crash tres probable a
un moment de cette boucle fort longue.
l'alternative for (j = i; j-- > 0;) ... n'est pas tres elegante, mais evite
cet ecueil.

free(tab);
exit(EXIT_FAILURE);
}
}
return tab;


Incomplet : les tableaux de caracteres alloues ne sont pas initialises, il
aurait suffit de les allouer par calloc(chaine_size, sizeof(char))
On peut d'ailleurs argumenter que sizeof(char) vaut 1 par definition, et
qu'il serait preferable d'allouer chaine_size+1 parce qu'ils serviront
vraisemblablement a stocker des chaines de caracteres C qui occupent 1 char
de plus pour le '' final.

}

par exemple, mais ton cahier des charges n'est pas trés précis non plus,
alors...


D'ailleurs cela ressemble fort a un devoir d'informatique que le posteur
aurait du faire lui-meme.

Chqrlie.

Avatar
Pierre Maurette

[...]

D'ailleurs cela ressemble fort a un devoir d'informatique que le posteur
aurait du faire lui-meme.


Des devoirs de vacances, alors ;-)

--
Pierre Maurette

Avatar
Pascal Bourguignon
unbewust writes:

j'ai regarder sur le net quelques exemples de tableaux de chaines,
manque de pot il y a des erreurs...

donc je cherche un moyen pour créer un tableau de dimension variable
de chaines de caractères elles-mêmes de dimensions variables...


en créant, par exemple une stucture pour ce faire.

quelqu'un aurait des pistes ???


Oui, en créant une structure pour ce faire.

Comme il est probable que tu auras besoinde chaines de dimension
variable indépendament du tableau de chaines, je conseillerais
d'implémenter deux types abstraits:

- chaines de dimension variable.
- tableaux de dimensions variables (1, 2 ou plus?).

Voir par exemple:
http://darcs.informatimago.com/public/common/bclib/interfaces/BcString.h
http://darcs.informatimago.com/public/common/bclib/interfaces/BcList.h

(et implémentations dans le répèrtoire sources dans
http://darcs.informatimago.com/public/common/bclib/ )

mais il y a beaucoup d'autres bibliothèques implémentant ces types
abstraits.


--
__Pascal Bourguignon__ http://www.informatimago.com/
I need a new toy.
Tail of black dog keeps good time.
Pounce! Good dog! Good dog!

Avatar
unbewust
On 3 août, 15:37, Pascal Bourguignon wrote:


Oui, en créant une structure pour ce faire.

Comme il est probable que tu auras besoinde chaines de dimension
variable indépendament du tableau de chaines, je conseillerais
d'implémenter deux types abstraits:

- chaines de dimension variable.
- tableaux de dimensions variables (1, 2 ou plus?).


simplement 1 c'est pour représenter des path unix...

Voir par exemple:http://darcs.informatimago.com/public/common/bclib/inter faces/BcString.hhttp://darcs.informatimago.com/public/common/bclib/interfac es/BcList.h

(et implémentations dans le répèrtoire sources danshttp://darcs.inf ormatimago.com/public/common/bclib/)



au quai, merci beaucoup, je vai pouvoir m'arranger avec ça ;-)

Yvon

Avatar
AG
pas glop : il faut utiliser les <> pour les headers standard.
ouais, je m'étais mis ça comme règle un jour. Sauf qu'en pratique, ça m'a

jamais posé problème. du coup j'ai fini par oublié pourquoi je le faisais.
Alors maintenant, de temps en temps, ça m'échappe.

attention les size_t sont piegeux.
certes, moi qui croyais bien faire alors que j'avais mis des int... :-)


pas tres lisible : tab_size * sizeof(*tab) bien que plus verbeux est plus
clair.
ouais... quand j'ai commencé le C, à chaque post que je faisais ou

j'écrivais sizeof(*tab), il y un mec qui, systématiquement (un peu comme toi
?) me faisait une réponse pour me dire que c'était inutile. Il s'appelait ED
si je me souviens bien...bon allé, je te taquine.

pourquoi printf et exit ? return NULL est plus classique pour une fonction
oui, moi dans l'utilisation que je fais de mes programmes (je ne fais pas de

temps réel), j'aime bien le printf qui me dit tout de suite ou ça plante (en
générale j'ajoute un __FILE__ et __LINE__)

Bof : si on va faire exit, a quoi bon ?
Ben c'est plus propre non ? Si je ne l'avais pas fait un autre m'aurait dit

: t'as pas libéré la mémoire, c'est pas glop !

BOUM ! si i vaut 0, j vaut MAX_UINT qui est >= 0 et crash tres probable a
Quand j'ai lu le boum, j'ai sursauté et je suis devenu tout rouge. On voit

l'oeil de l'expert aguérrit par de nombre revues de codes !

Incomplet : les tableaux de caracteres alloues ne sont pas initialises, il
aurait suffit de les allouer par calloc(chaine_size, sizeof(char))
blablabla...
Certes, mais pour un devoir de vacances gratos... et heureusement que j'ai

pas utilisé de strncat et touti quanti ;-)

Donc je retiens quoi ? Pas de size_t dans les indices de boucles ?

AG.

Avatar
Charlie Gordon
"AG" a écrit dans le message de news:
f8vkb0$n3f$
attention les size_t sont piegeux.
certes, moi qui croyais bien faire alors que j'avais mis des int... :-)


pas tres lisible : tab_size * sizeof(*tab) bien que plus verbeux est plus
clair.
ouais... quand j'ai commencé le C, à chaque post que je faisais ou

j'écrivais sizeof(*tab), il y un mec qui, systématiquement (un peu comme
toi ?) me faisait une réponse pour me dire que c'était inutile. Il
s'appelait ED si je me souviens bien...bon allé, je te taquine.
Emmanuel doit etre en vacances lui aussi, mais j'insiste sur la lisibilite.


pourquoi printf et exit ? return NULL est plus classique pour une
fonction
oui, moi dans l'utilisation que je fais de mes programmes (je ne fais pas

de temps réel), j'aime bien le printf qui me dit tout de suite ou ça
plante (en générale j'ajoute un __FILE__ et __LINE__)
alors mets un assert ?


Bof : si on va faire exit, a quoi bon ?
Ben c'est plus propre non ? Si je ne l'avais pas fait un autre m'aurait

dit : t'as pas libéré la mémoire, c'est pas glop !
pour retourner NULL en effet il faut liberer les trucs deja alloues qui vont

se perdre.
pour faire un exit brutal, il y a tellement d'autres trucs qui ne seront pas
faits (FILE * non flushed pas exemple) que cette boucle de liberation est
bien vaine.

BOUM ! si i vaut 0, j vaut MAX_UINT qui est >= 0 et crash tres probable
a
Quand j'ai lu le boum, j'ai sursauté et je suis devenu tout rouge. On voit

l'oeil de l'expert aguérrit par de nombre revues de codes !
Eh oui !


Incomplet : les tableaux de caracteres alloues ne sont pas initialises,
il aurait suffit de les allouer par calloc(chaine_size, sizeof(char))
blablabla...
Certes, mais pour un devoir de vacances gratos... et heureusement que j'ai

pas utilisé de strncat et touti quanti ;-)
strncpy et encore pire ;-)


Donc je retiens quoi ? Pas de size_t dans les indices de boucles ?


Personnellement, et depuis que size_t fait 64 bits en linux/amd64, j'utilise
ssize_t qui est la version signee de size_t, autrement dit un entier signe
de meme taille que size_t, mais je trouve cela bien vain de trainer partout
des tailles en 64 bits alors que les objets dont la taille ne tient pas en
32 bits sont peu courants et que le C a de toutes facons d'autres
incoherences en ce qui concerne les tailles d'objets : printf("%.*s",
sizeof(buf), buf) ne passe pas en 64 bits, il faut passer un int pour les
parametres de format width et precision. ssize_t n'est pas standard mais
peu facilement se definir en quelques ifdef bien sentis (hint: tester la
valeur de SIZE_MAX, pas sizeof(size_t) qui n'est pas connu du
preprocesseur).

Bonnes vacances!

Chqrlie.


Avatar
espie
In article <f8vkb0$n3f$, AG wrote:
Donc je retiens quoi ? Pas de size_t dans les indices de boucles ?


Tu peux mettre des size_t dans les indices de boucle, faut juste
eviter de les parcourir dans l'autre sens, vu que le <0 ne marchera
jamais...

Sinon, faudrait des specs precises. Toutes les chaines de meme taille ?
Des chaines a allouer/redimensionner separement, ou une fois pour toutes ?

Parce que, par exemple, si tu connais la taille de tes chaines et qu'elles
bougent pas, c'est presque toujours plus efficace d'allouer une grosse
zone memoire, et de mettre des pointeurs aux bons endroits.

Lorsqu'elles bougent, c'est qu'elles viennent d'ailleurs. C'est tout aussi
simple d'avoir un tableau de pointeurs nuls, et d'allouer les chaines lorsqu'on
en a besoin (et ca simplifie aussi la liberation, puisque free(0) fonctionne).

Pour le reste, sur les erreurs d'allocation memoire, le printf/free/exit
est une super mauvaise approche.

- soit on se place dans une optique `bibliotheque' et on renvoie un NULL
en cas de probleme.
- soit on se protege direct du cas ou malloc() peut echouer, en partant
de l'idee que, de toutes facons, le programme est deja a moitie mort,
et on ecrit un wrapper autour de malloc (appele souvent xmalloc ou emalloc)
qui fait gentiement son fprintf(stderr, "...") et son exit...

Avatar
Makkhdyn
On 2007-08-03 15:15:09 +0200, "Charlie Gordon" said:
for(j=i-1;j>=0;j--) free(tab[j]);


BOUM ! si i vaut 0, j vaut MAX_UINT qui est >= 0 et crash tres probable a
un moment de cette boucle fort longue.
l'alternative for (j = i; j-- > 0;) ... n'est pas tres elegante, mais evite
cet ecueil.


Pourquoi pas un while(i-- > 0) ? Ou plutot pourquoi avoir déclaré un j ?


Avatar
Antoine Leca
En news:46b32a68$0$8055$, Charlie Gordon écrivit:
"AG" a écrit dans le message de news:
char ** tab=malloc(tab_size*sizeof*tab);


pas tres lisible : tab_size * sizeof(*tab) bien que plus verbeux est
plus clair.


Tant qu'à faire, je préfère tab_size * sizeof(tab[0]),
ou même tab_size * sizeof tab[0] pour les fainéants de la touche majuscules
(ailleurs qu'en France, les parenthèses nécessitent d'appuyer sur la touche
de majuscule, un peu comme pour les chiffres en France.)


Antoine