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 :

comment se débarasser des "if" ?


Sujet :

C

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 14
    Points : 13
    Points
    13
    Par défaut comment se débarasser des "if" ?
    Salut
    Petit nouveau ici et déjà une question (enfin si j'en aurai pas ...)

    Je ne sais pas comment faire pour choisir une fonction selon l'argument qu'on lui passe sans faire plein de if dans tout les coins.

    En code ça sera peut être plus limpide
    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
     
    void      fonction(char *str)
    {
      int    i;
     
      i = 0;
      while (str[i] != '\0')
      {
         if (str[i] == 'a')
            fonction1();
         if (str[i] == 'b')
            fonction2();
         if (str[i] == 'c')
            fonction3();
         if (str[i] == 'd')
            fonction4();
         if (str[i] == 'e')
            fonction5();
         i++;
      }
    return;
    }
    Je sais qu'il y a la fonction switch mais je ne préfére pas l'utiliser, surtout quand je sais qu'il y a un autre moyen ... dont je ne me souviens gère

  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 754
    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 754
    Points : 31 097
    Points
    31 097
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Damax Voir le message
    Salut
    Petit nouveau ici et déjà une question (enfin si j'en aurai pas ...)

    Je ne sais pas comment faire pour choisir une fonction selon l'argument qu'on lui passe sans faire plein de if dans tout les coins.

    En code ça sera peut être plus limpide
    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
     
    void      fonction(char *str)
    {
      int    i;
     
      i = 0;
      while (str[i] != '\0')
      {
         if (str[i] == 'a')
            fonction1();
         if (str[i] == 'b')
            fonction2();
         if (str[i] == 'c')
            fonction3();
         if (str[i] == 'd')
            fonction4();
         if (str[i] == 'e')
            fonction5();
         i++;
      }
    return;
    }
    Je sais qu'il y a la fonction switch mais je ne préfére pas l'utiliser, surtout quand je sais qu'il y a un autre moyen ... dont je ne me souviens gère
    C'est possible à condition que chaque fonction soit de même type et ait la même signature => tu utilises alors une structure contenant
    - la lettre
    - un pointeur sur la fonction associée

    Ex:
    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
    void      fonction(char *str)
    {
        typedef struct {
            char ordre;
            int (*fct)();
        } t_ordonanceur;
     
        // Tableau des ordonanceurs et pointeur pour balayer le tableau
        t_ordonanceur tabOrdo[]={
            {'a', fonction1},
            {'b', fonction2},
            {'c', fonction3},
            {'d', fonction4},
            {'e', fonction5},
            {0, NULL}
        };
        t_ordonanceur *ptOrdo;
     
        // Pointeur pour balayer la chaîne
        char *pt;
     
        // Balayage de la chaîne
        for (pt=str; *pt != '\0'; pt++)
        {
            // Recherche de la lettre dans le membre "ordre" de tabOrdo
            for (ptOrdo=tabOrdo; ptOrdo->ordre != 0; ptOrdo++)
            {
                 // Si l'ordre de l'élément pointé correspond à la lettre en cours
                 if (ptOrdo->ordre == *pt)
                     // On sort de la boucle
                     break;
            }
     
            // Si on n'est pas en fin de "tabOrdo" => on est sorti par "break" => on a "pt" qui pointe alors vers l'ordre correspondant
            if (ptOrdo->ordre != 0)
                // On peut exécuter la fonction associée
                (*ptOrdo->fct)();
        }
    }

  3. #3
    Membre habitué Avatar de archer
    Ingénieur développement logiciels
    Inscrit en
    Mai 2007
    Messages
    338
    Détails du profil
    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 338
    Points : 180
    Points
    180
    Par défaut
    Salut
    Et bien je crois « peut être »que notre ami est un débutant alors si c’est le cas ça sera difficile à digérer. Je propose ‘case’ même si cette commande est très proche de ce qu’il vient de faire
    swich (str[i])
    {
    case 'a' : fonction1();
    break;
    case 'b' : fonction2();
    break;
    case 'c' : fonction3();
    break;
    case 'd' : fonction4();
    break;
    case 'e' : fonction5();
    break;
    default : break;
    }

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 754
    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 754
    Points : 31 097
    Points
    31 097
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par archer Voir le message
    Salut
    Et bien je crois « peut être »que notre ami est un débutant alors si c’est le cas ça sera difficile à digérer. Je propose ‘case’ même si cette commande est très proche de ce qu’il vient de faire
    Ben il a dit dans son premier post qu'il ne voulait pas...

  5. #5
    Membre habitué Avatar de archer
    Ingénieur développement logiciels
    Inscrit en
    Mai 2007
    Messages
    338
    Détails du profil
    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 338
    Points : 180
    Points
    180
    Par défaut
    oui c'est vrai, je suis tout à fait d'accord avec vous, c'est juste au cas où il n'arrive pas à comprendre ce code car il me parrait très avancé

  6. #6
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 754
    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 754
    Points : 31 097
    Points
    31 097
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par archer Voir le message
    c'est juste au cas où il n'arrive pas à comprendre ce code car il me parrait très avancé
    Faut ce qu'il faut. Soit on veut faire sans "if" ni "case" et donc on est obligé de passer par un tableau contenant les pointeurs sur les fonctions à lancer puis on sélectionne l'élément du tableau qui va bien et on l'appelle (car le pointé d'un pointeur de fonction est quand-même une fonction appelable), soit on programme comme au début avec du "case" et/ou du "if". Et c'est pour ça que j'ai mis des commentaires...

  7. #7
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Novembre 2007
    Messages
    16
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2007
    Messages : 16
    Points : 21
    Points
    21
    Par défaut
    on peut faire plus marrant si tu n'es pas a cheval sur la quantite de memoire
    et que tu veux un code rapide.

    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
     
    typedef void (*FctPtr)();
     
    void  DftFct()
    {
      /* fais ce qu'il y a a faire si le caractere est errone */
    }
     
    char  *FctQuiAffectStr()
    {
      return "hello world\n";
    }
     
    /* affectation des appels par defaut */
    int InitFunc(FctPtr *list_fcts, int size)
    {
      int count;
     
      if (size < 0)
        return -1;
      for (count = size - 1; count >= 0; --count)
        list_fcts[count] = &DftFct;
      return 0;
    }
     
    void fonction(FctPtr *list_fct, char *str)
    {
      while (*str)
      {
        list_fct[*str](); /* et la tu appelles directement la fonction sans parcours de liste */
        ++str;
      }
    }
     
    int main()
    {
      FctPtr list_fct[256];
      char *str;
     
      InitFunc(list_fct, 255);
      list_fct['a'] = &fonction1;
      list_fct['b'] = &fonction2;
      /* etc... */
      str = FctQuiAffectStr();
      fonction(list_fct, str);
      return 0;
    }

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 382
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 382
    Points : 41 593
    Points
    41 593
    Par défaut
    Ça manque de const, mais c'est sympa...

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 48
    Points : 37
    Points
    37
    Par défaut
    Sinon tu peux faire une structure qui contiens le caractere et un pointeur la fonction qui correspond et ensuite faire un tableau de structure

    Un exemple base sur un projet que je fais actuellement :

    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
     
     
    typedef struct	s_opt
    {
      char		ch;
      int		(*f)();
      int		va;
      int		fl;
    }		opt_t;
     
    opt_t opt[] = {
      {'c', my_printf_c, 1, 0},
      {'s', my_printf_s, 1, 0},
      {'d', my_printf_d, 1, 1},
      {'i', my_printf_d, 1, 1},
      {'u', my_printf_u, 1, 1},
      {'b', my_printf_b, 1, 0},
      {'S', my_printf_S, 1, 0},
      {'%', my_printf_mod, 0, 0},
      {'o', my_printf_o, 1, 0},
      {0, 0, 0, 0}
    };
     
     
    char	*optest(char *c, va_list *va, int *ctp)
    {
      int	i;
      int	space;
      int	fl;
     
      i = 0;
      while (opt[i].ch != '\0')
        {
          if (*c == opt[i].ch)
    	{
    	  opt[i].f(va, ctp);
    	  return (c);
    	}
          i++;
        }
      return (c);
    }
    J'ai modifier a l'arrache pour qu'il n'y est que le minimum donc j'ai peut eter glisser une pitite faute , mais dans l'idee tu peux faire comme ca et c'est beaucoup plus propre qu'une trentaine de if

    EDIT : Oups j'avais pas vu le message de Sve@r qui dit pareil mais en mieux

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 14
    Points : 13
    Points
    13
    Par défaut
    Citation Envoyé par archer Voir le message
    Salut
    Et bien je crois « peut être »que notre ami est un débutant alors si c’est le cas ça sera difficile à digérer
    Débutant, débutant, j'en fais déjà depuis 8 ... semaines en C et en prog tout court . Sérieusement je suis la pour apprendre donc dur ou pas, c'est neccessaire. Et puis qu'est ce que difficile ?


    Merci à Sve@r, c'était exactement ce que je cherchais.
    Et merci aussi à firemax, je trouve sans code plus lisible (je ne suis pas encore habiter à l'utilisation des for) par contre je ne vois pas l'utilité des variable va et fl dans la structure. Tu peux m'expliquer ?

  11. #11
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 754
    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 754
    Points : 31 097
    Points
    31 097
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Damax Voir le message
    Débutant, débutant, j'en fais déjà depuis 8 ... semaines en C et en prog tout court . Sérieusement je suis la pour apprendre donc dur ou pas, c'est neccessaire (...) je ne suis pas encore habiter à l'utilisation des for
    Et tu t'attaques déjà aux pointeurs de fonctions

    Citation Envoyé par Damax Voir le message
    par contre je ne vois pas l'utilité des variable va et fl dans la structure. Tu peux m'expliquer ?
    fl non plus mais pour moi, "va" me semble être un paramètre que tu passes à la fonction. Dans mon exemple mes fonctions ne recevaient pas de paramètre mais si tu veux leur en passer faut bien les stocker quelque part...

    Citation Envoyé par firemax Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef struct	s_opt {...} opt_t;
    Attention, il me semble que mettre "_t" comme nom de type est un usage réservé à ceux qui font évoluer le C et pas aux utilisateurs (à vérifier)

  12. #12
    Membre émérite Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Points : 2 280
    Points
    2 280
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Attention, il me semble que mettre "_t" comme nom de type est un usage réservé à ceux qui font évoluer le C et pas aux utilisateurs (à vérifier)
    7.1.3 Reserved identifiers
    1 Each header declares or defines all identifiers listed in its associated subclause, and
    optionally declares or defines identifiers listed in its associated future library directions
    subclause and identifiers which are always reserved either for any use or for use as file
    scope identifiers.
    — All identifiers that begin with an underscore and either an uppercase letter or another
    underscore are always reserved for any use.
    — All identifiers that begin with an underscore are always reserved for use as identifiers
    with file scope in both the ordinary and tag name spaces.
    — Each macro name in any of the following subclauses (including the future library
    directions) is reserved for use as specified if any of its associated headers is included;
    unless explicitly stated otherwise (see 7.1.4).
    — All identifiers with external linkage in any of the following subclauses (including the
    future library directions) are always reserved for use as identifiers with external
    linkage.157)
    — Each identifier with file scope listed in any of the following subclauses (including the
    future library directions) is reserved for use as a macro name and as an identifier with
    file scope in the same name space if any of its associated headers is included.
    2 No other identifiers are reserved. If the program declares or defines an identifier in a
    context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved
    identifier as a macro name, the behavior is undefined.
    3 If the program removes (with #undef) any macro definition of an identifier in the first
    group listed above, the behavior is undefined.

  13. #13
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 14
    Points : 13
    Points
    13
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Et tu t'attaques déjà aux pointeurs de fonctions
    Ben ... au faite ... je devais déjà l'avoir apris depuis quelques semaines mais bon ... Et en faite c'est pas si dur, une fois qu'on a compris. C'est comme les pointeurs normaux, je ne pourrai pas faire mes progs sans alors quand un pote me dit qu'il les a vu que 30 minutes après 1an de cours, je ne veux même imaginer la taille des fonctions, sa doit être inbuvable et indébuggable.

    Citation Envoyé par Sve@r Voir le message
    fl non plus mais pour moi, "va" me semble être un paramètre que tu passes à la fonction. Dans mon exemple mes fonctions ne recevaient pas de paramètre mais si tu veux leur en passer faut bien les stocker quelque part...
    je comprend pas vraiment, les arguments sont passer à la fonction dans la fonction qui l'appel. Comme firemax a fait avec va et ctp, non ? Surtout que s'il veut utilisé les valeurs qu'il a mit faut aussi qu'il envoi la valeur pour allé les cherché.

    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
    typedef struct	s_opt
    {
      char		ch;
      int		(*f)();
    }		t_opt;
     
    t_opt      gl_opt[] = {
      {'c', my_printf_c},
      {'s', my_printf_s},
      {'d', my_printf_d},
      {'i', my_printf_d},
      {'u', my_printf_u,
      {'b', my_printf_b},
      {'S', my_printf_S},
      {'%', my_printf_mod},
      {'o', my_printf_o},
      {0, 0}
    };
     
     
    char	*optest(char *c, va_list *va, int *ctp)
    {
      int	i;
      int	space;
      int	fl;
     
      i = 0;
      while (gl_opt[i].ch != '\0')
        {
          if (*c == gl_opt[i].ch)
    	{
    	  gl_opt[i].f(va, ctp);
    	  return (c);
    	}
          i++;
        }
      return (c);
    }

    En regardant bien la code retourné une valeur sans la modifier (ici c) alors qu'il est passé en paramètre, ne sert à rien selon moi.

  14. #14
    Expert éminent sénior
    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
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Attention, il me semble que mettre "_t" comme nom de type est un usage réservé à ceux qui font évoluer le C et pas aux utilisateurs (à vérifier)
    Vu du C, pas de problème. Mais c'est une extension réservée par POSIX...

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

Discussions similaires

  1. comment se débarasser des doublons ?
    Par PtiteNanou dans le forum Modélisation
    Réponses: 2
    Dernier message: 21/11/2007, 16h37
  2. comment se débarasser des trojans
    Par astan31 dans le forum Sécurité
    Réponses: 5
    Dernier message: 03/04/2006, 17h33

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