begin process at 2010 03 20 13:31:44
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Divers

 > [C] COMPARAISON GÉNÉRIQUE (OU COMMENT COMPARER DES ELEMENTS DU TYPE VOID * ...)

[C] COMPARAISON GÉNÉRIQUE (OU COMMENT COMPARER DES ELEMENTS DU TYPE VOID * ...)


 Information sur la source

 Description

Bon, je sais que c'est pas très clair, mais c'est un peu compliqué à expliquer seulement à l'aide du titre.
Alors voilà mon problème. J'avais codé une liste en C dont les élements à l'interieur était du type void*. Ainsi, la liste pouvait contenir des pointeurs sur n'importe quoi. En clair, la liste pouvait donc contenir n'importe quoi. Mais le soucis, c'est que je devais créer une fonction sort() associée à cette liste pour pouvoir comparer les élements à l'interieur ... Sauf que ces élements sont concidérés dans la liste comme des pointeurs du type void* ... Et donc impossible d'en faire quoi que ce soit.
La solution, c'est d'utiliser un pointeur de fonction sur une fonction de comparaison dont les paramètres sont du type void*, qui retourne un booléen (ou quoi que ce soit qui peut aider à comparer). Ce pointeur est alors utilisé comme paramètre de la fonction sort() dont je vous parlais précedement.
On doit ensuite donner la fonction adaptée aux élements présents dans la liste.
Dans l'exemple que je vous donne, c'est pas une liste, mais une simple fonction qui détermine si ces 2 premiers paramètres sont egaux, à l'aide du 3ème paramètre qui est en fait le pointeur sur la fonction de comparaison.

Source

  • #include <stdio.h>
  • #include <stdlib.h>
  • typedef enum{TRUE = 1, FALSE = 0} tBoolean;
  • #define and &&
  • #define tElement void *
  • typedef struct sComparator *tComparator;
  • struct sComparator
  • {
  • tBoolean (*areEqual)(tElement, tElement);
  • };
  • tComparator Comparator_allocate()
  • {
  • return (tComparator)malloc(sizeof(struct sComparator));
  • }
  • typedef struct sInteger *tInteger;
  • struct sInteger
  • {
  • int Value;
  • tInteger (*create)(int);
  • tComparator Comparator;
  • };
  • tInteger Integer_allocate()
  • {
  • return (tInteger)malloc(sizeof(struct sInteger));
  • }
  • tInteger Integer_create(int value)
  • {
  • tInteger This = Integer_allocate();
  • This -> Value = value;
  • return This;
  • }
  • tBoolean Integer_areEqual(tElement a, tElement b)
  • {
  • tInteger i = (tInteger)a;
  • tInteger j = (tInteger)b;
  • return (i -> Value) == (j -> Value);
  • }
  • tInteger Integer;
  • void createIntegerType(void)
  • {
  • Integer = Integer_allocate();
  • Integer -> create = Integer_create;
  • tComparator comparator = Comparator_allocate();
  • comparator -> areEqual = Integer_areEqual;
  • Integer -> Comparator = comparator;
  • }
  • typedef struct sComplex *tComplex;
  • struct sComplex
  • {
  • float RealPart;
  • float ImaginaryPart;
  • tComplex (*create)(float, float);
  • tComparator Comparator;
  • };
  • tComplex Complex_allocate()
  • {
  • return (tComplex)malloc(sizeof(struct sComplex));
  • }
  • tComplex Complex_create(float real_part, float imaginary_part)
  • {
  • tComplex This = Complex_allocate();
  • This -> RealPart = real_part;
  • This -> ImaginaryPart = imaginary_part;
  • return This;
  • }
  • tBoolean Complex_areEqual(tElement a, tElement b)
  • {
  • tComplex x = (tComplex)a;
  • tComplex y = (tComplex)b;
  • return ((x -> RealPart) == (y -> RealPart)) and ((x -> ImaginaryPart) == (y -> ImaginaryPart));
  • }
  • tComplex Complex;
  • createComplexType()
  • {
  • Complex = Complex_allocate();
  • tComparator comparator = Comparator_allocate();
  • Complex -> create = Complex_create;
  • comparator -> areEqual = Complex_areEqual;
  • Complex -> Comparator = comparator;
  • }
  • tBoolean areEqual(tElement a, tElement b, tComparator comparator)
  • {
  • return comparator -> areEqual(a, b);
  • }
  • int main(void)
  • {
  • createIntegerType();
  • createComplexType();
  • tInteger i = Integer -> create(4);
  • tInteger j = Integer -> create(4);
  • tComplex x = Complex -> create(1, 1);
  • tComplex y = Complex -> create(1, 1);
  • tBoolean b;
  • b = areEqual(i, j, Integer -> Comparator);
  • if(b) printf("Oui ! Ces 2 entiers sont egaux ! \n");
  • b = areEqual(x, y, Complex -> Comparator);
  • if(b) printf("Oui ! Cest 2 complexes sont egaux ! \n");
  • system("PAUSE");
  • return 0;
  • }
#include <stdio.h>
#include <stdlib.h>


typedef enum{TRUE = 1, FALSE = 0} tBoolean;

#define and &&


#define tElement void *


typedef struct sComparator *tComparator;
struct sComparator
{
   tBoolean (*areEqual)(tElement, tElement);
};

tComparator Comparator_allocate()
{
   return (tComparator)malloc(sizeof(struct sComparator));
}


typedef struct sInteger *tInteger;
struct sInteger
{
   int Value;
   
   tInteger (*create)(int);
   
   tComparator Comparator;   
};

tInteger Integer_allocate()
{
   return (tInteger)malloc(sizeof(struct sInteger));
}

tInteger Integer_create(int value)
{
   tInteger This = Integer_allocate();
   This -> Value = value;
   return This;   
}

tBoolean Integer_areEqual(tElement a, tElement b)
{
   tInteger i = (tInteger)a;
   tInteger j = (tInteger)b;
   
   return (i -> Value) == (j -> Value);
}

tInteger Integer;

void createIntegerType(void)
{
   Integer = Integer_allocate();
   Integer -> create = Integer_create;
   tComparator comparator = Comparator_allocate();
   comparator -> areEqual = Integer_areEqual;
   Integer -> Comparator = comparator;
}


typedef struct sComplex *tComplex;
struct sComplex
{
   float RealPart;
   float ImaginaryPart;
   
   tComplex (*create)(float, float);
   
   tComparator Comparator;
};

tComplex Complex_allocate()
{
   return (tComplex)malloc(sizeof(struct sComplex));   
}

tComplex Complex_create(float real_part, float imaginary_part)
{
   tComplex This = Complex_allocate();
   This -> RealPart = real_part;
   This -> ImaginaryPart = imaginary_part;
   return This;
}

tBoolean Complex_areEqual(tElement a, tElement b)
{
   tComplex x = (tComplex)a;
   tComplex y = (tComplex)b;
   
   return ((x -> RealPart) == (y -> RealPart)) and ((x -> ImaginaryPart) == (y -> ImaginaryPart));
}

tComplex Complex;

createComplexType()
{
   Complex = Complex_allocate();
   tComparator comparator = Comparator_allocate();
   Complex -> create = Complex_create;
   comparator -> areEqual = Complex_areEqual;
   Complex -> Comparator = comparator;
}


tBoolean areEqual(tElement a, tElement b, tComparator comparator)
{
   return comparator -> areEqual(a, b);
}

int main(void)
{
   createIntegerType();
   createComplexType();
   
   tInteger i = Integer -> create(4);
   tInteger j = Integer -> create(4);
   
   tComplex x = Complex -> create(1, 1);
   tComplex y = Complex -> create(1, 1);
   
   tBoolean b;
   
   b = areEqual(i, j, Integer -> Comparator);
   if(b) printf("Oui ! Ces 2 entiers sont egaux ! \n");
   
   b = areEqual(x, y, Complex -> Comparator);
   if(b) printf("Oui ! Cest 2 complexes sont egaux ! \n");
   
   system("PAUSE");
   return 0;   
}

 Conclusion

J'ai rien trouver sur internet pour faire ce genre de chose et c'est pourquoi je le poste. De plus, j'ai codé de tel manière à ce que ça ressemble à de l'objet. Mais c'est pas le problème ici. En tout cas, le niveau de la source est expert parce que mine de rien, c'est pas mal tendu pour comprendre.


 Sources de la même categorie

Source avec une capture POWER MATH: TESTE DE VITESSE ENTIERS VS REELS , CLASS VS STR... par dedalusman
Source avec Zip PARSER XML par MagnumPP
[C BZLIB] LIRE ET ÉCRIRE UN FICHIER COMPRESSÉ par Zestyr
Source avec Zip Source avec une capture BOT DE CLIC (SIMULATION DE CLIC PARAMÈTRABLE) par jojo930
Source avec Zip Source avec une capture [C++] GENERATEUR DE PSEUDO par Miwik

 Sources en rapport avec celle ci

EVALUER UNE EXPRESSION MATHÉMATIQUE par begueradj
SMART POINTEUR À COMPTEUR DE RÉFÉRENCE par nirgal76
POINTEUR INTELLIGENT par snpier wolf
Source avec Zip SUDOKU CONSOLE par fratom
Source avec Zip CACHER LES CURSEURS SYSTÈME (WIN32 API) par racpp

Commentaires et avis

Commentaire de vecchio56 le 12/01/2007 22:06:20 administrateur CS

Tu montres comment on utilise un pointeur de fonction en gros, je vois pas ce qu'il y a de nouveau
Pour simplifier l'écriture, pourquoi ne pas écrire areEqual(i, j, Integer_areEqual);

Sinon, j'ai été assez étonné de voir la ligne #define and &&, il y a une raison particulière pour que tu mettes ca?

Commentaire de LocalStone le 12/01/2007 22:19:40

Tu as raison, c'est clair que l'on peut écrire ça, y a pas de soucis. Si j'ai fait tout ce bordel, c'était pour rendre l'ensemble corréhent. Si tu regardes, c'est codé un peu différement de ce que l'on peut voir d'habitude.
Ensuite, pour le pointeur ... Euh oui, c'est vrai. Mais l'idée, c'est d'avoir un pointeur void* comme paramètre.
Enfin, le #define and && ... Bah quoi ? Qu'est ce que ça peut faire ? Au lieu d'avoir à marquer a && b, j'ai juste à marquer a and b ... Je vois pas trop le soucis.

Commentaire de acx01b le 12/01/2007 23:46:29

salut, je te donne mon avis
je trouve l'avantage du C++ c'est que quand c'est bien fait, c'est lisible, là ton code c'est un peu du langage codé je trouve qui va jusqu'à un
#define and &&
et
#define tElement void *
ou encore pire selon moi
typedef struct sComparator *tComparator;

pas bien ! on doit savoir quand on utilise un pointeur ou pas
( pour bien utiliser le free par exemple ! )

voila je trouve ça tarabiscôté
a+

Commentaire de vicenzo le 12/01/2007 23:48:45

J'ai du mal a saisir l'utilité de ce code c++ dans le contexte c qui tu décris... Toute cette mayo bizarre pour un simple pointeur sur une fonction !!! Ton code fait 137 lignes. Voici une variante pure C de 45 lignes (soit 3 fois moins de code) et qui fait la même chose :

#include <stdio.h>
#include <stdlib.h>
  
typedef int (*cmp_fct_t)(void *, void*);

typedef struct complex_t
{
float real;
float imaginary;
} complex_t;

int equals(void *arg1, void *arg2, cmp_fct_t f)
{
return f(arg1, arg2);
}

int cmp_int(void *pi1, void *pi2)
{
return ((*(int*) pi1) == (*(int*) pi2));
}

int cmp_complex(void *pcpx1, void *pcpx2)
{
complex_t *cpx1 = (complex_t *) pcpx1;
complex_t *cpx2 = (complex_t *) pcpx2;

return ((cpx1->real == cpx2->real) && (cpx1->imaginary == cpx2->imaginary));
}

int main(void)
{
int i = 4;
int j = 4;

complex_t x = {1,1};
complex_t y = {1,2};

if (equals(&i, &j, cmp_int))
printf("Oui ! Ces 2 entiers sont egaux ! \n");

if (equals(&x, &y, cmp_complex))
printf("Oui ! Ces 2 complex sont egaux ! \n");

system("PAUSE");
return 0;
}

Commentaire de BruNews le 13/01/2007 03:26:39 administrateur CS

Oui oui Vicenzo, c'est le type de code qu'on emploie ordinairement avec une fonction comme qsort(), très simple d'écriture et qu'un compilo correct optimisera parfaitement.

Commentaire de vicenzo le 13/01/2007 11:09:46

simplicité est mère d'efficacité ! Pourquoi faire compliqué quand le problème est tout simple. !

C'est pourquoi, je ne pige pas le choix du niveau initié !

les pointeurs génériques et les pointeurs de fonction ont fait la force (puissance) du C et en même temps sa faiblesse (la + grande source de bug au monde !)

Donc, pour ta fonction sort, utilise qsort() en lui fournissant une fonction de tri de ton choix, tu ne pourra pas faire mieux, je pense !

Commentaire de LocalStone le 13/01/2007 11:30:18

:) En fait vous n'êtes pas encore prêt ...
Non, je plaisante. C'est vrai que j'ai pas trop expliqué pourquoi le code est un peu bizarre. En fait, j'ai appris le C cette année. Je connaissais déjà le Java, le C# et tout ça, mais je ne connaissais pas le C. Et il se trouve que dans l'école dans laquelle je me trouve, il nous appris à nous servir du C en utilisant que des références. En fait, ils pensaient déjà au semestre suivant : l'apprentissage du Java.
Du coup j'ai cherché et j'ai trouvé ça : http://chgi.developpez.com/c/objet/.
Et en fait, j'ai globalement suivi cette methode. J'ai seulement rajouté l'idée de l'instance porteuse de constructeut avec la variable globale dont le nom est presque identique au type.
Voilà voilà ... Maintenant, je suis d'accord, autant faire du C++. Bah ouais, mais je peux pas ... Pour l'instant :)
Dans l'espoir d'avoir été un peu mieux compris ...

Commentaire de vicenzo le 13/01/2007 13:38:43

Bon, LocalStone :

* primo : la notion de "référence" n'existe pas en C ! Donc dire : "je fais du C avec des références" est un non sens. En C il y des objets (au sens générique de variable et non en terme de poo) et des pointeurs sur ces objets !

* L'article que tu mentionnes "le C Objet" explique en fait l'idée qu'a eu un certain Bjarne Soustroup il y a 25 ans quant il a crée le "C with classes" qui est devenu le C++. Au début, le code "C with classes" était présenté à un précompileur qui se chargait de générer un code C dans le même esprit que celui de l'article...

* Si tu a besoin d'aide sur le C, n'hésites pas, demande !!!

Commentaire de LocalStone le 13/01/2007 14:54:52

Grrr ... Je sais pas comment vous expliquer.
Je sais qu'il n'y a pas de référence en C. La manière dont le code est structuré permet dans ce cas de SIMULER des références, justement en cachant totalement la notion de pointeur. Naturellement, c'est stupide de faire ça, étant donné qu'il existe le Java, le C++, le C# et j'en passe et des meilleurs. Mais ! ... Bah dans le cadre de mon projet, je devais absolument le faire en C. C'est pour ça que j'ai du faire ça. Voilà voilà ...

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

void comparaison [ par yopia ] voila le principe g une liste de pointeurs (void*)comme ca on peut mettre nimporte quoi dans cte liste.le pb : comment faire pour comparer 2 élément e Tri d'objets avec qsort. [ par Tazrael ] Hum, voilà je souhaite trier un tableau d'objets avec qsort. Ici les objets sont des scores, et on y accède via un accesseur. Le problème c'est que la "Comparaison" pointeur [ par LordBob ] Bonjour a tous,voila j'ai des petits probl&#232;mes avec une application et mes pointeurs... en fait je r&#233;cup&#233;ren en d&#233;but de programme Utilisation d'un pointeur de fonction membre [ par cyrcocq ] Bonjour,J'ai d&#233;j&#224; discut&#233; de &#231;a ailleurs, on m'a conseill&#233; d'autres m&#233;thodes, mais imaginons une classe contenant un ens liste chainée et pointeur générique ? [ par tintin72 ] Bonjour, J'essaie de coder une liste chainée dont la valeur à stockée est matérialisé par un pointeur sur void de façon rendre mon code générique: comparaison entre 2 fonctions [ par cyss ] Est-ce que ces 2 fonctions sont equivalentes?void f1(char *t){    if (t!=0)    {        while(*t!=0)        {            cout&lt;&lt;*t;             t Pointeur sur fonction envoyé par dll [ par MoDDiB ] Voila ce que j'ai fais mais ca ne marche pas :Dll :#include &lt;windows.h&gt;BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpR pointeur static sur fonction :) [ par luhtor ] Certain reconnaitront surement le tutoriel en question. J'ai rajouté quelques trucs au gestionnaire d'exception, mais je bloque sur le point suivant:J Pointeur vers une fonction dans une classe ... [ par MoDDiB ] Supposons que j'ai la fonctionvoid Fonction(int test,int t);appartenant a la classe Cclass.Quelle est la syntaxe pour creer un pointeur vers cette fon écriture pointeur de struct [ par Vaughn018 ] Bonjour j'ai un oubli complet (trop de code tue le code!) sur la façon d'écrire des données lorsqu'il s'agit du cas suivant :typedef struct Point{


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mars 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728
293031    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,780 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales