La gestion des erreurs
Problématique
Si nous reprenons une des problématiques précédentes concernant l'enregistrement des notes, on peut facilement imaginer les erreurs rencontrées par l'utilisateur
- Envoyer une note négative
- Envoyer une note supérieure à 20
- Envoyer un caractère à la place d'un nombre réel
- Ne rien envoyer (appui simplement sur Entrée)
L'objectif est de contrôler tout cela avec la syntaxe C++... tout en calculant la moyenne des notes enregistrées.
Pré-Requis
Tous les cours précédents !
Enregistrement des données
Commençons par l'enregistrement des données, il est clair qu'on ne va pas s'amuser à compter le nombre de notes à entrer, pour deux raisons:
- C'est pénible (perte de temps)
- C'est risqué (risque de ne pas avoir compté le nombre correct de notes à enregistrer)
On va donc créer une boucle infinie, qui demandera continuellement d'enregistrer une note.
Euh, oui mais, quand j'ai plus de note, comment on fait pour quitter cette boucle infinie ?
Simple, on va prévenir l'utilisateur d'un signe qui permettra de breaker (d'interrompre) cette boucle.
Dans ma problématique, plusieurs choix s'offrent à moi pour interrompre cette boucle,
- Je n'envoie rien !
- J'envoie un nombre réel non conforme (négatif, supérieur à 20)
- J'envoie autre chose qu'un nombre
Ok, pour l'instant ça va, je comprend bien la problématique, parlons C++ maintenant,
Pour créer notre boucle infinie, c'est une syntaxe assez simple
Code:
while (1){ // suite de mon code }
Code:
while (true){ // suite de mon code }
Réponse, à l'aide du mot clé break !
Code:
while (true){ // suite de mon code if (condition){ break; // interruption de ma boucle infinie } }
Ok, je vois pour ma boucle infinie, je comprend pourquoi l'utiliser, mais j'enregistre ça dans quel objet ?
Bonne question, mais vous l'aurez deviné, on a vu l'objet vector dans notre cours précédent, alors allons-y avec cet objet
Demande utilisateur
Il faut parler maintenant du type où nous allons recevoir la note.
Vous allez me dire, c'est simple ! On prend le type double
Eh bien non ! Comment faîtes vous si l'utilisateur n'entre aucune note ?
En effet cin a des effets de bord, c'est à dire que des choses imprévues peuvent se passer si la donnée attendue n'est pas conforme, il faut donc analyser (parser) la chaîne de caractères, avant d'exécuter quoi que se soit.
On utilisera donc le type string, et on pourra vérifier si c'est une chaîne vide
Code:
string line; getline(cin, line); // On demande à l'utilisateur une chaîne de caractères if (line.empty()){ // Afficher moyenne // interruption de la boucle }
Pour l'utiliser vous aurez besoin de compiler en C++11 (norme) et charger la librairie string, donc ne pas oublier
Code:
#include <string>
Code:
note = stod(line);
Si vous entrez une chaîne, par exemple "bonjour", comment va réagir cette fonction ? Très mal, je vous le dis, on va donc essayer et au cas où, faire en sorte de...
Pour notre problématique, je pense résoudre de la sorte,
Si j'ai quelque chose de non conforme, je calcule ma moyenne des notes avec toutes celles enregistrées sauf la valeur non conforme évidemment et je quitte la boucle.
Pour essayer la transformation string -> double, avec la fonction stod, on utilisera une gestion d'erreur avec la syntaxe try - catch
Elle fonctionne comme cela
Code:
try{ // Utilisation de stod } catch (const invalid_argument & ia){ // Affichage de la moyenne // On interrompt la boucle }
Attention pour invalid_argument, il faut charger la librairie stdexcept.
Code:
#include <stdexcept>
Pour afficher la moyenne, on va créer une fonction prenant en argument l'objet vector et ne renvoyant rien.
Code:
void displayMean(vector<double> notes)
Soit le tableau de notes est vide, dans ce cas on affiche "Pas de notes enregistrées".
Soit le tableau de notes n'est pas vide, dans ce cas on calcule la moyenne et on l'affiche, "La moyenne est de ".
Pour vérifier si le tableau est vide, on peut vérifier que sa taille est nulle.
Code:
if (notes.size() == 0){ // "Pas de notes enregistrées" }
Le code final à compléter pour vous guider au cas où,
Code:
#include <iostream> #include <vector> #include <string> #include <stdexcept> using namespace std; void displayMean(vector<double> notes); int main() { // déclaration de variables while (true){ // demande utilisateur avec getline // Si l'utilisateur entre rien ? try{ // Essai conversion string -> double } catch (const invalid_argument & ia){ // Essai n'est pas concluant, on fait quoi ? } // Ajout de la note dans le tableau } return 0; } void displayMean(vector<double> notes){ // vos variables // Si notes est vide ? // Sinon calculer moyenne et l'afficher }