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

question à propos de struct

8 réponses
Avatar
pere.noel
j'ai une struct qui n'est qu'une variante de "Les listes doublement
chaînées en C" trouvée sur developpez :
<http://nicolasj.developpez.com/articles/listedouble/>
Date de publication : 20 Juillet 2005

Par Nicolas Joseph

bon, ça marche très bien, la struct est :

dans *.h :
typedef struct dllp dllp_s;

dans *.c :
struct dllp
{
struct dllp *prev;
struct dllp *next;
void *data;
};

donc elle fait référence à elle-même.

bien sur il y a des fonctions insert, remove, delete etc...


j'aurais souhaité ajouter un attribut à cette structure, ce n'est pas
vraiment possible car la structure est auto-référentielle.

l'attribut devrait-être un bool "valid" qui dit si la structure et
valide ou non. Dans mon cas, dès qu'un élément n'est pas valide alors la
structure ne l'est pas.

au départ je suppose la structure valide et dès qu'un élément ne l'est
pas (suite à une insertion) je souhaite stoper toute manip sur cette
structure et propager l'"info structure invalide" sur tous les éléments
de la liste.

cette liste n'est pas indicée, il y a un élément NULL avant le premier
élément et un élément NULL après le dernier élément.

appellons "elt" un élément qqc de cette structure, je voudrais pouvoir
faire en sorte que :

if (!elt->valid) {
dllp_s elt_p = elt->next;
dllp_s elt_n = elt->next;
if (elt_p != NULL)
elt_p->valid = false;
if (elt_n != NULL)
elt_n->valid = false;
}


est-ce possible sans avoir à balayer tous les éléments de la liste ?
ie. que ça soit "récursif" ?

ou, autre solution, plus élégante, avoir un attribut "valid" pour toute
la liste, qui vaut true par défaut et qu'un membre qqc de la liste peut
mettre à false ???

c'est dans ce cas où je ne vois pas très bien comment changer cette
struc...
--
une bévue

8 réponses

Avatar
Stéphane Goujet
Une bévue wrote:
typedef struct dllp dllp_s;
struct dllp
{
struct dllp *prev;
struct dllp *next;
void *data;
};
if (!elt->valid) {
dllp_s elt_p = elt->next;
dllp_s elt_n = elt->next;
if (elt_p != NULL)
elt_p->valid = false;
if (elt_n != NULL)
elt_n->valid = false;
}
est-ce possible sans avoir à balayer tous les éléments de la liste ?
ie. que ça soit "récursif" ?


Comme ça ?

dllp_s elt_it;
if (!elt->valid) {
elt_it=elt;
while(elt_it=elt_it->prev) {
elt_it->validúlse;
}
elt_it=elt;
while(elt_it=elt_it->next) {
elt_it->validúlse;
}
}

A+,
Stéphane.

Avatar
pere.noel
Stéphane Goujet wrote:

dllp_s elt_it;
if (!elt->valid) {
elt_it=elt;
while(elt_it=elt_it->prev) {
elt_it->validúlse;
}
elt_it=elt;
while(elt_it=elt_it->next) {
elt_it->validúlse;
}
}


oui, d'accord, j'avais vu cette solution.
donc si elt_it a un "elt_it->prev" == NULL pas besoin de tester ???
(l'identité à NULL)

donc pas moyen d'avoir un attribut global à cette structure (sorte de
singleton?) ?
--
une bévue

Avatar
Stéphane Goujet
Une bévue wrote:

Stéphane Goujet wrote:
dllp_s elt_it;
if (!elt->valid) {
elt_it=elt;
while(elt_it=elt_it->prev) {
elt_it->validúlse;
}
elt_it=elt;
while(elt_it=elt_it->next) {
elt_it->validúlse;
}
}
oui, d'accord, j'avais vu cette solution.

donc si elt_it a un "elt_it->prev" == NULL pas besoin de tester ???
(l'identité à NULL)


C'est testé dans le while.

Si tu fais :
if(elt_it=elt_it->prev)
c'est pareil que :
elt_it=elt_it->prev;
if(elt_it)
donc pareil que
elt_it=elt_it->prev;
if(elt_it!=NULL)

ici le while est équivalent à :
while((elt_it=elt_it->prev)!=NULL)

donc pas moyen d'avoir un attribut global à cette structure (sorte de
singleton?) ?


Je ne vois pas, non, chaque variable structure comportant tous les
éléments de la structure. Je pense qu'il te faut recourir à une variable
extérieure à ta structure.

A+,
Stéphane.


Avatar
Eric Levenez
Le 11/09/06 19:55, dans <qqhNg.281$, « Stéphane
Goujet » a écrit :

C'est testé dans le while.

Si tu fais :
if(elt_it=elt_it->prev)


if ((elt_it = elt_it->prev))

Les doubles parenthèses, c'est pour éviter les warnings de certains
compilateurs qui pensent que le programmeur a voulu mettre un "==".

c'est pareil que :
elt_it=elt_it->prev;
if(elt_it)


elt_it = elt_it->prev;
if (elt_it)

Avec des blancs là où il faut, c'est plus lisible.

donc pareil que
elt_it=elt_it->prev;
if(elt_it!=NULL)


elt_it = elt_it->prev;
if (elt_it != NULL)

Avec des blancs là où il faut, c'est plus lisible.

ici le while est équivalent à :
while((elt_it=elt_it->prev)!=NULL)


while ((elt_it = elt_it->prev) != NULL)

Avec des blancs là où il faut, c'est plus lisible.

Mais dans ce cas, le mieux est encore :

while ((elt_it = elt_it->prev))

Je ne vois pas, non, chaque variable structure comportant tous les
éléments de la structure. Je pense qu'il te faut recourir à une variable
extérieure à ta structure.


Toutes les structures peuvent ne pas avoir la même structure. Normalement on
utilise une union avec plusieurs structures qui commencent par la même chose
(pointeur "next"...). Chaque structure peut être différente mais on peut
aussi avoir juste la première différente.

--
Éric Lévénez -- <http://www.levenez.com/>
Unix is not only an OS, it's a way of life.

Avatar
pere.noel
Stéphane Goujet wrote:

C'est testé dans le while.

Si tu fais :
if(elt_it=elt_it->prev)
c'est pareil que :
elt_it=elt_it->prev;
if(elt_it)
donc pareil que
elt_it=elt_it->prev;
if(elt_it!=NULL)

ici le while est équivalent à :
while((elt_it=elt_it->prev)!=NULL)


OK, merci, pigé ;-)


donc pas moyen d'avoir un attribut global à cette structure (sorte de
singleton?) ?


Je ne vois pas, non, chaque variable structure comportant tous les
éléments de la structure. Je pense qu'il te faut recourir à une variable
extérieure à ta structure.


ben j'ai essayé avec une variable externe ça roule mais ne me satisfait
pas parce qu'il ne faut oublier de la resettée quand on crée une
nouvelle structure, ce n'est pas "idiot proof" donc.

je prendaris donc ta solution; ma solution actuelle et proche de la
tienne exceptés deux points :

- je n'avais pas vu que le test à NULL était inutile ))
- ensuite je le fait après coup, quand toute la liste est entrée, ta
solution me permet de le faire dès qu'un élément n'est pas valide :
inutile de faire bosser le cpu pour rien, les CPUs ne sont pas des
esclaves tout de même )))
--
une bévue


Avatar
Stéphane Goujet
Eric Levenez wrote:

Avec des blancs là où il faut, c'est plus lisible.
Avec des blancs là où il faut, c'est plus lisible.
Avec des blancs là où il faut, c'est plus lisible.


Raciste !

A+,
Stéphane.

Avatar
Stéphane Goujet
Eric Levenez wrote:

if(elt_it=elt_it->prev)
if ((elt_it = elt_it->prev))

Les doubles parenthèses, c'est pour éviter les warnings de certains
compilateurs qui pensent que le programmeur a voulu mettre un "==".


C'est vrai, je les mets parfois pour éviter ces warnings, mais je
trouve ça lourdingue et moins lisible. En fait, il faudrait que je
consacre 5 minutes à chercher l'option permettant de désactiver ce
warning. Un jour...

A+,
Stéphane.


Avatar
pere.noel
Eric Levenez wrote:

if ((elt_it = elt_it->prev))

Les doubles parenthèses, c'est pour éviter les warnings de certains
compilateurs qui pensent que le programmeur a voulu mettre un "==".


Très juste, je ne l'avait pas remarqué )))

Finalement plus j'apprend de C, plus je comprends certaines
particularité de Ruby ; héritées du C donc...

<snip/>

Avec des blancs là où il faut, c'est plus lisible.


c'est ce que je fais aussi, d'ailleurs même en ce qui concerne le
parenthésage, gcc envoie des warnings sur, par ex :`

if (machin == bidule && bidule == chose) {...}

un warning dit qu'il vaudrait mieux écrire :

if ((machin == bidule) && (bidule == chose)) {...}

<snip/>

Je ne vois pas, non, chaque variable structure comportant tous les
éléments de la structure. Je pense qu'il te faut recourir à une variable
extérieure à ta structure.


Toutes les structures peuvent ne pas avoir la même structure. Normalement on
utilise une union avec plusieurs structures qui commencent par la même chose
(pointeur "next"...). Chaque structure peut être différente mais on peut
aussi avoir juste la première différente.


OK, je dois regarder ça de + près, dans mon cas, ce serait pas mal
d'avoir une struct avec un premier élément "first" (supportant par ex
l'attribut valid) et un dernier élément "last", le dernier élément
pouvant avoir d'autres propriétés ques les autres éléments, y compris le
premier.


--
une bévue