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 :

Relancer une exception dans un bloc « catch »


Sujet :

C++

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2013
    Messages : 25
    Points : 17
    Points
    17
    Par défaut Relancer une exception dans un bloc « catch »
    Salut à tous,

    J'aimerais pouvoir relancer une exception pour réitérer une saisie dans un bloc catch (je ne sais pas si c'est possible mais ça me faciliterais grandement la tâche).
    Ci-dessous la fonction dans laquelle j'aimerais relancer l'exception pour réitérer la saisie.

    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
    istream& operator>> (istream& flux, Timing &P)
    {
    	char pause = 0;
    	char *J = new char[50];
    	Temps Heure;
    	Temps Duree;
     
    	cout << "Jour: ";
    	flux >> J;
     
     
    	try
    	{
    		P.setJour(J);
    	}
    	catch(InvalidJourException const &i)
    	{
    		do
    		{
    			cout << "Jour: ";
    			flux >> J;
    			if(strcmp(J, "Lundi") != 0 && strcmp(J, "Mardi") != 0 && strcmp(J, "Mercredi") != 0 && strcmp(J, "Jeudi") != 0 && strcmp(J, "Vendredi") != 0 && strcmp(J, "Samedi") != 0 && strcmp(J, "Dimanche") != 0)
    				cout << "Saisie invalide" << endl;
    		} while(strcmp(J, "Lundi") != 0 && strcmp(J, "Mardi") != 0 && strcmp(J, "Mercredi") != 0 && strcmp(J, "Jeudi") != 0 && strcmp(J, "Vendredi") != 0 && strcmp(J, "Samedi") != 0 && strcmp(J, "Dimanche") != 0);
    		P.setJour(J);
    	}
     
    	try
    	{
    		flux >> Heure;
    		flux >> Duree;
    	}
    	catch(InvalidTempsException const &t)
    	{
    		flux >> Heure;
    		flux >> Duree;
    	}
    	P.setHeure(Heure);
    	P.setDuree(Duree);
     
     
    	return flux;
    }
    (le deuxième catch)

    Ci-dessous, la fonction qui lance l'exception en cas d'erreur de saisie..

    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
    istream& operator>> (istream& flux, Temps &t)
    {
    	int h,m;
     
    	cout << "Heure: ";
    	flux >> h;
    	if(h > 23)
    		throw InvalidTempsException("Saisie Invalide");
     
    	cout << "Minute: ";
    	flux >> m;
    	if(m > 59)
    		throw InvalidTempsException("Saisie Invalide");
     
    	t.setHeure(h);
    	t.setMinute(m);
     
    	return flux;
    }
    J'aimerais donc que dans le catch je puisse faire une sorte de boucle qui relancerais l'exception et qui me permettrais de saisir à nouveau mes valeurs pour ne pas devoir refaire mes conditions dans le catch.
    J'espère avoir été assez clair et que quelqu'un pourra m'aider.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Si je ne me trompe c'est l'instruction throw;
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Bonjour,

    throw; permet de relancer l'exception courante, cela prolonge un défaut, ça n'est pas fait pour le corriger. Ton besoin est autre.
    S'il y a eu une erreur provoquant une exception, il faut réitérer plutôt que relancer l'exception
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    do {
       bool ok = false;
       try {
          ... action pouvant provoquer une exception ...
          ok = true;
       }
       catch ( std::exception const& e ) {
          ... signal de l'anomalie ...
       }
    } while ( !ok );

  4. #4
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    throw; relance l'exception, mais ne fait pas de boucle qui est le rôle... d'une boucle \o/.

    Concernant le code en lui-même:

    - dangereux: lecture d'une c-string sans préciser la taille -> buffer overflow
    - fuis: pas de désallocation de l'objet alloué.
    - faux: facile de faire une boucle infinie tellement la vérification est mal foutue: Comment vérifier les valeurs saisies avec cin ?
    - en dehors de la philosophie d'utilisation des flux: usuellement, quand la lecture échoue, le flux passe dans un état invalide est s'arrête.
    - en fait trop: c'est une fonction de lecture, pas une fonction pour afficher du texte.

    Je te conseille:

    - d'utiliser istream::setstate avec failbit pour les erreurs de formatage et non des exceptions.
    - de remplacer la c-string par std::string.
    - de ne faire que du parsing et pas un mélange "interactive".

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2013
    Messages : 25
    Points : 17
    Points
    17
    Par défaut
    Salut Jo_link_noir,

    C'est une application pour l'école,
    Au niveau de la sécurité, ce n'est pas important , c'est une gestion d'horaire, je ne suis pas évaluer sur ce point.
    Pour la désallocation, si tu parles des objets temps, elle est faite lors de la sortie de la fonction par le destructeur non ?
    Pour le c-string, on nous oblige à l'utiliser, ce n'est pas un choix si non il se porterais bien sur sur le std::string (C'est un examen de repêchage et lors de ce cours les std::string n'avaient pas encore été vus.. d'où l'obligation).
    Que veux-tu dire par parsing ?
    Je pense que je vais juste annuler la saisie lors d'une saisie invalide plus tôt que de la réitérer, qu'en penses tu ?

    Bàv.

  6. #6
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Ton problème est que tu utilises une exception dans une situation où ce n'est pas approprié. Tu veux faire une boucle jusqu'à ce que l’utilisateur ait entré des valeurs correctes ? Et bien, fait simplement une boucle jusqu'à ce que l'utilisateur ait entré des valeurs correctes.
    Le but d'une exception est de propager l'information d'une erreur entre le point où celle-ci est détectée et le point où l'on peut la traiter, quand ces deux points sont éloignés. Ce qui n'est pas le cas ici.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  7. #7
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2013
    Messages : 25
    Points : 17
    Points
    17
    Par défaut
    Salut JolyLoic,

    C'est une application pour l'école, il est demandé de lever une exception lors de la saisie d'un jour non conforme, je n'ai pas choisi de le faire ainsi.

    Je viens de me rendre compte que la réponse avait été apportée plus haut par dalfab.

    Merci à vous pour vos réponses.

  8. #8
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2013
    Messages : 25
    Points : 17
    Points
    17
    Par défaut
    Re tout le monde,

    J'ai testé la façon de faire de dalfab, tout d'abord, j'ai appris une chose que je ne savais pas c'est que lorsqu'une exception est levée, les destructeurs des objets ou autres présents dans le try sont appelés.
    Il me reste quand même un petit problème, lorsque l'exception est levée pour les heures, un message du type "terminate called after throwing an instance of 'InvalidTempsException' Abandon (core dumped)" s'affiche, comme si je ne récupérais pas l'exception... Je ne comprends pas..

    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
    istream& operator>> (istream& flux, Timing &P)
    {
    	char pause = 0;
    	char *J = NULL;
    	Temps Duree;
    	bool ok;
    	Temps Heure;
     
    	do
    	{
    		J = new char[50];
    		ok = false;
    		cout << "Jour: ";
    		flux >> J;
    		try
    		{
    			P.setJour(J);
    			ok = true;
    		}
    		catch(InvalidJourException const &J)
    		{
    			cout << J.Message_Jour() << endl;
    		}
     
    	}while(!ok);
     
     
    	do
    	{
    		ok = false;
    		cout << "Heure" << endl;
    		flux >> Heure;
    		try
    		{
    			P.setHeure(Heure);
    			ok = true;
     
    		}
    		catch(InvalidTempsException const &T)
    		{
    			cout << T.Message_Temp() << endl;
    		}
     
    	}while(!ok);
     
    	do
    	{
    		ok = false;
    		cout << "Durée" << endl;
    		flux >> Duree;
    		try
    		{
    			P.setDuree(Duree);
    			ok = true;
     
    		}
    		catch(InvalidTempsException const &T)
    		{
    			cout << T.Message_Temp() << endl;
    		}
     
    	}while(!ok);
     
    	return flux;
    }
    Je mets ici en plus le chemin que fait le P.setHeure(Heure) là où l'exception est levée.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void Timing::setHeure(const Temps &H)
    {
    	//cout << "setHeure Timing" << endl;
    	Heure.setHeure(H.getHeure());
    	Heure.setMinute(H.getMinute());
    }
    ensuite,
    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 Temps::setHeure(const int heure)
    {
    	//cout << "SetHeure Temps" << endl;
    	if(heure > 23)
    		throw InvalidTempsException();
    	else
    		Heure = heure;
    }
     
    void Temps::setMinute(const int minute)
    {
    	//cout << "SetMinute Temps" << endl;
    	if(minute > 59)
    		throw InvalidTempsException();
    	else
    		Minute = minute;
    }
    petite précision en plus, mes messages sont directement créés dans mon constructeur par défaut, je n'ai qu'un type d'erreur dans ces exceptions donc pas besoin de le passer en paramètre à chaque fois.
    Est ce qu'une exception ne peut remonter plus qu'une fonction ? Je ne vois que ça car pour les jours ça fonctionne..

    J'espère que vous saurez m'aider, merci !

  9. #9
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Bonjour,

    Il semble que tu peux produire une exception dans ton opérateur>>, quand tu écris
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        flux >> Heure;
        try
        {
            P.setHeure(Heure);
            ok = true;
         }
        catch(InvalidTempsException const &T) { ...
    Si l'exception se produit dans l'opérateur>> elle ne sera pas catchée, essaie de placer la lecture du flux à l'interieur du try.

  10. #10
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2013
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2013
    Messages : 25
    Points : 17
    Points
    17
    Par défaut
    Bonjour,

    Merci Dalfab, effectivement ça fonctionne !

    Comme quoi mieux vaut ne pas coder à 4h du matin, la concentration n'est pas des meilleur...

    Merci à tous.

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

Discussions similaires

  1. lever une EXCEPTION pour 2 blocs séparés
    Par atruong dans le forum Oracle
    Réponses: 2
    Dernier message: 05/05/2006, 10h27
  2. Utilisation d'une variable dans un bloc pl/sql
    Par paris2000fr dans le forum PL/SQL
    Réponses: 2
    Dernier message: 29/03/2006, 14h08
  3. inclure une image dans un bloc de texte
    Par allowen dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 25/08/2005, 14h11
  4. Réponses: 2
    Dernier message: 28/08/2003, 00h00

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