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 :

remonter un resultat à differents niveaux d'appel


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    70
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 70
    Par défaut remonter un resultat à differents niveaux d'appel
    J'un probleme tout simple, j'ai une fonction A qui appelle plusieurs fois B qui appelle plusieurs fois C qui appelle plusieurs fois D qui appelle plusieurs fois E. Chacune des fonctions fait un peu la meme chose, cad qu'elles cherchent une solution au probleme sauf que chacune le fait de maniere differente et eventuellement d'apres les resultats de la fonction appelante.

    Voila mon probleme. Chaque fonction retourne le statut de la recherche, j'ai rien trouve on continue, j'ai trouve c'est fini ou je sais qu'on ne peut rien trouver.

    Voila mon probleme, a chaque appel de fonction a l'interieur d'une fonction je me retrouve a stocker le statut de la fonction appelée, puis a faire 3 ifs pour savoir si je continue ou si je remonte le statut (trouve, impossible) a la fonction plus haut. Bref en faisant cela, j'ai sur mes 100 lignes de codes 30 lignes de if et de return. Je trouve cela pas beau.

    En c++ le plus simple aurait ete de lever une exception pour remonter direcement du fond d'une fonction jusqu'a la principale. Mais c'est un peu trash quand meme.

    J'ai la solution de ne faire qu'une fonction de 70 lignes... que c'est moche, mais ca resoudrait le probleme.

    Je ne vois pas trop comment s'en sortir avec des variables globales.
    Le plus simple mais encore peu propre a mon gout serait d'ecrire une macro qui balance les 3 ifs et les returns autours de chaque appel...

    Y aurait il une solution elegante a mon probleme ?

    dans tous les cas, le resultats (trouvé, impossible de trouver) doit etre remonté a la meme fonction, celle qui a lancé la recherche

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 35
    Par défaut
    Je ne sais pas si c'est très élégant, mais a priori tu peux compacter la solution.
    "continue" correspond au fait que la fonction f retourne "j'ai rien trouve on continue". Dans les deux autre cas, il faut passer la reponse à la fonction du dessus...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int reponse;
    do{ reponse=f();}
    while(reponse==continue);
    return reponse;

  3. #3
    Expert confirmé

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Par défaut
    Citation Envoyé par Nemehy
    Je ne sais pas si c'est très élégant, mais a priori tu peux compacter la solution.
    "continue" correspond au fait que la fonction f retourne "j'ai rien trouve on continue". Dans les deux autre cas, il faut passer la reponse à la fonction du dessus...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int reponse;
    do{ reponse=f();}
    while(reponse==continue);
    return reponse;
    Attention au code que tu écris. "continue" est un mot clé du C, tu ne peux pas l'utiliser comme tu le fais. Ce n'est qu'un exemple, certes, mais il vaut mieux l'éviter.

    Jc

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 35
    Par défaut
    oups C'est vrai, j'ai pas fait gaffe sur le coup !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int reponse;
    do{ reponse=f();}
    while(reponse==cherche_encore);
    return reponse;
    C'est mieux comme ça

  5. #5
    Expert confirmé

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Par défaut
    Citation Envoyé par Nemehy
    oups C'est vrai, j'ai pas fait gaffe sur le coup !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int reponse;
    do{ reponse=f();}
    while(reponse==cherche_encore);
    return reponse;
    C'est mieux comme ça
    Oui!

    Maintenant je vais répondre à la question de base... Tu dis:

    puis a faire 3 ifs pour savoir si je continue
    Est-ce qu'on pourrait voir les 3 if que tu fais?

    Jc

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    70
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 70
    Par défaut
    oui c'est vrai je n'avais pas pensé a cela, mais ca ne marche que s'il y a une fonction a appeler et j'en ai plusieurs...

    j'ai 3 cas de reponses, le 1 (trouve, c'est fini, on remonte) le 2 (on a trouvé que c'etait pas possible, c'est fini, on remonte) le 3 ou 4 (faire le truc de 3 uo le truc de 4)

    donc je fais

    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
     
    fnt1(données A)
    { 
      for (i = 0 ; i < n ; i++)
     {
      t=Appel1(A)
      if ( (t == cas 1) || ( t== cas2) ) return t;
      if ( t == cas3) modif3(A); 
      else               modif4(A);
     
      t=Appel2(A)
      if ( (t == cas 1) || ( t== cas2) ) return t;
      if ( t == cas3) modif3(A); 
      else               modif4(A);
      }
    }
    vous me direz, ya des ifs qui sont inevitables...
    disons que si j'avais pu ecrire juste :
    if ( Appel1(A) == cas3 ) modif3(A) else modif4(A)
    ca aurait été 2 fois plus lisibles...

    bien sur appel1 et appel2 ont aussi la meme tete...

  7. #7
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    C'est tout de meme un algorithme etrange. Le plus bizarre est certainement la boucle for exterieure. En gros, elle dit que si les fonctions appel1, appel2, appel3, etc. n'ont ni reussi ni echoue une premiere fois, alors les modifications faites apres chaque appel meritent qu'on re-essaie un coup! Pour la tracabilite des traitements appliques aux donnees, ca doit etre coton...

    La solution avec les suites de if est tres acceptable. Tu pourrais aussi modifier les fonctions appel* pour prendre un nouveau parametre, le numero de l'appel. Si celui-ci vaut 1, alors on appele le premier traitement, etc.
    Ce qui donne:
    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
     
    int appel(data *A, int n_appel)
    {
       switch (n_appel)
       {
          case 1:
             /* first process (or call to first processing function) */
            break;      
          case 2:
             /* second process (or call to second processing function) */
            break;
          ...
          default:
            /* no such process -> error */
       }
       return t;
    }
    Ce qui s'utiliserait comme suit:
    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
     
    for (i = 0; i < n; i++)
    {
      n_appel = 1;
      done = 0;
      do
      {
        t = appel(A, n_appel);
        switch (t)
        {
          case cas1:
          case cas2:
              done = 1;
              break;
          case cas3:
             modif3(A);
             break;
          case cas4:
             modif4(A);
             break;
        }
        n_appel++;
     } while(!done && n_appel <= 5);
     if (done)
     {
       /* no need to continue looping on i */
       break;
     }
    } /* for i */
    Si, pour une raison inconnue, on ne peut pas modifier le prototype des fonctions appel*, alors il y a une solution. Mais c'est du C avance et il faut s'accrocher aux branches.
    L'idee est d'utiliser un tableau de pointeurs de fonctions. Cela est facile car les fonctions appel* partagent le meme prototype.
    Par exemple:
    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
     
    /*
     * prototypes of functions appel*
     */
    int appel1(data *A);
    int appel2(data *A);
    int appel3(data *A);
    int appel4(data *A);
    int appel5(data *A);
     
    ...
     
    /*
     * array of function pointers
     */
    int (*fp[5])(data *A) = { NULL };
     
    /*
     * initialise array
     */
    fp[0] = appel1;
    fp[1] = appel2;
    fp[2] = appel3;
    fp[3] = appel4;
    fp[4] = appel5;
     
    for (i = 0; i < n; i++)
    {
      n_fp = 0;
      done = 0;
      do
      {
        t = fp[n_fp](A);
        switch (t)
        {
          case cas1:
          case cas2:
              done = 1;
              break;
          case cas3:
             modif3(A);
             break;
          case cas4:
             modif4(A);
             break;
        }
       n_fp++;
     } while(!done && n_fp < 5);
     if (done)
     {
       /* no need to continue looping on i */
       break;
     }
    } /* for i */
    Si t'aimes pas le break qui fait sortir de la boucle i, tu peux la remplacer par une do while(!done).

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    70
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 70
    Par défaut
    le for exterieur n'est pas etrange
    car il y a bcp de traitements complementaires
    entre chaque appel, j'ai viré pour simplifier.

    interessant l'idée des pointeurs, mais apres
    j'ai d'autres fonctions qui s'ecrivent de la meme maniere
    donc il faudra que je retappe la meme fonction appel pour
    mettre a jour le tableau de pointeurs...

    ca me prend la tete, en fait ce qu'il me faudrait tout betement
    c'est une factorisation de ce code if/return qui se ferait tout
    betement par une macro... mon dieu j'ai honte

    je n'arrive pas a faire d'equivalent en utilisant le langage. Il me faudrait un return qui remonte de deux niveaux, la oui

    fnt

  9. #9
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    Utiliser un tableau de pointeurs de fonctions peut etre extraordinairement puissant, puisqu'on gagne toute la facilite d'un tableau (on peut choisir un indice, boucler sur des indices, re-organiser l'ordre des elements). Mais adapter une telle approche a ton probleme peut demander un certain travail.

    Comme le sequencement de ton algorithme a l'air complexe, en supposant que les specifications ont ete bien faites, je resterais sur ton systeme actuel de tests avec un fort niveau d'imbrication. Mais c'est lourd a coder et difficile a maintenir.

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    70
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 70
    Par défaut
    je crains que tu ais raison

Discussions similaires

  1. Réponses: 7
    Dernier message: 11/07/2007, 20h10
  2. Réponses: 2
    Dernier message: 26/09/2006, 10h46
  3. Réponses: 1
    Dernier message: 12/06/2006, 16h56
  4. Réponses: 12
    Dernier message: 10/06/2006, 19h06
  5. [FLASH 8] 2 codes semblables mais resultats differents !?
    Par kubito dans le forum ActionScript 1 & ActionScript 2
    Réponses: 2
    Dernier message: 14/04/2006, 16h17

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