IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

rendre une fonction plus générique


Sujet :

C

  1. #1
    Membre averti
    Avatar de Sparky95
    Homme Profil pro
    Full Stack (web) developer
    Inscrit en
    Décembre 2016
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Full Stack (web) developer
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2016
    Messages : 379
    Points : 358
    Points
    358
    Par défaut rendre une fonction plus générique
    Bonjour,
    J'ai pour le moment 2 fonctions quasi identique et je voulais savoir comment les fusionner?
    fonction 1
    Code c : 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
    /*
    	tri un stucture index ouvrier
    	DEMANDE adresse struct index ouvrier, Max ouvriers
    */
    void tri(struct indexouvrier* Index, int size)
    {
    	short i = 0, j = 0;
    		struct indexouvrier tmp;
     
    	for (i = 0; i < size; i++)
    		for (j = i; j < size && strcmp((Index + i)->Nom, "-1") != 0 && strcmp((Index + j)->Nom, "-1") != 0; j++)
    			if (strcmp((Index + i)->Nom, (Index + j)->Nom) > 0 && strcmp((Index + j)->Nom, "-1") != 0) {
    				/*intervertir les 2 structures*/
    				tmp = Index[i];
    				Index[i] = Index[j];
    				Index[j] = tmp;
    			}
    }
    fonction 2
    Code c : 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
    /*
    	tri un stucture index chantier
    	DEMANDE adresse struct index chantier, Max chantiers
    */
    void tri(struct indexchantier* Index, int size)
    {
    	short i = 0, j = 0;
    		struct indexchantier tmp;
     
    	for (i = 0; i < size; i++)
    		for (j = i; j < size && strcmp((Index + i)->Nom, "-1") != 0 && strcmp((Index + j)->Nom, "-1") != 0; j++)
    			if (strcmp((Index + i)->Nom, (Index + j)->Nom) > 0 && strcmp((Index + j)->Nom, "-1") != 0) {
    				/*intervertir les 2 structures*/
    				tmp = Index[i];
    				Index[i] = Index[j];
    				Index[j] = tmp;
    			}
    }
    la seul chose qui change c'est la définition de structure l'une est faite pour un index chantier et l'autre pour un index ouvrier.
    Size représente la taille du tableau de structure index respectif

    Merci d'avance pour votre aide

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Si tu veux faire une fonction pouvant accepter deux pointeurs différents dans un même paramètre, alors faut que ce paramètre soit un pointeur universel (void *).

    Mais ensuite vient le souci de la comparaison. Parce qu'avec un pointeur universel, tu ne peux plus accéder à son membre "nom" (car le compilo ne sait pas associer le pointeur à la structure adéquate). Donc faut que tu intègres un nouveau paramètre permettant à la fonction de savoir de quoi il s'agit. Selon ce paramètre soit tu récupères le pointeur dans un struct ouvrier soit dans un struct chantier. Et de même avec ton "tmp" que tu dois décliner en 2 versions.

    Code c : 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
    void tri(void* Index, int size, char item) {
    	short i = 0, j = 0;
    	struct indexouvrier *iO;
    	struct indexouvrier tmpO;
    	struct indexchantier *iC;
    	struct indexchantier tmpC;
     
    	switch (item) {
    		case 'C':
    			iC=Index;
    			for (i = 0; i < size; i++) {
    				for (j = i; j < size && strcmp((iC + i)->Nom, "-1") != 0 && strcmp((iC + j)->Nom, "-1") != 0; j++) {
    					if (strcmp((iC + i)->Nom, (iC + j)->Nom) > 0 && strcmp((iC + j)->Nom, "-1") != 0) {
    						/*intervertir les 2 structures*/
    						tmpC = iC[i];
    						iC[i] = iC[j];
    						iC[j] = tmpC;
    					}
    				}
    			}
    			break;
    		case 'O':
    			iO=Index;
    			for (i = 0; i < size; i++) {
    				for (j = i; j < size && strcmp((iO + i)->Nom, "-1") != 0 && strcmp((iO + j)->Nom, "-1") != 0; j++) {
    					if (strcmp((iO + i)->Nom, (iO + j)->Nom) > 0 && strcmp((iO + j)->Nom, "-1") != 0) {
    						/*intervertir les 2 structures*/
    						tmpO = iO[i];
    						iO[i] = iO[j];
    						iO[j] = tmpO;
    					}
    				}
    			}
    			break;
    	}
    }

    Ou alors tu t'inspires de qsort qui reçoit en paramètre à la fois le tableau à trier mais aussi comment comparer deux éléments de ce tableau et la taille d'un élément afin de pouvoir le permuter avec un autre...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Il faudrait aussi savoir s'il y a une réelle différence entre les 2 structures , pour soit :
    • Supprimer 1 et peut-être renommer l'autre de façon générique one_index
    • Fusionner les 2 structures, au prix que les structures vont être plus grosses en mémoire. Et donc juger si la partie utile de chaque structure reste majoritaire.
    • Utiliser des pointeurs opaques, au prix d'indirections en plus.



    Et pour le code de Sve@r, j'aurais plutôt coder comme cela
    Code c : 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
     
    // Peut-être l'encapsuler dans une structure
    typedef enum e_INDEX_TYPE {
        GLB_TYPE_CHANTIER = 0,
        GLB_TYPE_OUVRIER/*,
        GLB_NB_TYPES*/
    } t_INDEX_TYPE
     
     
    void tri(void* Index, int size, t_INDEX_TYPE item) {
    	size_t i, j;
     
    	switch (item) {
    	case GLB_TYPE_CHANTIER :
    		{
    			struct indexchantier *iC;
    			struct indexchantier tmpC;
     
    			iC=Index;
    			for (i = 0; i < size; i++) {
    				for (j = i; j < size && strcmp((iC + i)->Nom, "-1") != 0 && strcmp((iC + j)->Nom, "-1") != 0; j++) {
    					if (strcmp((iC + i)->Nom, (iC + j)->Nom) > 0 && strcmp((iC + j)->Nom, "-1") != 0) {
    						/*intervertir les 2 structures*/
    						tmpC = iC[i];
    						iC[i] = iC[j];
    						iC[j] = tmpC;
    					}
    				}
    			}
    		}
    		break;
    	case GLB_TYPE_OUVRIER:
    		{
    			struct indexouvrier *iO;
    			struct indexouvrier tmpO;
     
    			iO=Index;
    			for (i = 0; i < size; i++) {
    				for (j = i; j < size && strcmp((iO + i)->Nom, "-1") != 0 && strcmp((iO + j)->Nom, "-1") != 0; j++) {
    					if (strcmp((iO + i)->Nom, (iO + j)->Nom) > 0 && strcmp((iO + j)->Nom, "-1") != 0) {
    						/*intervertir les 2 structures*/
    						tmpO = iO[i];
    						iO[i] = iO[j];
    						iO[j] = tmpO;
    					}
    				}
    			}
    		}
    		break;
    	}
    }

  4. #4
    Membre averti
    Avatar de Sparky95
    Homme Profil pro
    Full Stack (web) developer
    Inscrit en
    Décembre 2016
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Full Stack (web) developer
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2016
    Messages : 379
    Points : 358
    Points
    358
    Par défaut
    Malheureusement je ne peux pas faire cela car c'est dans le cadre d'un dossier de fin d'année à rendre et donc les structures sont fournies
    et les profs ne veulent pas de variables globales.
    Et ta proposition j'y ai pensé mais c'est aussi gros que de faire 2 fonctions donc autant en faire 2 ^^ c'est plus claire et plus portable
    Et à ce moment la moi j'aurais codé cela comme ca
    Code c : 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
    /*
    	tri un stucture index ouvrier
    	DEMANDE adresse struct index ouvrier, Max ouvriers
    */
    void tri((void*) Index, int size, bool status)
    {
    	short i = 0, j = 0;
    	struct indexouvrier tmp;
    	struct indexchantier tm2;
     
    	for (i = 0; i < size; i++)
    		for (j = i; j < size && strcmp((Index + i)->Nom, "-1") != 0 && strcmp((Index + j)->Nom, "-1") != 0; j++)
    			if (strcmp((Index + i)->Nom, (Index + j)->Nom) > 0 && strcmp((Index + j)->Nom, "-1") != 0)
    				if(status){
    					/*intervertir les 2 structures*/
    					tmp = Index[i];
    					Index[i] = Index[j];
    					Index[j] = tmp;
    				}else{
    					/*intervertir les 2 structures*/
    					tmp2 = Index[i];
    					Index[i] = Index[j];
    					Index[j] = tmp2;
    				}
    }
    maintenant si je comprend bien ce qui est écris n'irait pas car si l'on mets (void*)
    la comparaison "tmp = Index[i]" ne fonctionne pas vu qu'il ne peut vérifier si les 2 éléments sont de même type
    est-ce bien ça?

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par Sparky95 Voir le message
    Et ta proposition j'y ai pensé mais c'est aussi gros que de faire 2 fonctions donc autant en faire 2 ^^ c'est plus claire et plus portable
    Il faut faire des interfaces dans ce cas

    One_Ouvrier.h/ One_Ouvrier.c :
    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
    #ifndef ONE_OUVRIER_H
    #define ONE_OUVRIER_H
     
    typedef strut s_One_Ouvrier {
    /* ... */
    } One_Ouvrier;
     
     
    /* Public Interface */
     
    void ouvrier_destroy(One_Ouvrier*);
     
    void ouvrier_init(One_Ouvrier**);
     
    void ouvrier_tri(One_Ouvrier*, int /*size*/, bool /*status*/);
     
    /* ... */
     
    #endif /*ONE_OUVRIER_H*/
    Et la même chose pour l'autre structure chantier


    Citation Envoyé par Sparky95 Voir le message
    la comparaison "tmp = Index[i]" ne fonctionne pas vu qu'il ne peut vérifier si les 2 éléments sont de même type
    est-ce bien ça?
    Oui, void veut dire "quelque chose" et le compilateur doit savoir le type pour compiler les tests, les déférencements, les passages de paramètres ...

  6. #6
    Membre averti
    Avatar de Sparky95
    Homme Profil pro
    Full Stack (web) developer
    Inscrit en
    Décembre 2016
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Full Stack (web) developer
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2016
    Messages : 379
    Points : 358
    Points
    358
    Par défaut
    Je fais plus ou moins ça vu qu'on nous à pas appris comment faire ces *.h et qu'on nous dis tapez tout dans le fichier main ,...
    mais qu'ayant déjà fais quelques makefiles de mon coté je cré un fichier .h ou je mets tout les prototypes,... et plusieurs fichiers .c en fonction des parties: ouvrier, chantier, menu pour mettre les fonctions correspondantes

  7. #7
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Ou alors tu t'inspires de qsort qui reçoit en paramètre à la fois le tableau à trier mais aussi comment comparer deux éléments de ce tableau et la taille d'un élément afin de pouvoir le permuter avec un autre...
    Je plussoie !

  8. #8
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Sparky95 Voir le message
    et les profs ne veulent pas de variables globales.
    J'espère que tu les comprends et que tu adhères...

    Citation Envoyé par Sparky95 Voir le message
    Et ta proposition j'y ai pensé mais c'est aussi gros que de faire 2 fonctions donc autant en faire 2 ^^ c'est plus claire et plus portable
    Exact. Content que tu t'en sois rendu compte tout seul.

    Citation Envoyé par Sparky95 Voir le message
    Et à ce moment la moi j'aurais codé cela comme ca
    Code c : 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
    /*
    	tri un stucture index ouvrier
    	DEMANDE adresse struct index ouvrier, Max ouvriers
    */
    void tri((void*) Index, int size, bool status)
    {
    	short i = 0, j = 0;
    	struct indexouvrier tmp;
    	struct indexchantier tm2;
     
    	for (i = 0; i < size; i++)
    		for (j = i; j < size && strcmp((Index + i)->Nom, "-1") != 0 && strcmp((Index + j)->Nom, "-1") != 0; j++)
    			if (strcmp((Index + i)->Nom, (Index + j)->Nom) > 0 && strcmp((Index + j)->Nom, "-1") != 0)
    				if(status){
    					/*intervertir les 2 structures*/
    					tmp = Index[i];
    					Index[i] = Index[j];
    					Index[j] = tmp;
    				}else{
    					/*intervertir les 2 structures*/
    					tmp2 = Index[i];
    					Index[i] = Index[j];
    					Index[j] = tmp2;
    				}
    }
    maintenant si je comprend bien ce qui est écris n'irait pas car si l'on mets (void*)
    la comparaison "tmp = Index[i]" ne fonctionne pas vu qu'il ne peut vérifier si les 2 éléments sont de même type
    est-ce bien ça?
    C'est ça mais en pire. Car non seulement on peut pas comparer "tmp" avec "index[i]" mais en plus "index" n'étant pas de type "struct ouvrier" ou "struct chantier", il ne possède même pas de membre "nom" quand tu écris "index[i].nom"...

    Citation Envoyé par Bktero Voir le message
    Je plussoie !
    En fait, je voulais même écrire un exemple dans ce sens. Mais à un moment il compare index[i].nom avec "-1" (sentinelle probable) et en dessous il compare index[i].nom avec index[j].nom. Et là, ça devenait trop chiant...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Membre averti
    Avatar de Sparky95
    Homme Profil pro
    Full Stack (web) developer
    Inscrit en
    Décembre 2016
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : Belgique

    Informations professionnelles :
    Activité : Full Stack (web) developer
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2016
    Messages : 379
    Points : 358
    Points
    358
    Par défaut
    enfait j'initialise à -1 du coup si je triais j'avais le -1 au début du tableau donc ce que je fais c'est que je mets les -1 deriere
    Et du coup j'ai pas besoin de comparer plus loins si il y a 2 "-1"

  10. #10
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Sparky95 Voir le message
    enfait j'initialise à -1 du coup si je triais j'avais le -1 au début du tableau donc ce que je fais c'est que je mets les -1 deriere
    Et du coup j'ai pas besoin de comparer plus loins si il y a 2 "-1"
    Oui, principe de la sentinelle (valeur précise indiquant la fin logique de l'ensemble => le plus connu étant le '\0' terminant une chaine de caractères).

    Maintenant, si le tri n'est pas forcé d'être à ta charge, pourquoi ne pas carrément utiliser la fonction standard qsort() ???

    Exemple
    Code c : 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
    int cmpOuvrier(void const *x, void const *y) {
    	struct indexouvrier *xx=x;
    	struct indexouvrier *yy=y;
     
    	return strcmp(xx->nom, yy->nom);
    }
     
    int cmpChantier(void const *x, void const *y) {
    	struct indexchantier *xx=x;
    	struct indexchantier *yy=y;
     
    	return strcmp(xx->nom, yy->nom);
    }
     
    ...
    // Tri des ouvriers
    qsort(tabOuvrier, nb_ouvrier, sizeof(struct indexouvrier), cmpOuvrier);
     
    // Tri des chantiers
    qsort(tabChantier, nb_chantier, sizeof(struct indexchantier), cmpChantier);

    Ca fonctionne mais ça t'oblige à modifier un peu tes conventions. Tu n'as plus le droit de mettre "-1" dans un nom (ou si tu le fais ce "-1" est vu comme un nom donc il est comparé ainsi avec les autres noms) et tu dois connaitre le nombre d'éléments de ton tableau.

    Mais en contrepartie tu n'as plus à t'embêter à écrire le tri...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  11. #11
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Comportement indéterminé. Le type attendu est int (*)(void const *, void const *), il faut cast les paramètres manuellement.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Rendre Une Fonction Parametrable
    Par khayate dans le forum VB.NET
    Réponses: 9
    Dernier message: 06/06/2007, 14h23
  2. [C#][2.0] Appel à une fonction dans global.asax
    Par lilianjee dans le forum ASP.NET
    Réponses: 2
    Dernier message: 05/10/2006, 15h58
  3. rendre une cellule plus claire au passage de la souris
    Par pierrot10 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 5
    Dernier message: 02/08/2006, 09h29
  4. Rendre une fonction generalisable...
    Par Grand Mamamouchi dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 21/11/2004, 09h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo