Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 12 sur 12
  1. #1
    Invité de passage
    Homme Profil pro Nicolas
    Étudiant
    Inscrit en
    décembre 2012
    Messages
    2
    Détails du profil
    Informations personnelles :
    Nom : Homme Nicolas
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : décembre 2012
    Messages : 2
    Points : 0
    Points
    0

    Par défaut Probleme try, catch, throw

    Bonjour,

    je suis débutant en c++ et j'ai du mal avec les exeptions. Je comprend le principe par contre je ne sais pas du tout comment l'intégrer à mon proramme de recherche dichotomique.
    Ici j'en ai besoins pour gérer une entrée incohérente : une borne de recherche supérieur à la taille du tableau d'entier ou inférieur à 0.

    J'espere que quelqu'un pourra m'éclairer un peu
    Fichiers attachés Fichiers attachés

  2. #2
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    février 2012
    Messages
    574
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : Autre

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2012
    Messages : 574
    Points : 1 347
    Points
    1 347

    Par défaut

    Bonjour

    Lorsque tu throw ton exception dans la fonction rechercheDichotomique, il faut en construire une.
    Le constructeur de std::out_of_range prend une chaîne de caractère.
    http://www.cplusplus.com/reference/s.../out_of_range/

    Voici un exemple (modifié) issu de la FAQ
    http://cpp.developpez.com/faq/cpp/?page=exceptions
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <iostream>
    #include <stdexcept>
     
    int main()
    {
        try
        {
            throw std::logic_error("Exemple d'exception");
        }
        catch (std::logic_error const & e)
        {
            std::cerr << e.what() << std::endl; // Affiche "Exemple d'exception"
        }
    }
    Pour la vérification avec 0, tu peux t'en passer si tu utilises un unsigned int ou un std::size_t au lieu de int pour la taille de ton tableau et tes indices.

    Il est important de préciser que ton code est à vocation pédagogique ou dans le cadre scolaire pour ne pas avoir de messages du genre «utilise std::vector et std::sort»

    Il faut aussi que tu détailles mieux l'erreur rencontrée et qu'elle est la partie qui te pose réellement problème.
    [Tu peux aussi utiliser la balise [CODE] pour insérer du code dans le message. Je trouve ça plus pratique que le fichier.]

  3. #3
    Invité de passage
    Homme Profil pro Nicolas
    Étudiant
    Inscrit en
    décembre 2012
    Messages
    2
    Détails du profil
    Informations personnelles :
    Nom : Homme Nicolas
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : décembre 2012
    Messages : 2
    Points : 0
    Points
    0

    Par défaut

    Merci pour les conseils, les forum sont nouveaux pour moi.

    J'ai résolu mon probleme, en faite je n'ai pas encore assez avancé dans mes cours pour comprendre les classe d'exeptions ( le code concerne un TP bonus ).

    Ducoup j'ai réussi de cette manière :
    Programme principal:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
     try
              {
                 cout<<"Entrer la borne maximal de recherche\n";
                 cin>> n;
                 cout<<"Entrer le nombre rechercher\n";
                 cin>> x;
                rechercheDichotomique (tab, x, n, rg, trouv);
     
              }
              catch (int n)
              {
                   cout<<n<<" est une borne [! \n";
                   trouv = false;
                   e = true;
              }
    procédure
    Code :
    1
    2
    3
    4
    5
     
    if (n<0 || n>MAX)
            {
               throw n; // levée d'exeption          
            }
    Est-ce correct ?

  4. #4
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    février 2012
    Messages
    574
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : Autre

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2012
    Messages : 574
    Points : 1 347
    Points
    1 347

    Par défaut

    (Bienvenue à toi alors )

    Oui, cela est correct (dans le cadre scolaire) (syntaxiquement).

    À toi de faire des tests/jeux d'essais pour voir si l'exception est bien levé avec des n invalides et que le calcul est bien fait dans les cas valides.

    Pour aller plus loin:
    Tu peux remplacer ton int par un std::out_of_range.
    Sauf qu'au lieu de throw n tu throw std::out_of_range("Description de l'exception") et tu catch un std::out_of_range & au lieu du int.
    (Tu peux aussi utiliser un std::string si tu les as vu et que std::out_of_range te perturbe.)

    Utilise plutôt std::cout << "texte" << std::endl; plutôt que "\n";

    Si le problème est résolu, il faut le noter résolu

  5. #5
    Expert Confirmé Sénior

    Homme Profil pro Pierre
    Ingénieur développement logiciels
    Inscrit en
    juin 2007
    Messages
    2 182
    Détails du profil
    Informations personnelles :
    Nom : Homme Pierre
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : juin 2007
    Messages : 2 182
    Points : 5 060
    Points
    5 060

    Par défaut

    Bonjour,
    j'en profite pour indiquer que std::out_of_range est définie (avec d'autres exceptions) dans <stdexcept>

    au final, la capture d'une exception devrait se faire via une référence constante, pour ne pas la copier, et ne pas perdre le polymorphisme (parce que certaines exception hérite d'une autre)

    le code devient alors:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    #include <iostream>
    #include <stdexcept>
     
    void lanceur(){
        throw std::out_of_range("from lanceur");
    }
     
    int main() {
        //ceci fonctionne bien sûr
        try {
            lanceur();
        } catch (const std::out_of_range& e) {
            std::cerr<<"out_of_range "<< (e.what()) << std::endl;
        }
        //mais ceci aussi, parce que out_of_range hérite de logic_error (donc "est une" logic_error)
        try {
            lanceur();
        } catch (const std::logic_error& e) {
            std::cerr<<"logic_error"<< (e.what()) << std::endl;
        }
    }
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • La plus sotte des questions est celle qu'on ne pose pas.

    Pour faire des graphes, essayez yEd.

  6. #6
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    février 2012
    Messages
    574
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : Autre

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2012
    Messages : 574
    Points : 1 347
    Points
    1 347

    Par défaut

    Citation Envoyé par leternel Voir le message
    au final, la capture d'une exception devrait se faire via une référence constante, pour ne pas la copier, et ne pas perdre le polymorphisme (parce que certaines exception hérite d'une autre)
    Petit HS au passage:
    Lorsque j'aurais plus de temps je voulais voir si on peut expliquer ce code proprement et le mettre dans la FAQ (si ce n'est pas déjà fait)
    Code :
    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
    // g++ -Wall -Wextra stdexcept.cpp -o stdexcept && stdexcept
     
    #include <iostream>
    #include <stdexcept>
     
    // template <class Except>
    // void throw_except(Except const & e) { throw e; }
     
    void throw_except(std::exception const & e) { throw e; }
    //void throw_except(std::logic_error const & e) { throw e; }
     
    int main()
    {
     
    	try
    	{
    		throw std::logic_error("Description of exception");
    	}
    	catch (std::exception const & e)
    	{
    		std::cout << e.what() << std::endl;
    	}
     
    	try
    	{
    		throw_except(std::logic_error("Description of exception"));
    	}
    	catch (std::exception const & e)
    	{
    		std::cout << e.what() << std::endl;
    	}
     
    	return 0;
    }
    Contrairement à ce qu'on pourrait penser, l'affichage est:
    Code :
    1
    2
    Description of exception
    std::exception
    On pert le polymorphisme alors qu'on a manipulé (a première vue en tout cas) que des const &...
    Pour avoir le comportement voulu, on doit surcharger les fonctions avec le type voulu. (On peut utiliser la programmation générique avec les templates.)

    Bref, je ferais les vérifications nécessaires et posterais un petit message à ce sujet si besoin.

  7. #7
    Expert Confirmé Sénior

    Homme Profil pro Pierre
    Ingénieur développement logiciels
    Inscrit en
    juin 2007
    Messages
    2 182
    Détails du profil
    Informations personnelles :
    Nom : Homme Pierre
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : juin 2007
    Messages : 2 182
    Points : 5 060
    Points
    5 060

    Par défaut

    En effet, bonne question.

    Ta version non template est équivalente à l'appel explicite de la template throw_except<std::exception>(std::logic_error("Description of exception"));Mais pourquoi, je n'en sais rien.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • La plus sotte des questions est celle qu'on ne pose pas.

    Pour faire des graphes, essayez yEd.

  8. #8
    Expert Confirmé Sénior

    Avatar de germinolegrand
    Homme Profil pro Germino Legrand
    Développeur de jeux vidéo
    Inscrit en
    octobre 2010
    Messages
    731
    Détails du profil
    Informations personnelles :
    Nom : Homme Germino Legrand
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : octobre 2010
    Messages : 731
    Points : 4 115
    Points
    4 115

    Par défaut

    @Ehonn: en fait il n'y a aucun intérêt à ce code, passer une exception en paramètre d'une fonction pour qu'elle la lance n'a tout simplement aucun sens... On perd la simplicité du throw (sans parler de la perte de polymorphisme que je trouve intéressante).
    Donc je doute de la possibilité de retrouver ce genre de code dans un projet...

    Par contre je m'étonne que personne ne rajoute catch(...) après le dernier bloc catch d'un try... alors que ça fournit un système très simple et puissant de gestion des erreurs... et une belle exploitation du RAII
    Choisis un travail que tu aimes et tu n'auras pas à travailler un seul jour de ta vie.

    N'oubliez pas de marquer votre sujet comme et de mettre des aux messages apportant un plus à votre discussion.

    Si vous souhaitez participer à la rubrique C++, ne me contactez plus !

  9. #9
    Expert Confirmé Sénior

    Homme Profil pro Pierre
    Ingénieur développement logiciels
    Inscrit en
    juin 2007
    Messages
    2 182
    Détails du profil
    Informations personnelles :
    Nom : Homme Pierre
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : juin 2007
    Messages : 2 182
    Points : 5 060
    Points
    5 060

    Par défaut

    catch(...) n'est pas l'application du RAII, c'est l'attrapage de toute exception.

    RAII repose sur l'exploitation du contraire.
    En effet, le principe se résumerait à "la ressource est manipulable aussi longtemps que la variable existe, ni plus ni moins."

    toute sortie de scope (paire d'accolade, normalement) provoque la destruction des variables locales qu'il contient.
    Les constructeurs lance des exceptions pour empecher l'utilisation de ressource qui n'ont pas pu être acquises, et les destructeurs libère la dite ressource.

    catch(…) bloque la remontée des exceptions.


    PS: pour les plus débutant, je rappelle que n'importe quoi peut-être levé via throw.
    Le compilateur ne vous empechera d'utiliser throw printf; bien que le type de printf soit un truc aussi barbare que (int)(*)(const char*, …). Par contre, c'est du suicide professionnel.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • La plus sotte des questions est celle qu'on ne pose pas.

    Pour faire des graphes, essayez yEd.

  10. #10
    Expert Confirmé Sénior

    Avatar de germinolegrand
    Homme Profil pro Germino Legrand
    Développeur de jeux vidéo
    Inscrit en
    octobre 2010
    Messages
    731
    Détails du profil
    Informations personnelles :
    Nom : Homme Germino Legrand
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : octobre 2010
    Messages : 731
    Points : 4 115
    Points
    4 115

    Par défaut

    Oups, dit une bêtise, seulement dans les fonctions d'entrée (main, fonction threadée, etc.). Pour moi une exception ne doit pas faire planter le programme (faut utiliser assert pour ça). Elle doit plutôt remettre le programme dans un état stable. Donc un catch(...) dans le main peut aider à signaler l'erreur à l'utilisateur (ouverture d'une fenêtre pop-up, etc.). Oubliez ce que j'ai dit sur le RAII, rien à voir

    (moi ce que je mets dans un catch(...) ailleurs que dans ces fonctions là se résume souvent à un throw)
    Choisis un travail que tu aimes et tu n'auras pas à travailler un seul jour de ta vie.

    N'oubliez pas de marquer votre sujet comme et de mettre des aux messages apportant un plus à votre discussion.

    Si vous souhaitez participer à la rubrique C++, ne me contactez plus !

  11. #11
    Expert Confirmé Avatar de Flob90
    Homme Profil pro Florian Blanchet
    Etudiant en Optique
    Inscrit en
    août 2004
    Messages
    1 321
    Détails du profil
    Informations personnelles :
    Nom : Homme Florian Blanchet
    Âge : 24
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Etudiant en Optique

    Informations forums :
    Inscription : août 2004
    Messages : 1 321
    Points : 2 925
    Points
    2 925

    Par défaut

    Comment tu arrives à remettre le programme dans un état valide avec un catch(...) ?

    En général la présence d'un catch(...) masque le fait que le développeur ne sait pas comment remettre le programme dans un état valide. Si le programme ne peut pas être remis dans un état valide, pourquoi ne pas le laisser planter ?

    Sans catch(...) il pourra y avoir un core-dump qui donnera toutes les informations voulues aux développeur pour comprendre l'état du programme .
    "We can solve any problem by introducing an extra level of indirection" Butler Lampson

    "N'importe quel problème peut être résolu en introduisant un niveau d'indirection supplémentaire" Butler Lampson (traduction libre)

  12. #12
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    février 2012
    Messages
    574
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : Autre

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2012
    Messages : 574
    Points : 1 347
    Points
    1 347

    Par défaut

    Citation Envoyé par germinolegrand Voir le message
    @Ehonn: en fait il n'y a aucun intérêt à ce code, passer une exception en paramètre d'une fonction pour qu'elle la lance n'a tout simplement aucun sens... On perd la simplicité du throw (sans parler de la perte de polymorphisme que je trouve intéressante).
    Donc je doute de la possibilité de retrouver ce genre de code dans un projet...
    Il s'agit d'un exemple minimal reproduisant "l'erreur"...
    assert qui vient de la bibliothèque C, est une macro et ne permet pas de lancer d'exception, elle fait un abort (je ne pense pas que la mémoire et les ressources soit correctement libérées par le programme lui même mais peu importe).
    Même pour un assert, il est légitime de vouloir throw une exception. Il est aussi légitime de vouloir activer ces assertions seulement si NDEBUG n'est pas défini par exemple. On peut aussi afficher un message dans un certain style (en rouge par exemple).
    Pour éviter de copier-coller ces lignes, on peut factoriser ce code (pour le NDEBUG c'est une mauvaise idée car un appel de fonction vide peut quand même tuer les performances avec g++ 4.7 en -O3 !).

    Citation Envoyé par germinolegrand Voir le message
    [...] seulement dans les fonctions d'entrée (main, fonction threadée, etc.). Pour moi une exception ne doit pas faire planter le programme (faut utiliser assert pour ça).
    Pour un programme plus ou moins personnel, l'affichage et la fin dû à std::bad_alloc me convient très bien

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •