Bonjour,

Je suis en train de me prendre la tête sur ce code ci-dessous.
Voici le principe (bon, je sais il y a toujours moyen de faire mieux, ...) je voudrais créer des listes chainées contenant vraiment n'importe quoi en C (un peu comme les templates en orienté objet).

A priori cela fonctionne mais j'ai un soucis avec le fait qu'en C il n'est pas possible de "reconnaitre" le type de la variable, sizeof() ne nous renseigne que sur la taille qu'il occupe en mémoire.
C'est pour cela que j'ai ajouté le champs dataType dans la structure, pour pouvoir savoir ce que je manipule.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
enum{cssmbyte,cssmint,cssmlong,cssmfloat,cssmdouble,cssmldouble};
 
typedef struct item_Datas
{
	int				item_Number;
	int				dataSize;
	int				dataType;
	void				*value;
	struct item_Datas	*pPrevious;
	struct item_Datas	*pNext;
}Datas;
 
typedef struct 
{
	int		NbElem;
	Datas	*pHead;
}ListeChainee;

Ne vous préoccupez pas des champs pPrevious pour le moment il ne sert pas à grand chose...

J'ai une fonction qui sert à insérer à la tête de liste

Code : Sélectionner tout - Visualiser dans une fenêtre à part
int lc_insert(void*,ListeChainee*,short,short);
Le principe est le suivant, le passe une variable convertie en void* à la fonction, le pointeur sur la liste chainée, le type de la variable et la taille.
La taille seule ne suffit pas, car un int et un float peuvent se confondre (chez moi la taille pour les deux types est 4 bytes).
Pareil pour un double et un long, chez moi c'est 8 bytes.

Et le soucis en C, à moins que j'aie raté un épisode, c'est que printf() a besoin de formater les données à afficher en fonction de la taille du type en question (il ne fera pas le même traitement pour un int ou un float).

Pour tester mon programme voici les autres lignes de codes:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
Datas* lc_get(ListeChainee*,int);
 
void lc_showList(ListeChainee*);
 
int		CodeDeRetour;
int		element;
 
int		Insertion1=256;
long 	Insertion2=74004L;
float	Insertion3=5.325;
double	Insertion5=5455E-2;
char	Insertion4='d';
lc_get() permet d'extraire un élément de la liste.
lc_showList() permet d'afficher des informations sur le contenu de la liste.

Dans la fonction main, j'essaie d'insérer les éléments et puis j'essaie de relire les informations extraites des éléments de la liste et de les afficher.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 
void main(void)
{
  ListeChainee *pListeChainee=malloc(sizeof(ListeChainee));
  if(pListeChainee==NULL)
	printf("Erreur d'allocation de mémoire...\n");
 
  CodeDeRetour=lc_insert((void*)&Insertion1,pListeChainee,cssmint,sizeof(int));
  CodeDeRetour=lc_insert((void*)&Insertion3,pListeChainee,cssmfloat,sizeof(float));
 
  CodeDeRetour=lc_insert((void*)&Insertion5,pListeChainee,cssmdouble,sizeof(double));
  CodeDeRetour=lc_insert((void*)&Insertion2,pListeChainee,cssmlong,sizeof(long));
 
  CodeDeRetour=lc_insert((void*)&Insertion4,pListeChainee,cssmbyte,sizeof(char));
 
  lc_showList(pListeChainee);
 
  // tentative d'affichage...
 
  Datas *lc_parcours=(Datas*)malloc(sizeof(Datas));
  element=0;
  while(element<pListeChainee->NbElem)
  {
	  lc_parcours=lc_get(pListeChainee,element);
	  if(lc_parcours==NULL) printf("Elément non trouvé...\n");
	  else
	  {
		void	*vtmp=(void*)malloc(lc_parcours->dataSize);
		vtmp=lc_parcours->value;
		int		tmpInt;
		long	tmpLong;
		double	tmpDouble;
		float	tmpFloat;
		char	tmpChar;
		switch(lc_parcours->dataType)
		{
			case cssmint: 
				  memcpy((void*)&tmpInt,vtmp,sizeof(lc_parcours->dataSize));
				  printf("Valeur de l'élément %d --> %d\n",element,tmpInt);
				  break;
			case cssmlong:
				  memcpy((void*)&tmpLong,vtmp,sizeof(lc_parcours->dataSize));
				  printf("Valeur de l'élément %d --> %ld\n",element,tmpLong);
				  break;
			case cssmdouble:
				  memcpy((void*)&tmpDouble,vtmp,sizeof(lc_parcours->dataSize));
				  printf("Valeur de l'élément %d --> %lf\n",element,tmpDouble);
				  break;
			case cssmbyte:
				  memcpy((void*)&tmpChar,vtmp,sizeof(lc_parcours->dataSize));
				  printf("Valeur de l'élément %d --> %c\n",element,tmpChar);
				  break;
			case cssmfloat:
				  memcpy((void*)&tmpFloat,vtmp,sizeof(lc_parcours->dataSize));
				  printf("Valeur de l'élément %d --> %f\n",element,tmpFloat);
				  break;
 
		}
	  }
	  element++;
  }
}
...ça ne marche pas avec la variable de type double...

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
 
Datas* lc_get(ListeChainee *pListe,int position)
{
  Datas *lc_parcours=pListe->pHead;
  while(lc_parcours!=NULL)
  {
	if(lc_parcours->item_Number==position) return lc_parcours;
	lc_parcours=lc_parcours->pNext;
  }
  return (Datas*)NULL;
}
 
int lc_insert(void *pData,ListeChainee *pListe,short type,short taille)
{
  // l'insert se fera toujours en tête...
  if(pListe->pHead!=NULL)
  {
	// Il y a un élément dans la liste
	Datas *lc_new=(Datas*)malloc(sizeof(Datas));
	pListe->pHead->pPrevious=lc_new;
 
	lc_new->pPrevious=NULL;
	lc_new->pNext=pListe->pHead;
	lc_new->dataSize=taille;
	lc_new->dataType=type;
	lc_new->value=(void*)malloc(taille);
	lc_new->item_Number=pListe->NbElem;
	memcpy((void*)lc_new->value,pData,taille);
	pListe->NbElem++;
	pListe->pHead=lc_new;
  }
  else
  {
	// La liste est vide
	Datas	*lc_new=(Datas*)malloc(sizeof(Datas));
	lc_new->pPrevious=NULL;
	lc_new->pNext=NULL;
	lc_new->dataSize=taille;
	lc_new->dataType=type;
	lc_new->value=(void*)malloc(taille);
	memcpy((void*)lc_new->value,pData,taille);
	lc_new->item_Number=pListe->NbElem;
	pListe->NbElem++;
	pListe->pHead=lc_new;
  }
}
 
void lc_showList(ListeChainee *pListe)
{
  Datas *lc_parcours=pListe->pHead;
 
  while(lc_parcours!=NULL)
  {
	printf("Adresse de l'élément : %08x\n",lc_parcours);
	printf("Adresse de l'élément précédent: %08x\n",lc_parcours->pPrevious);
	printf("Adresse de l'élément suivant: %08x\n",lc_parcours->pNext);
	printf("Taille de l'élément : %d\n",lc_parcours->dataSize);
	lc_parcours=lc_parcours->pNext;
  }
}
...je suis content, il est possible de créer une liste qui peut contenir "n'importe quoi", mais le soucis c'est que sur un type standard, en l'occurrence le type "double", ça ne marche pas...

Et je voudrais avoir une explication. Comme je ne manipule pas souvent des double, float etc... peut-être ais-je manqué quelque chose dans mon approche.
Nom : listechainee.png
Affichages : 2945
Taille : 12,4 Ko