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 :

Passer un opérateur en paramètre et lire un double ?


Sujet :

C

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Par défaut Passer un opérateur en paramètre et lire un double ?
    Bonjour

    J'aurais 2 questions si vous permettez

    J'ai 4 fonctions, la seule chose qui en fait la différence c'est l'opérateur, + - * et /

    Est-ce que c'est possible de ne faire qu'une seule fonction et lui passer l'opérateur en paramètre ?

    Faire un truc du genre: fonction A(operator op, int x) x op = x
    Si on passe + ça ferait x+=x;

    Aussi quelle serait la façon la plus pratique de convertir une chaîne char* en double ? Mais que la fonction puisse me dire si char* est un nombre valide au cas ou mon char* aurait des lettres ou des espaces, etc.

    Merci

  2. #2
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Citation Envoyé par AsmCode
    J'ai 4 fonctions, la seule chose qui en fait la différence c'est l'opérateur, + - * et /

    Est-ce que c'est possible de ne faire qu'une seule fonction et lui passer l'opérateur en paramètre ?
    Oui bien sûr, l'opérateur peut être stocké dans un type char tout simplement (attention pas un pointeur mais bel et bien un char) puis ensuite il te suffit de faire un switch ... case avec les différents cas qui seront les opérateurs:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    switch (operateur)
    {
       case '+':
       ...
       case '-':
       ...
       case '*':
       ...
       case '/':
       ...
    }

    Citation Envoyé par AsmCode
    Aussi quelle serait la façon la plus pratique de convertir une chaîne char* en double ? Mais que la fonction puisse me dire si char* est un nombre valide au cas ou mon char* aurait des lettres ou des espaces, etc.
    strtod
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  3. #3
    Membre extrêmement actif

    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Juin 2003
    Messages
    4 506
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 506
    Par défaut
    Pour savoir s'il s'agit d'un nombre ou pas tu peux utiliser la fonction isdigit

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2007
    Messages : 41
    Par défaut
    Tu ne peut pas passer des operateurs en arguements en C, mais tu peut passer des fonctions:

    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
     
    int add(int a, int b){
        return a + b;
    }
     
    int sub(int a, int b){
        return a - b;
    }
     
    int mul(int a, int b){
        return a * b;
    }
     
    int div(int a, int b){
        return a / b;
    }
     
    int fold(int (*f)(int,int), int a, int *list, int size){
        int i;
        for(i = 0; i < size; i++){
            a = f(a,list[i]);
        }
        return a;
    }
     
    int main(){
        int nums[5] = {1,2,3,4,5};
        printf("somme: %d\nproduit: %d\n", fold(add,0,nums,5), fold(mul,1,nums,5));
    }

  5. #5
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Citation Envoyé par atnnn
    Tu ne peut pas passer des operateurs en arguements en C, mais tu peut passer des fonctions:
    Si tu te prennais la peine de lire au moins les posts tu saurais que justement sont but c'est de n'avoir qu'une seule fonction donc ma solution est bonne à prendre.

    Ce qui donne par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double calcul_double (double operande1, double operande2, char operateur);
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  6. #6
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Franck.H
    Si tu te prennais la peine de lire au moins les posts tu saurais que justement sont but c'est de n'avoir qu'une seule fonction donc ma solution est bonne à prendre.

    Ce qui donne par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double calcul_double (double operande1, double operande2, char operateur);
    Sauf que ce n'est pas un "opérateur" au sens strict que l'on passe, ( f(+) n'est pas du C) mais une constante caractère (donc de type int et non char... : f('+') ) qui sert à déterminer quelle opération doit être effectuée.

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2007
    Messages : 41
    Par défaut
    Citation Envoyé par Franck.H
    Si tu te prennais la peine de lire au moins les posts tu saurais que justement sont but c'est de n'avoir qu'une seule fonction donc ma solution est bonne à prendre.

    Ce qui donne par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double calcul_double (double operande1, double operande2, char operateur);
    Si ce n'est qu'une seule fonction qu'il faut, alors il faudrait prendre par exemple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    double A(double (*op)(double,double), double *x){
        return *x = op(*x,*x);
    }
    Le but de ne faire qu'une seule fonction est de reduire la taille du code, de ne pas repeter le meme code plusieurs fois et de faciliter la reutilisation du code. Avec un switch, il faut modifier la fonction chaque fois que l'ont veut rajouter un operateur, mais si on ne fait que passer la fonction en parametre, il suffit de lui passer une autre fonction.

    Malheureusement, le C ne supporte pas entierement le polymorphisme, les fonctions anonymes et la programmation orientee object, mais il faut quand utiliser les abstractions disponibles.

  8. #8
    Membre extrêmement actif

    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Juin 2003
    Messages
    4 506
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2003
    Messages : 4 506
    Par défaut
    Citation Envoyé par atnnn
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    double A(double (*op)(double,double), double *x){
        return *x = op(*x,*x);
    }
    Le truc qui cloche c'est le nom de la fonction et le nom du second paramètre, vraiment pas du tout autoinformant.

    Sinon pourquoi ne pas faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    double A(double (*op)(double,double), double *x){
        return op(*x,*x);
    }
    ?

  9. #9
    Membre émérite

    Profil pro
    Inscrit en
    Août 2003
    Messages
    878
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 878
    Par défaut
    Citation Envoyé par atnnn
    Avec un switch, il faut modifier la fonction chaque fois que l'ont veut rajouter un operateur
    Et avec ta solution il faut écrire une nouvelle fonction.
    Je ne mets pas en cause ta solution mais ton argument est loin d'être convaincant : en gros, avec une solution il faut modifier le code alors qu'avec la tienne il faut modifier le code. Un gain énorme, sans aucun doute.
    Tu aurais parlé d'élégance, je t'aurai peut-être suivi mais c'est une notion plutôt subjective...

    Citation Envoyé par atnnn
    Malheureusement, le C ne supporte pas entierement le polymorphisme, les fonctions anonymes et la programmation orientee object
    D'autres langages sont là pour ça.

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2007
    Messages : 41
    Par défaut
    Citation Envoyé par David.Schris
    Et avec ta solution il faut écrire une nouvelle fonction.
    Je ne mets pas en cause ta solution mais ton argument est loin d'être convaincant : en gros, avec une solution il faut modifier le code alors qu'avec la tienne il faut modifier le code. Un gain énorme, sans aucun doute.
    Tu aurais parlé d'élégance, je t'aurai peut-être suivi mais c'est une notion plutôt subjective...

    D'autres langages sont là pour ça.
    Mais si on n'a pas besoin de modifier nos fonctions pour rajouter de la fonctionalite, on peut les compiler separement et les reutiliser facilement dans d'autres projets sans utiliser le presse-papiers. Imagine que tu aies maintenant une fonction qui prends deux operateurs en parametres, tu dois maintenant imbriquer tes enormes switch, et tu dois recopier a chaque case le code voulu, en y remplacant les operateurs correspondants. Si jamais c'est vraiment d'un switch/case que tu as besoin, eh bien tu peut le faire sur les pointeurs de fonctions. N'es-ca pas amusant?

  11. #11
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    je rajouterais juste un commentaire...

    Le mécanisme que tu suggères, atnnn , est élégant, utile, et déjà largement utilisé en C.

    C'est le mécanisme utilisé en XWindow pour les callbacks, que j'ai également largement utilisé pour diverses fonctions...

    Plus généralement cela s'appelle le mécanisme de fonctions enregistrées.

    Il y a beaucoup d'avantages à ce style (outre l'élégance, il y a la souplesse d'utilisation et de programmation).

    Il n'y a qu'un inconvénient à ma connaissance :

    Il faut définir une structure de fonction invariable, et dont les arguments sont invariables également...
    (voir l'exemple donné par toi ainsi que celui d'hegros).

    Mais c'est effectivement la meilleure solution pour traiter un certain type de choses...


  12. #12
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par souviron34
    Le mécanisme que tu suggères, atnnn , est élégant, utile, et déjà largement utilisé en C.

    C'est le mécanisme utilisé en XWindow pour les callbacks, que j'ai également largement utilisé pour diverses fonctions...

    Plus généralement cela s'appelle le mécanisme de fonctions enregistrées.
    http://emmanuel-delahaye.developpez.com/complog.htm

  13. #13
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Si tu veux Emmanuel.. Mais je parlais d'un mécansime encore plus général que ton exemple (réellement celui donné plus haut)..

    Voici un exemple de ce que je voulais dire :

    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
    63
    64
    65
    66
    67
    68
    69
     
    /*** Structures ***/
     
    typedef int My_Proc(void *client, void *cbstruct);
    typedef struct _My_Fct {
     
          int           functiontype ;
          My_Proc   *adr ;
          void         *data ;
     
    } My_Fct ;
     
     
    typedef struct _My_FctList {
     
          My_Fct *elt ;
          int        n_elts ;
     
    } My_FctList ;
     
     
    /**** Declarations de fonctions publiques ****/
    extern int     My_RegisterFunction   ( int functiontype,
                                                       My_Proc Adr, void *data );
     
    extern int     My_CallRegisteredFunction  ( int functiontype,
                                                             void *FctStruct );
     
     
    /***** Exemple de code ********/
     
    int MCore_CallRegisteredFunction ( int functiontype, void *FctStruct )
    {
    int i, s = ERROR, ss=ERROR ;
     
      if ( Pas_Init == 0 )
         Init_Registered_Functions();
     
       if ( Liste_Fonctions.n_elts == 0 )
          return SUCCESS;
     
       for ( i = 0 ; i < Liste_Fonctions.n_elts ; i++ )
         {
    	if ( ((Liste_Fonctions.elt[i].functiontype == functiontype) ||
    	      (functiontype == ALL_FUNCTIONS)) )
    	  {
    	     ss = Liste_Fonctions.elt[i].adr(Liste_Fonctions.elt[i].data, FctStruct) ;
    	     if ( ss == SUCCESS )
    	       s = SUCCESS ;
    	  }
         }
     
       return s ;
    }
     
    /**** Exemple d'appel ****/
     
      if ( My_RegisterFunction ( DB_POSITIONING, Sets_DB_Position, (void *)NULL) == ERROR )
     
       if ( My_RegisterFunction ( DB_READ_DATA, Gets_Data, (void *)NULL) == ERROR )
     
       if ( My_RegisterFunction ( DB_WRITE_DATA, Writes_Data, (void *)NULL) == ERROR )
     
       if ( My_RegisterFunction ( DB_READ_DATA_INFO, Gets_Data_Info, (void *)NULL) == ERROR )
     
          i = My_RegisterFunction ( INFO_NEW_GRAPHICSDATA,    
                                             Stores_New_GraphicData, (void *)idata );
     
          i = My_RegisterFunction ( START_MOVE, Starts_Shift, (void *)idata);

  14. #14
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    J'ai oublié dans l'exemple précédent de mettre un exemple d'application :

    Exemple :

    une bibliothèque est fabriquée pour servir à fabriquer des serveurs facilement.

    Dans les serveurs on trouve :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
      if ( My_RegisterFunction ( DB_POSITIONING, Sets_DB_Position, (void *)NULL) == ERROR )
    Et dans la bibliothèque on trouve :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
       if ( My_CheckIfRegisteredFunction ( DB_POSITIONING ) )
          if ( My_CallRegisteredFunction ( DB_POSITIONING, &fct3 ) == ERROR )
              return ERROR ;

  15. #15
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par atnnn
    Mais si on n'a pas besoin de modifier nos fonctions pour rajouter de la fonctionalite, on peut les compiler separement et les reutiliser facilement dans d'autres projets sans utiliser le presse-papiers.
    Ta solution est certes elegante et souple (et plutot frequente). Toutefois il y a quelques soucis par rapport a la demande intiale:

    * Alors que le PO souhaites reduire le nombre de fonction de calcul de 4 a 1 (on peut d'ailleurs se demander pourquoi) tu lui proposes une solution avec 5 fonctions, ce qui, vu la demande initiale, ne conviendra propablement pas.
    * Ensuite la switch...case a l'interieur de la fonction de calcul que tu proposes de remplacer, il faudra probablement le faire (ou utiliser un nombre mecanisme equivalent) dans la fonction appelante pour etablir la correspondance entre l'operateur et la fonction a utiliser. Sans connaitre plus de details sur le programme, il est difficile de dire si une telle methode est vraiment interessante pour ce projet (Si l'utilisation de fonction elementaires de calcul est une bonne chose en soi, remonter l'analyse de l'operateur dans la fonction appelante plutot que dans la fonction de calcul ne l'est pas necessairement).

  16. #16
    Membre émérite

    Profil pro
    Inscrit en
    Août 2003
    Messages
    878
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 878
    Par défaut
    Citation Envoyé par gl
    [...]
    * Ensuite la switch...case a l'interieur de la fonction de calcul que tu proposes de remplacer, il faudra probablement le faire (ou utiliser un nombre mecanisme equivalent) dans la fonction appelante pour etablir la correspondance entre l'operateur et la fonction a utiliser. [...]
    Exactement.

  17. #17
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 309
    Par défaut
    Ce que j'avais pensé c'est:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int c = fgetc(stdin);
     
    if (c == 'a' ||c == 'b' || c == 'c' || c == 'd') fonctionA(c);
     
    fonction(int commande) {
     
    char op[3] = {'+', '-', '*', '/'}; // correspond à la valeur ascii de + - * /
    #define action(x) op[x];
     
    double v action(commande-97)= 5; // si c'est a alors double v += 5;
     
    }

  18. #18
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    bah alors là pour faire ça ce serait vraiment un switch à mon humble avis....

Discussions similaires

  1. Réponses: 3
    Dernier message: 17/10/2014, 16h08
  2. [C#] Passer un dataset en paramètre dans un WinForm enfant
    Par iDaaX dans le forum Windows Forms
    Réponses: 3
    Dernier message: 06/01/2005, 21h55
  3. [Conception] Passer une fonction en paramètre
    Par pejay dans le forum Langage
    Réponses: 9
    Dernier message: 09/12/2004, 13h58
  4. passer un champ en paramètre, c'est possible ??
    Par marie253 dans le forum Bases de données
    Réponses: 6
    Dernier message: 09/07/2004, 09h22
  5. Passer une procédure en paramètre ?
    Par Cornell dans le forum Langage
    Réponses: 2
    Dernier message: 24/10/2003, 12h21

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