Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

statique contre dynamique

0 views
Skip to first unread message

Sebastien Tricaud

unread,
Feb 3, 2003, 8:13:43 AM2/3/03
to
Bonjour,

je programme un éditeur de partitions musicales et j'ai un petit soucis
avec les structures et je voudrais avoir votre avis.

Ce que je veux faire, c'est repérer les notes posées sur la partition pour
pouvoir
1) les retracer quand la fenêtre subit des modifications (déplacement...)
2) les enregistrer en récupérant toutes les notes posées.

Par note je veut aussi dire objet, sachant que objet c'est pas forcément
une note mais toute note est un objet.

Ainsi, chaque objet (ici en l'occurrence la note : "noire") est ainsi
enregistrée.

Score.Staff[1].Object[3].label = "quarter";
Score.Staff[1].Object[3].up = TRUE;
etc...

Dans ce cas, l'objet 3 de la portée 1 est un noire.
J'ai fixé le nombre de portée maximale à 255, ce qui me semble amplement
suffisant.
Par contre, je voudrais avoir au maximum 65535 Object.

ce qui donnerais la chose suivante dans ma structure:

typedef struct nStaff
{
gboolean is_selected;
gint key_signature;
gint time_signature;
glong extremity_begin_x;
glong extremity_end_x;
glong extremity_begin_y;
gint nb_measures;
glong length;
struct nObject Object[65535];
struct nTime Time;
} nStaff;

Ce qui est vraiment pas bon car j'aurais 255*65535 espaces mémoire pour
les objets de pris pour le programme, alors que si ça se trouve,
l'utilisateur n'utiliseras que 50 objets sur une seule portée.

Je veux donc pouvoir faire en sorte tout ceci en dynamique.

Je sais que si je sort Object de la structure nStaff, je pourrais faire
ainsi:

struct nObject *Object;

Object = malloc(sizeof(nObject)*count);
for (i=0;i<count;i++) faire_qqch_avec_lobjet(Object[i]);
Object=realloc(sizeof(nObject)*new_count); // augmente le tableau de count
à new_count.

ce qu'il se passe c'est que je peux pas faire ceci étant donné que la
structure Object dépend de Staff.

Quelqu'un aurait une idée, un éclaircissement, de la documentation à ce
sujet ?

merci de votre aide.

DINH Viêt Hoà

unread,
Feb 3, 2003, 8:26:50 AM2/3/03
to
> ce qu'il se passe c'est que je peux pas faire ceci étant donné que la
> structure Object dépend de Staff.

en quoi la structure Object dépend-t-elle de Staff ?

--
DINH V. Hoa


AG

unread,
Feb 3, 2003, 9:21:33 AM2/3/03
to
typedef struct nStaff
{
gboolean is_selected;
gint key_signature;
gint time_signature;
glong extremity_begin_x;
glong extremity_end_x;
glong extremity_begin_y;
gint nb_measures;
glong length;
struct nObject *Object;
struct nTime Time;
} nStaff;

nStaff staff;

staff.Object=malloc(sizeof(*staff.Object)*count);

non ?


Sebastien Tricaud wrote:

Message has been deleted

Emmanuel Delahaye

unread,
Feb 3, 2003, 4:00:53 PM2/3/03
to
In 'fr.comp.lang.c', "Sebastien Tricaud" <to...@cell-security.com> wrote:

> je programme un éditeur de partitions musicales et j'ai un petit soucis

Je pense plutôt que tu l'écris...

> avec les structures et je voudrais avoir votre avis.

Je sens venir une question de conception...



> Ce que je veux faire, c'est repérer les notes posées sur la partition pour
> pouvoir
> 1) les retracer quand la fenêtre subit des modifications (déplacement...)
> 2) les enregistrer en récupérant toutes les notes posées.
>
> Par note je veut aussi dire objet, sachant que objet c'est pas forcément
> une note mais toute note est un objet.
>
> Ainsi, chaque objet (ici en l'occurrence la note : "noire") est ainsi
> enregistrée.
>
> Score.Staff[1].Object[3].label = "quarter";
> Score.Staff[1].Object[3].up = TRUE;
> etc...
>
> Dans ce cas, l'objet 3 de la portée 1 est un noire.
> J'ai fixé le nombre de portée maximale à 255, ce qui me semble amplement
> suffisant.

C'est beaucoup.

> Par contre, je voudrais avoir au maximum 65535 Object.

Possible, mais pas portable en C90. La taille minimale garantie d'un objet
étant de 32767 bytes.



> ce qui donnerais la chose suivante dans ma structure:
>
> typedef struct nStaff
> {
> gboolean is_selected;
> gint key_signature;
> gint time_signature;
> glong extremity_begin_x;
> glong extremity_end_x;
> glong extremity_begin_y;
> gint nb_measures;
> glong length;

Qu'est-ce qui empèche d'utiliser les types standards?

> struct nObject Object[65535];

Le tout x 255? C'est risqué! Il est préférable d'implémenter un mécanisme qui
optimise l'utilisation de la mémoire et dont les objets ne dépassent pas les
tailles standard. Un tableau alloué (mettons 256 objets par défaut) peut être
ensuite agrandi avec realloc si le besoin s'en fait sentir. Pareil pour le
tableau des Staff, qui pourrait faire 4 par defaut et d'être augmenté à la
demande.

> struct nTime Time;
> } nStaff;
>
> Ce qui est vraiment pas bon car j'aurais 255*65535 espaces mémoire pour
> les objets de pris pour le programme, alors que si ça se trouve,
> l'utilisateur n'utiliseras que 50 objets sur une seule portée.
>
> Je veux donc pouvoir faire en sorte tout ceci en dynamique.
>
> Je sais que si je sort Object de la structure nStaff, je pourrais faire
> ainsi:
>
> struct nObject *Object;
>
> Object = malloc(sizeof(nObject)*count);
> for (i=0;i<count;i++) faire_qqch_avec_lobjet(Object[i]);
> Object=realloc(sizeof(nObject)*new_count); // augmente le tableau de count
> à new_count.
>
> ce qu'il se passe c'est que je peux pas faire ceci étant donné que la
> structure Object dépend de Staff.

> Quelqu'un aurait une idée, un éclaircissement, de la documentation à ce
> sujet ?

Reprenons calmement..

(Nota : staff = portée, score = partition)

On a un tableau dynamique d'objets

obj_s *p_obj;

dans un staff

typedef struct
{
size_t n_obj;
obj_s *p_obj;
}
staff_s;

Et on a un tableau de staffs:

staff_s *p_staff;

dans une score:

typedef struct
{
size_t n_staff;
staff_s *p_staff;
}
score_s;


Maintenant, on définit une partition vierge :

{
score_s * p_score = score_create (NB_STAFF_DEFAULT, NB_OBJ_DEFAULT);
}

qui fait ça:

score_s * score_init (size_t const n_staff, size_t const n_obj)
{
score_s * p_score = malloc (sizeof *p_score);
if (p_score)
{
staff_s *p_staff = staff_create (n_staff);

/* clear the score */
{
static const score z = {0};
*p_score = z;
}

if (p_staff)
{
p_score->p_staff = p_staff;
p_score->size = n_staff;
}
else
{
score_delete (p_score);
p_score = NULL;
}
}

return p_score;
}

et avec

void score_delete (score_s *const p_score)
{
if (p_score != NULL)
{
if (p_score->p_staff)
{
staff_delete (p_score->p_staff);
p_score->p_staff = NULL;
}
free (p_score);
p_score = NULL;
}
}

etc. Ensuite, il faut faire des fonctions de création/suppression de staff et
d'objets. Si on est trop petit, on agrandit avec realloc() (lire la FAQ). On
maintient les tailles etc. Rien d'extraordinaire. Un bon exercice sur les
ADT (Abstract Data Types).

Je conseille de séparer les implémentations de score, staff et obj, bien
qu'elles soient liées:

score -> staff -> obj

--
-ed- emdel at noos.fr ~]=[o
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/
C-library: http://www.dinkumware.com/manuals/reader.aspx
"Give peace a chance!"

laotseu

unread,
Feb 3, 2003, 10:17:20 PM2/3/03
to
Sebastien Tricaud wrote:
> Bonjour,
>
> je programme un éditeur de partitions musicales et j'ai un petit soucis
> avec les structures et je voudrais avoir votre avis.
>
> Ce que je veux faire, c'est repérer les notes posées sur la partition pour
> pouvoir
> 1) les retracer quand la fenêtre subit des modifications (déplacement...)
> 2) les enregistrer en récupérant toutes les notes posées.
>
> Par note je veut aussi dire objet, sachant que objet c'est pas forcément
> une note mais toute note est un objet.
>
> Ainsi, chaque objet (ici en l'occurrence la note : "noire") est ainsi
> enregistrée.
>
> Score.Staff[1].Object[3].label = "quarter";
> Score.Staff[1].Object[3].up = TRUE;
> etc...
>
> Dans ce cas, l'objet 3 de la portée 1 est un noire.
> J'ai fixé le nombre de portée maximale à 255, ce qui me semble amplement
> suffisant.

<HS>
Ne limite jamais arbitrairement la taille des données si tu n'a pas une
raison *valable* de le faire ("valable" par rapport aux règles de ton
domaine d'application, pas par rapport à ta machine/ton langage/etc)
</HS>

> Par contre, je voudrais avoir au maximum 65535 Object.
>

<HS>
idem
</HS>

> ce qui donnerais la chose suivante dans ma structure:
>
> typedef struct nStaff
> {
> gboolean is_selected;
> gint key_signature;
> gint time_signature;
> glong extremity_begin_x;
> glong extremity_end_x;
> glong extremity_begin_y;
> gint nb_measures;
> glong length;
> struct nObject Object[65535];
> struct nTime Time;
> } nStaff;
>
> Ce qui est vraiment pas bon car j'aurais 255*65535 espaces mémoire pour
> les objets de pris pour le programme, alors que si ça se trouve,
> l'utilisateur n'utiliseras que 50 objets sur une seule portée.
>
> Je veux donc pouvoir faire en sorte tout ceci en dynamique.
>
> Je sais que si je sort Object de la structure nStaff, je pourrais faire
> ainsi:
>
> struct nObject *Object;
>
> Object = malloc(sizeof(nObject)*count);
> for (i=0;i<count;i++) faire_qqch_avec_lobjet(Object[i]);
> Object=realloc(sizeof(nObject)*new_count); // augmente le tableau de count
> à new_count.

Ne jamais réassigner le retour de realloc au pointeur reallouer, realloc
peut echouer (cf la faq et la doc de realloc()).

> ce qu'il se passe c'est que je peux pas faire ceci étant donné que la
> structure Object dépend de Staff.

Elle n'en dépend pas. Elle en fait partie.
Et alors ? ou est le probleme ?

typedef struct nStaff
{
gboolean is_selected;
gint key_signature;
gint time_signature;
glong extremity_begin_x;
glong extremity_end_x;
glong extremity_begin_y;
gint nb_measures;
glong length;

struct nObject *object;
struct nTime Time;
} nStaff;

nStaff staff;
staff.object = malloc(sizeof *(staff.object) * count);
staff.object = malloc(sizeof *(staff.object) * count);

nObject *tmp = realloc(staff.object, sizeof *(staff.object) * new_count);
if (tmp) staff.object = tmp;

> Quelqu'un aurait une idée, un éclaircissement, de la documentation à ce
> sujet ?
>
> merci de votre aide.

Bon, je simplifie ta question et j'enlève les trucs de gtk+, j'essaye
d'y répondre et tu me dis si c'est ça, ok ?-)

Question simplifiée : j'ai un struct foo qui entre autres champs un
tableau de structs bar, et je voudrai modifier ça pour utiliser
l'allocation dynamique pour le tableau de structs bar.

Ok jusque là ?

typedef struct
{
int baaz;
int woop;
} bar;


/* tel que c'est pour l'instant */
typedef struct
{
int booz; /* juste histoire d'avoir autre chose */
bar barz[65535];
} foo;


/* tel que tu le voudrait */
typedef struct
{
int booz;
bar *barz;
size_t nb_bar;
} foo;


foo *foo_create(void)
{
foo *newfoo = malloc(sizeof *newfoo);
if (newfoo != NULL)
{
newfoo->booz = 0; /* soyons propres */
newfoo->nb_bar = 0;
newfoo->barz = NULL;
}
return newfoo;
}

void foo_destroy(foo *f)
{
if (f != NULL)
{
if (f->nb_bar > 0 && f->barz != NULL)
{
free(f->barz);
f->nb_bar = 0;
}
free(f);
}
}

int foo_had_bar(foo *f, bar b)
{
int result = 1;

if (f != NULL)
{
bar *buf = realloc(f->barz, sizeof *(f->barz)*(f->nb_bar + 1));
if (buf != NULL)
{
f->barz = buf;
f->barz[f->nb_bar] = b;
f->nb_bar++;
result = 0;
}
}

return result;
}

Je te laisse écrire la fonction pour supprimer un bar de foo->barz.

NB1 : code non testé, mais sauf typo ou grosse fatigue...
NB2 : tu peux améliorer ça en allouant d'office un certain nombre de
bar, et en faisant tes realloc par blocs (realloc est coûteux). Dans ce
cas, il te faut aussi dans foo un champ gardant trace du nombre de blocs
alloués...
NB3 : une recherche google sur ce ng sur ADT devrait te mener aux posts
d'Emmanuel sur ce sujet.

J'ai bon, jusque là ?


Maintenant, juste une réflexion comme ça :
Si j'ai bien compris, ton tableau d'"objets" sert à stocker les notes
posées sur la portée ? Si oui, une liste chainée serait AMHA plus
appropriée qu'un tableau dynamique : il est courant, quand on écrit une
portée, du supprimer, insérer, déplacer (= supprimer + insérer) des
notes, et la liste chainée se prête bien mieux à ce type de manip que
les tableaux dynamiques.

HTH
Laotseu

Emmanuel Delahaye

unread,
Feb 3, 2003, 4:57:55 PM2/3/03
to
In 'fr.comp.lang.c', laotseu <bde...@removethis.free.fr> wrote:

> Maintenant, juste une réflexion comme ça :
> Si j'ai bien compris, ton tableau d'"objets" sert à stocker les notes
> posées sur la portée ? Si oui, une liste chainée serait AMHA plus
> appropriée qu'un tableau dynamique : il est courant, quand on écrit une
> portée, du supprimer, insérer, déplacer (= supprimer + insérer) des
> notes, et la liste chainée se prête bien mieux à ce type de manip que
> les tableaux dynamiques.

Bien vu!

laotseu

unread,
Feb 4, 2003, 10:19:22 AM2/4/03
to
Emmanuel Delahaye wrote:
> In 'fr.comp.lang.c', laotseu <bde...@removethis.free.fr> wrote:
>
>
>>Maintenant, juste une réflexion comme ça :
>>Si j'ai bien compris, ton tableau d'"objets" sert à stocker les notes
>>posées sur la portée ? Si oui, une liste chainée serait AMHA plus
>>appropriée qu'un tableau dynamique : il est courant, quand on écrit une
>>portée, du supprimer, insérer, déplacer (= supprimer + insérer) des
>>notes, et la liste chainée se prête bien mieux à ce type de manip que
>>les tableaux dynamiques.
>
>
> Bien vu!
>

Merci, cher Maître !-)

Sebastien Tricaud

unread,
Feb 4, 2003, 9:38:12 PM2/4/03
to


eheh, merci pour la réflexion et la suggestion, que je vais m'empresser de
mettre en oeuvre ;)

Sebastien Tricaud

unread,
Feb 4, 2003, 9:39:43 PM2/4/03
to

Chaque Object dépend de la portée en elle même.
Une portée contient un ensemble d'objet qui sont les notes (entre autres).
Il peut y avoir plusieurs portées donc Staff[x].Object=...

Sebastien Tricaud

unread,
Feb 4, 2003, 9:48:14 PM2/4/03
to
On Mon, 03 Feb 2003 21:00:53 +0000, Emmanuel Delahaye wrote:

>> Par contre, je voudrais avoir au maximum 65535 Object.
>
> Possible, mais pas portable en C90. La taille minimale garantie d'un objet
> étant de 32767 bytes.
>
>> ce qui donnerais la chose suivante dans ma structure:
>>
>> typedef struct nStaff
>> {
>> gboolean is_selected;
>> gint key_signature;
>> gint time_signature;
>> glong extremity_begin_x;
>> glong extremity_end_x;
>> glong extremity_begin_y;
>> gint nb_measures;
>> glong length;
>
> Qu'est-ce qui empèche d'utiliser les types standards?

standard par rapport à quoi ?
tu parles des "gint" au lieu de "int" ?
il s'agit d'un programme écrit en gtk+, donc je code avec les types de la
glib.

>
>> struct nObject Object[65535];
>
> Le tout x 255? C'est risqué! Il est préférable d'implémenter un mécanisme qui
> optimise l'utilisation de la mémoire et dont les objets ne dépassent pas les
> tailles standard. Un tableau alloué (mettons 256 objets par défaut) peut être
> ensuite agrandi avec realloc si le besoin s'en fait sentir. Pareil pour le
> tableau des Staff, qui pourrait faire 4 par defaut et d'être augmenté à la
> demande.

Tout à fait.

>
>> struct nTime Time;
>> } nStaff;
>>
>> Ce qui est vraiment pas bon car j'aurais 255*65535 espaces mémoire pour
>> les objets de pris pour le programme, alors que si ça se trouve,
>> l'utilisateur n'utiliseras que 50 objets sur une seule portée.
>>
>> Je veux donc pouvoir faire en sorte tout ceci en dynamique.
>>
>> Je sais que si je sort Object de la structure nStaff, je pourrais faire
>> ainsi:
>>
>> struct nObject *Object;
>>
>> Object = malloc(sizeof(nObject)*count);
>> for (i=0;i<count;i++) faire_qqch_avec_lobjet(Object[i]);
>> Object=realloc(sizeof(nObject)*new_count); // augmente le tableau de count
>> à new_count.
>>
>> ce qu'il se passe c'est que je peux pas faire ceci étant donné que la
>> structure Object dépend de Staff.
>
>> Quelqu'un aurait une idée, un éclaircissement, de la documentation à ce
>> sujet ?
>
> Reprenons calmement..
>
> (Nota : staff = portée, score = partition)

oui, on peut aussi dire stave pour portée.

>
> On a un tableau dynamique d'objets
>
> obj_s *p_obj;
>
> dans un staff
>
> typedef struct
> {
> size_t n_obj;
> obj_s *p_obj;
> }
> staff_s;
>
> Et on a un tableau de staffs:
>
> staff_s *p_staff;
>
> dans une score:
>
> typedef struct
> {
> size_t n_staff;
> staff_s *p_staff;
> }
> score_s;
>
>
> Maintenant, on définit une partition vierge :
>
> {
> score_s * p_score = score_create (NB_STAFF_DEFAULT, NB_OBJ_DEFAULT);
> }

Donc j'ai un nombre prédéfini par défaut.

ok, merci pour toutes ces précisions, même si il est vrai qu'utiliser les
listes chaînées est une meilleure solution car cela me permettra de
supprimer/d'insérer des objets sans jongler avec des horreurs.


0 new messages