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 :

Sortir d'un while qui n'est pas dans la fonction


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut Sortir d'un while qui n'est pas dans la fonction
    Bonjour, supposons un GUI avec une classe Menu.
    Cette classe Menu serais comme ci-dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Menu
    {
        private :
            std::vector<Objet*> sous_objets;
            std::vector<Evenement> evenements;
            //Ceci est un exemple simplifier et donc on ne marquera pas tout.
        public :
            void GUI_Main();
            void exit_Menu();
            //Ceci est un exemple simplifier et donc on ne marquera pas tout.
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void Menu::GUI_Main()//équivalent de GTK_main() par exemple
    {
        unsigned int i;
        while(1)
        {
            SDL_Delay(10);
            for(i=0;i<evenements.size();i++)
                evenements[i](this);
        }
    }
    Supposons, que l'on souhaite faire la fonction exit_Menu qui serait appelée depuis un des foncteurs Evenement.
    Comment la programmer ?
    L'objectif serait de faire l'équivalent de :
    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
     
    void Menu::GUI_Main()
    {
        unsigned int i;
        while(1)
        {
            SDL_Delay(10);
            for(i=0;i<evenements.size();i++)
                evenements[i](this);
        }
        end;
    }
     
    void Menu::exit_Menu()
    {
        goto end;
    }
    Quelqu'un a t-il une solution ? (Autre chose que se débrouiller pour tester la valeur de retour de evenement (qui renverait un bool))

    Ce code n'ayant pas été compilé, il se peut qu'il y ai des erreurs qui ne nous interessent pas : l'important étant la conception.

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    J'ose quand même donner ma solution qui se base sur setjmp() et longjmp().

    setjump() sauvegarde le contexte du programme appelant (la pile) et longjump() peut être appelé n'importe quand par une fonction va restaurer le contexte sauvegarder et donc reprendre le déroulement juste après le setjump().

    C'est l'équivalent d'un goto inter fonction (ce qui n'est pas possible avec un goto classique).

    La question que je me pose maintenant, comme c'est un forum c++, est ce que les destructeurs des objets seront appelés ou pas, je n'en sais rien. Il faudrait tester.

    Je pense quand même que cette solution n'est pas très propre et je ne l'utiliserai qu'en cas de force majeure.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  3. #3
    Membre chevronné

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2007
    Messages
    373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Santé

    Informations forums :
    Inscription : Juin 2007
    Messages : 373
    Par défaut
    Pour être sûr, autant utiliser une exception directement.
    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
    void Menu::GUI_Main()
    {
        unsigned int i;
        try
        {
            while(1)
            {
                SDL_Delay(10);
                for(i=0;i<evenements.size();i++)
                    evenements[i](this);
            }
        }
        catch (EndException& e)
        {
        }
    }
     
    void Menu::exit_Menu()
    {
        throw EndException();
    }
    ... mais c'est à peine mieux.
    Pourquoi ne pas utiliser tout simplement un booléen membre, du style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Menu
    {
        private :
            std::vector<Objet*> sous_objets;
            std::vector<Evenement> evenements;
            bool end;
            //Ceci est un exemple simplifiÉ et donc on ne marquera pas tout.
        public :
            void GUI_Main();
            void exit_Menu();
            //Ceci est un exemple simplifiÉ et donc on ne marquera pas tout.
    };
    ... puis :
    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
    void Menu::GUI_Main()
    {
        unsigned int i;
        while(!end)
        {
            SDL_Delay(10);
            for(i=0;i<evenements.size() && !end;i++)
                evenements[i](this);
        }
    }
     
    void Menu::exit_Menu()
    {
        end = true;
    }
    La seule différence avec le code utilisant les jumps ou les exceptions, c'est que exit_Menu() ne quitte pas immédiatement le menu. Mais peut être que tu t'en fiches ?

  4. #4
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Kalith, c'est la solution que je comptais adopter à defaut d'autres. Cependant, j'aurais préféré que le menu s'exit tout de suite et je pense que ta solution ralentit l'éxécution (comparé à un longjmp). Le temps d'éxécution est primordial pour un GUI qui va bouclé dans cette boucle plus de 50 fois par seconde.
    Ce qui fonctionnerais (mais je pense que le temps d'exécution pourrait être nettement ralentit) est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void Menu::GUI_Main()
    {
        unsigned int i;
        while(1)
        {
            SDL_Delay(10);
            for(i=0;i<evenements.size() ;i++)
                if(!evenements[i](this))
                    goto end;
        }
        end;
    }
    Dans ce cas, il n'y aurais pas besoin d'un exit_Menu();

    ram-0000, je pars étudier les longjmp.
    De plus, dans l'exemple montré (et je ne pense pas en avoir dans l'exemple réel), je n'ai pas de destructeur appelé dans la boucle while.
    Merci pour votre aide. Si quelqu'un a une autre solution que goto, longjmp,...
    L'important est tout de même la vitesse d'éxécution et non la relecture du code.

    [EDIT] J'avais oublié la méthode de l'exception. Est-ce aussi rapide qu'un longjmp ? aussi propre (vu qu'on ne l'utilise pas réellement pour une erreur) ?

  5. #5
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Je viens juste de tester longjmp (sa marche parfaitement) avec ce code :

    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
    #include <iostream>
    #include <setjmp.h>
     
    using namespace std;
    class Menu
    {
        private :
            jmp_buf end;
            //Ceci est un exemple simplifier et donc on ne marquera pas tout.
        public :
     
            void GUI_Main();
            void exit_Menu();
            //Ceci est un exemple simplifier et donc on ne marquera pas tout.
    };
     
     
    int main()
    {
        Menu menu;
        menu.GUI_Main();
        cout<<"FINI";
        return 0;
    }
     
    void Menu::exit_Menu()
    {
        longjmp(end,1);
    }
     
    void Menu::GUI_Main()
    {
        unsigned int i;
        int exit;
        exit=setjmp(end);
        while(!exit)
        {
            exit_Menu();
        }
    }
    Y a t-il plus efficace ?

    Je n'ai pas testé si les delete étés faits.

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    La variable d'état interne ou le retour sur un booléen me semble encore les approches les plus faciles à maintenir et comprendre.
    Quand à la rapidité ? Face à un Delay(10), la remonté de la pile devrait être plus rapide , non ?

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

Discussions similaires

  1. Récupérer tout ce qui n'est pas dans la base
    Par SnakeBoudoir dans le forum Requêtes
    Réponses: 2
    Dernier message: 01/11/2006, 19h18
  2. Trouver une valeur qui n'est pas dans un champ
    Par eric41 dans le forum Requêtes
    Réponses: 6
    Dernier message: 16/05/2006, 16h48
  3. [RegEx] highlight d'un mot qui n'est PAS dans un tag html.
    Par FMaz dans le forum Langage
    Réponses: 5
    Dernier message: 22/03/2006, 14h07
  4. Importer un .py qui n'est pas dans le rep courant
    Par Mr Hyde dans le forum Général Python
    Réponses: 5
    Dernier message: 25/08/2005, 17h30

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