Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1300 connectés 

  FORUM HardWare.fr
  Programmation

  [C] Implantation d'objets dans 1 liste

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[C] Implantation d'objets dans 1 liste

n°35420
Pschitt
Posté le 29-05-2001 à 23:18:32  profilanswer
 

J'aimerais pouvoir implanter n'importe quels types d'objets dans une même liste dont la définition est celle-ci :
 
typedef struct cel{
OBJ obj;
struct cel * lien_prec;  
struct cel * lien_svt;
} cell;
 
typedef struct {
cell * tete;
cell * queue;
} LISTE;  
 
Actuellement je ne peux q'utiliser le type OBJ.
Pour corser le tout l'objet devra être en dur dans la cellule, cell, donc pas de pointeur sur objets du genre void * obj.
 
Si une âme charitable serait m'aiguiller  
 
Merci

mood
Publicité
Posté le 29-05-2001 à 23:18:32  profilanswer
 

n°35436
BifaceMcLe​OD
The HighGlandeur
Posté le 30-05-2001 à 00:59:03  profilanswer
 

Ta question n'est pas très claire : est-ce que tu veux implémenter un type liste à la fois générique et typé ?
C'est-à-dire qu'à priori, on peut utiliser ton type liste pour n'importe quel type d'objet, mais une fois le type d'objet choisi, seul ce type-là n'est utilisable ?
 
Si seule la généricité totale (tout type d'objet) t'intéresse, pas le choix, il te faut définir OBJ comme étant void*. Enfin je veux dire, c'est de très loin ce qu'il y a de plus simple.
 
Par contre, si tu veux pouvoir profiter à la fois de la généricité au niveau source et du typage fort, il va falloir jouer serré avec le préprocesseur.
 
Je te propose ce qui suit (de mémoire, parce que j'ai fait ce genre de choses il y a longtemps) :

Code :
  1. #define _paste3(a,b,c)   a##b##c
  2. #define _paste4(a,b,c,d) a##b##c##d
  3. #define  paste3(a,b,c)   _paste3(a,b,c)
  4. #define  paste4(a,b,c,d) _paste4(a,b,c,d)
  5. #define LIST_TYPE(infotype)  paste3(List,_,infotype)
  6. #define _CELL_TYPE(infotype) paste4(_,Cell,_,infotype)
  7. #define CELL_TYPE(infotype)  paste3(Cell,_,infotype)
  8. #define DECLARE_LIST_TYPE(infotype) \
  9.       typedef struct _CELL_TYPE(infotype) { \
  10.          infotype obj; \
  11.          struct _CELL_TYPE(infotype)* lien_prec; \
  12.          struct _CELL_TYPE(infotype)* lien_svt; \
  13.       } STRUCT_TYPE(infotype); \
  14.          \
  15.       typedef struct { \
  16.          CELL_TYPE(infotype)* tete; \
  17.          CELL_TYPE(infotype)* queue; \
  18.       } LIST_TYPE(infotype)


 
Ensuite, tu n'as plus qu'à écrire :

Code :
  1. DECLARE_LIST_TYPE(OBJ);


pour définir un type liste sur OBJ., et

Code :
  1. LIST_TYPE(OBJ)


pour l'utiliser.
 
Ainsi, En supposant que tu as une fonction comme suit:

Code :
  1. void add(LIST_TYPE(infotype) list, infotype info);


 
si tu écris:

Code :
  1. DECLARE_LIST_TYPE(int);
  2.     DECLARE_LIST_TYPE(char*);
  3.     typedef LIST_TYPE(int) List_int;
  4.     typedef LIST_TYPE(char*) List_String;
  5.     List_int     list_n;
  6.     List_String  list_s;
  7.     add(list_n, 2);
  8.     add(list_s, "toto" );
  9.     add(list_s, 2);
  10.     add(list_n, "toto" );


 
Les 2 premiers appels à add() seront OK, par contre, le compilateur C t'interdira les 2 appels suivants.

 

[edit]--Message édité par BifaceMcLeOD--[/edit]

n°35438
gilou
Modérateur
Modzilla
Posté le 30-05-2001 à 02:44:12  profilanswer
 

Il a tout dit le Face de Bi (:D):
Soit tu as une liste non typee avec des void*
Soit tu imites ce que faisaient les convertisseurs C++->C du debut avec plein de macros indigestes.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°35464
minusplus
Posté le 30-05-2001 à 09:42:52  profilanswer
 

wooh putain ! cette usine à gaz ! :ouch:
 
:lol:  
 
(moi je passerais en C++ ! :lol: )

n°35500
altac
Posté le 30-05-2001 à 10:49:13  profilanswer
 

c'est vrai qu'en c++ et avec la STL c'est juste un peu plus simple ...
y'a une bonne raison de faire ca en C ?

n°35841
Pschitt
Posté le 30-05-2001 à 23:56:05  profilanswer
 

BifaceMcLeOD,
 
C'est vrai ma question n'est pas trés claire, c'est en fait l'objet obj que je ne souhaiterais pas typé. J'aimerais pouvoir simuler ceci :
 
typedef struct cel{  
void obj;  
struct cel * lien_prec;  
struct cel * lien_svt;  
} cell;  
 
typedef struct {  
cell * tete;  
cell * queue;  
} LISTE;
 
La raison pour laquelle je ne souhaite pas utiliser de void * pour obj est d'éviter que l'utilisateur de mes primitives ne vire un obj sans avoir fait le nécessaire dans la cellule, cell , contenant le pointeur sur cet obj.
 
Peux tu m'expliquer en quelques mots tes 4 premières déclarations #define _paste3(a,b,c) a##b##c ....  
 
Merci à toi

n°35844
BifaceMcLe​OD
The HighGlandeur
Posté le 31-05-2001 à 00:09:26  profilanswer
 

Dans ce cas, tu n'as pas le choix, il faut que tu définisses OBJ comme un void*, ou que ton champ "obj" soit en fait un pointeur sur ton type OBJ (ce qui revient au même du point de vue conceptuel, mais rajoute un niveau de pointeur dans la pratique).
 
Pour ta dernière question, " ## " est un opérateur du préprocesseur qui colle les 2 chaînes de caractères qui sont autour. Ainsi, si tu écris "List##_##OBJ", le compilateur recevra "List_OBJ". Et si tu écris (en utilisant mes macros) "CELL_TYPE(MonType)", le préprocesseur transformera cela en "paste3(Cell,_,MonType)", donc en "Cell##_##MonType", par conséquent en "Cell_MonType". Et le compilateur recevra cette dernière chaîne de caractères uniquement (qui comme par hasard ;) est un identificateur de type valide...).

n°35848
Pschitt
Posté le 31-05-2001 à 00:25:38  profilanswer
 

Bon dommage, j'vais m'orienter vers du void * obj qui offre tout de même l'avantage d'utiliser cet obj dans d'autres structures (Arbres, piles, ...).
 
Merci de ton aide  
 
@+

n°35855
mystereetb​ouledegomm​e
Posté le 31-05-2001 à 01:17:44  profilanswer
 

ET les templates en C++ c'est pas mieux ?

n°35864
verdy_p
Posté le 31-05-2001 à 03:27:19  profilanswer
 

Pschitt a écrit a écrit :

J'aimerais pouvoir implanter n'importe quels types d'objets dans une même liste dont la définition est celle-ci :
 
typedef struct cel{
OBJ obj;
struct cel * lien_prec;  
struct cel * lien_svt;
} cell;
 
typedef struct {
cell * tete;
cell * queue;
} LISTE;  
 
Actuellement je ne peux q'utiliser le type OBJ.
Pour corser le tout l'objet devra être en dur dans la cellule, cell, donc pas de pointeur sur objets du genre void * obj.
 
Si une âme charitable serait m'aiguiller  
 
Merci




 
Redefinit cell ainsi:
 
typedef struct cell{
struct cell * lien_prec;  
struct cell * lien_svt;
int celltype;
} cell;
 
Cell ne contient pas l'objet, mais on peut simuler une clsse dérivée C++ en C, en incluant la structure cell comme premier membre de la nouvelle structure:
 
typedef struct cell_OBJ1{
  cell c;
  OBJ1 o;
} cell_OBJ1;
 
typedef struct cell_OBJ2{
  cell c;
  OBJ2 o;
} cell_OBJ2;
 
Puis définit des fonctions constructeurs de chaque type de cellule, qui appeleront les constructeurs de la structure parente "cell" avant d'initialiser les champs de l'objet inclus:
 
function cell *new_cell(celltype, size){
  cell *pc = calloc(size, 1);
  pc->c.celltype = celltype;
}
function cell_OBJ1 * new_cellOBJ1(){
  cell_OBJ1 *pc = (cell_OBJ1 *)new_cell(1, sizeof(cell_OBJ1));
  pc->o.xxx = ...
}
function cell_OBJ2 * new_cellOBJ2(){
  cell_OBJ1 *pc = (cell_OBJ2 *)new_cell(2, sizeof(cell_OBJ2));
  pc->o.yyy = ...
}
 
Quand tu parcoures la liste ces cellules, tu dois utiliser un pointeur de type (cell *pc), et tu peux utiliser le membre
pc->celltype pour savoir quel type de cellule tu as, avant de le transtyper dans le bon type de cellule et d'accéder aux champs spécifiques.
 
Si tu as des champs communs ou si le nombre de types d'objets est restreint, tu peux aussi utiliser une union contenant les différents types d'objets, et tout mettre dans la structure cell au lieu de créer une structure de cellule par type d'objet.

 

[edit]--Message édité par verdy_p--[/edit]

mood
Publicité
Posté le 31-05-2001 à 03:27:19  profilanswer
 

n°36288
Pschitt
Posté le 01-06-2001 à 00:17:46  profilanswer
 

verdy_p,  
 
Je suis en train de bosser sur ta méthode, ça se présente pas mal sauf que j'ai encore du mal au niveau des castings pour lier les cellules entre elles, VC++ m'indique pas mal d'erreurs & warnings. Je n'arrive également pas à faire pointer, tete, sur la 1ère cellule de la liste.
 
Voici mon code :
 
Objets :
 
typedef struct cell{
struct cell * lien_prec;  
struct cell * lien_svt;
int celltype;
} cell;
 
typedef struct {
char nom[25];
} OBJ1;
 
typedef struct {
char nom[25];
} OBJ2;
 
typedef struct cell_OBJ1{
  cell c;
  OBJ1 obj;
} cell_OBJ1;
 
typedef struct cell_OBJ2{
  cell c;
  OBJ2 obj;
} cell_OBJ2;
 
typedef struct LISTE{
void * tete;
void * queue;
} LISTE;
 
Fonctions :
 
LISTE * CreerListe()
{
LISTE * l;
if((l = NEW(LISTE)) == NULL) return (l);
else
  l->tete = NULL;
  l->queue = NULL;
return (l);
}
 
cell * new_cell(int celltype, int size)
{cell * pc = calloc(1,size);
 if(pc==NULL)
 
  return (cell*)NULL;
 
 pc->celltype=celltype;
 return pc;
}
 
cell_OBJ1 * new_cellOBJ1()
{ return (cell_OBJ1*)new_cell(1,sizeof(cell_OBJ1));}
 
cell_OBJ2 * new_cellOBJ2()
{ return (cell_OBJ2*)new_cell(1,sizeof(cell_OBJ2));}    
 
Main :
 
void main()
{
 LISTE * l=NULL;
 cell_OBJ1 * tmp1=NULL;
 cell_OBJ2 * tmp2=NULL;
 
 l=CreerListe();
 tmp1=new_cellOBJ1();  
 tmp2=new_cellOBJ2();
 
 memcpy(tmp1->obj.nom,"Lulu",25*sizeof(char));
 memcpy(tmp2->obj.nom,"Toto",25*sizeof(char));
 
 printf("%s\n",tmp1->obj.nom);
 printf("%s\n",tmp2->obj.nom);
 
 tmp1->c.lien_prec=NULL;
 tmp1->c.celltype=1;
 (cell_OBJ2)tmp1->c.lien_svt=tmp2; /* VC++ n'arrive pas à caster */
 tmp2->c.lien_svt=NULL;
 
 (cell_OBJ1 *)l->tete=tmp1; /* ça passe mais après je n'accède pas à l->tete->obj.nom */
 
 getchar();
}

n°36306
morcandel
Posté le 01-06-2001 à 08:15:35  profilanswer
 

Pschitt a écrit a écrit :

verdy_p,  
 
// snip
 
 (cell_OBJ2)tmp1->c.lien_svt=tmp2; /* VC++ n'arrive pas à caster */
 tmp2->c.lien_svt=NULL;
 
 (cell_OBJ1 *)l->tete=tmp1; /* ça passe mais après je n'accède pas à l->tete->obj.nom */
}




 
Hello, essaie de bien parenthéser ton cast... peut-être que ça ira mieux (?)
 
Sinon, une question toute bête (je suis nouveau et j'arrive en pleine cogitation ;-) ), quel intérêt d'avoir les objets dans les cellules et pas avoir un bête void * à l'extérieur ?
 
Pour l'exercice de style, voilà une solution toute bête mais pas très belle (quoique...)
 
le type cellule (simplement chaîné, sinon ça fait mal à la tête ;-)
 
typedef struct _cellule
{
  struct _cellule *svt;
  int type;
} Cellule, *ListeCh;
 
pour l'ajout, on passe le numéro du type, un pointeur sur l'objet, et la taille en octet du type... on ajoute simplement l'objet à la suite de la cellule.
 
#define CHAMPVAL(x) (&x->type+1)
 
int ajout_tete(ListeCh *l, int type, void *el, int size)
{
  Cellule *c;
 
  if ( !(c=(Cellule*)malloc(sizeof(Cellule)+size)) )
    return 0;
 
  c->type = type;
  c->svt = *l;
  memcpy(CHAMPVAL(c), el, size);
 
  *l = c;
 
  return 1;
}
 
bref, après ça, inutile de vous faire un dessin, un fois que l'on a un Cellule *, on utilise CHAMPVAL pour avoir un pointeur (de type int *, il faut donc caster) sur le champ valeur, et roule ma poule.
 
l'insertion n'est pas très jolie, mais on s'y fait, par exemple :
 
  int a;
  ListeCh maliste=NULL;
 
  a=1515;
  ajout_tete(&maliste, TYPE_INT, &a, sizeof(int));
  ajout_tete(&maliste, TYPE_STRING, "tralala", 8);
 
après, tu peux t'écrire tes macros qui vont bien pour chacun de tes types préférés...
 
#define AJOUT_INT(l,x)   ajout_tete(&l, TYPE_INT, &x, sizeof(int))
#define AJOUT_STRING(l,x) ajout_tete(&,l, TYPE_STRING, x, strlen(x)+1)
 
a=10;
AJOUT_INT(maliste, a);
AJOUT_STRING(maliste, "tralala" );

n°36307
altac
Posté le 01-06-2001 à 08:47:14  profilanswer
 

list<string> maliste1;
maliste1.push_front("abc" );
maliste1.push_back("def" );
 
list<int> maliste2;
maliste2.push_front(2);
maliste2.push_back(3);
 
.... c pas mal la STL non ;) ?

n°36662
BifaceMcLe​OD
The HighGlandeur
Posté le 02-06-2001 à 00:10:04  profilanswer
 

Ben oui, mais quand on est obligé de se cantoner au C, c'est un dur d'utilisation, la STL...  :sarcastic:  ;)

n°36668
Pschitt
Posté le 02-06-2001 à 01:36:58  profilanswer
 

OK, c'est trés clair, le C++ permet de faire ça + simplement mais le C++ je ne connais pas encore. Pour moi, l'heure est à l'apprentissage de l'algorithmique et de la programmation. Voila 8 mois(Cours du soir au CNAM et surtout travail perso) que j'ai attaqué et je commence à me faire plaisir. On a beaucoup bosser sur le C et je trouve ça trés bien, pour démarrer, se familiariser à algorithmique, pointeurs, structures, ... Et puis c'est un language qui à quand même fait parler de lui et qui est encore largement utilisé il me semble (portabilité, rapidité, ...). Cela dit le C++ m'intéresse et je vais pas tarder à voir de + près.
 
Au fait c'est OK pour mes soucis de pointeurs :
 
(cell_OBJ2)tmp1->c.lien_svt=tmp2; /* VC++ n'arrive pas à caster */  
tmp2->c.lien_svt=NULL;  
   
(cell_OBJ1 *)l->tete=tmp1; /* ça passe mais je n'accède pas à l->tete->obj.nom */  
 
Comme ça c'est mieux :
 
((cell_OBJ2 *)tmp1->c.lien_svt)=tmp2;
((cell_OBJ1 *)l->tete)=tmp1;
 
Reste + qu'a mettre tous ça dans des fonctions les + générique possibles avec de void *, des #define partout et tout baigne
 
Je bataille, je bataille mais c'est comme ça que je gagne
 
Merci à vous tous pour votre aide  
 
Tchao


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation

  [C] Implantation d'objets dans 1 liste

 

Sujets relatifs
Java : lire/écrire dans un fichier des objets directement : possible ?[ASP] & liste...
[html] Envoi du résultat d'un formulaire sans le Submit ..??? (liste)[Access-VB] Conversion d'objets......
liste déroulante + saisieComment récupérer le choix ds une liste déroulante en PHP sans psser p
[HTML] Changer un cadre en fonction d'une listeComment changer l'épaisseur du traît de plusieurs objets en même temps
Utilisation d'objets sous VC++acces a des objets en flash
Plus de sujets relatifs à : [C] Implantation d'objets dans 1 liste


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR