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
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.
Code : Sélectionner tout - Visualiser dans une fenêtre à part int lc_insert(void*,ListeChainee*,short,short);
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:
lc_get() permet d'extraire un élément de la liste.
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_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.
...ç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
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++; } }
...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...
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; } }
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.
Partager