Choisissez votre style : colorisé, impression

Série 16 :
Gestion des exceptions et divers compléments

Buts

Cette série a pour but de vous faire réviser les notions vues au semestre passé et vous faire pratiquer la notion de gestion des exception, d'espace de nommage et d'arguments du main

Préliminaires :

Avant d'effectuer les manipulations décrites dans cette série, créez le répertoire ~/Desktop/myfiles/Programmation/cpp/serie16  (i.e. créez le sous-répertoire serie16  dans le répertoire ~/Desktop/myfiles/Programmation/cpp).

Exercice 0 : Gestion des exceptions ( niveau 0) 

Cet exercice est aussi détaillé à la page 175 de l'ouvrage C++ par la pratique.

Le but de cet exercice est de reprendre l'exemple du cours illustrant la gestion des exceptions.

Cliquez ici si vous souhaitez faire cet exercice. 


Exercice 1 : Dépassement de bornes (exceptions , niveau 1)

Le programme suivant est erroné car il accède au contenu du tableau v en dehors des bornes licites :

#include <vector>
#include <iostream>
using namespace std;

int acces(const vector<int>& vect, size_t i);

int main()
{
	vector<int> v({1, 2, 3, 4, 5, 6, 7, 8 });

	cout << acces(v, 2) << endl;
	cout << acces(v, 200) << endl;
	cout << acces(v, 0) << endl;
	return 0;
}

int acces(const vector<int>& vect, size_t i)
{
	return vect[i];
}

Sachant que pour un vector, vect, l'instruction vect.at(i) fait la même chose que vect[i] mais lance en plus une exception si i est en dehors des indices du tableau, modifiez ce programme pour qu'il arrête son exécution après la tentative d'accès erronée en écrivant sur le terminal Vous dépassez les bornes !

L'exécution du programme devrait ressembler à ceci :

3
Vous dépassez les bornes!

Indication: le type de l'exception lancée par at est out_of_range et on l'intercepte usuellement par la tournure

catch (const out_of_range& e)

L'inclusion de #include <stdexcept> est nécessaire pour utiliser le type out_of_range.

Quelle solution envisagez-vous pour que seules les instructions fautives provoquent l'affichage du message Vous dépassez les bornes ! et que toutes les autres s'exécutent normalement ?

L'exécution pour notre programme devrait alors plutôt être :

3
Vous dépassez les bornes!
1

Exercice 2 : Arguments de main (niveau 2)

Il s'agit dans cet exercice de compléter le programme fourni traiter_nombres.cc afin qu'il puisse calculer soit la somme soit la moyenne d'un séquence arbitraire d'entiers passé en ligne de commande.

Le programme finalisé pourra être invoqué en ligne de commande comme suit :

./traiter_nombres -m entier1 entier2 ... entiern
ou
./traiter_nombres -s entier1 entier2 ... entiern
avec l'option -m le programme affichera la moyenne de la séquence de nombres fournie en argument et avec l'option -s, sa somme.
Si vous utilisez QTCreator, vous pouvez invoquer votre programme en lui passant des paramètres en ligne de commande comme indiqué ici : https://iccsv.epfl.ch/series-prog/install/installation-tutorial.php#commandLineArgs_in_qtcreator. Ici par exemple, il faudrait saisir dans le champs indiqué, un espace suivi de l'option voulue, par example -m 1 2 3 4. Il n'est alors pas nécessaire d'avoir recours au terminal.

L'implémentation de votre programme devra obéir à certaines contraintes, décrites ci-dessous.

Espace de nommage standard

Au premier semestre, vous avez travaillé en vous plaçant systématiquement dans l'espace de nommage standard en utilisant la directive :

using namespace std;

Cette pratique peut être préjudiciable lorsque l'on travaille sur des projets (programme éclaté sur plusieurs fichiers, ce que nous commencerons à pratiquer dès la semaine prochaine).

Afin de vous habituer aux contraintes impliquées par l'abandon de cette clause, il vous est demandé de ne pas y avoir recours dans cet exercice.

Ce que cela implique est que les éléments standards devront être utilisé avec le préfixe std::. Par exemple, vous écrirez : std::string au lieu de string ou std::cout << std::endl; au lieu de cout << endl;.

Utilisation des exceptions

Des situations d'erreur peuvent se produire à différents endroits du programme (options mal écrites ou inconnues, des données qui ne correspondent pas à des entiers etc.). Votre programme devra signaler ces situations en lançant des exceptions.

C++ offre un ensemble de types correspondant à des exceptions prédéfinies et il est possible de les lancer en les assortissant d'un message.

Par exemple, il existe le type prédéfini std::invalid_argument que vous pourrez lancez comme suit:

throw std::invalid_argument("option invalide");

Le message peut bien sûr être librement choisi.

Toutes ces exceptions prédéfinies peuvent être rattrapées au moyen du type std::exception (voir le programme principal fourni). La fonctionnalité what retourne le message que l'on a assorti à l'exception au moment de son lancement.

Ainsi, si une partie de votre programme fait le lancement suivant :

throw std::invalid_argument("option inconnue");

Le programme principal fourni pourra la rattraper et affichera le message Erreur : option inconnue.

Dans cet exercice il vous est demandé de traiter les situations d'erreur en lançant des exceptions prédéfinies de C++ (décrites dans ce qui suit).

Fonctions à coder

Pour parvenir au résultat souhaité, il vous est demandé de coder les fonctions suivantes :

  1. La fonction start_with prenant en argument deux chaînes de caractères et retournant true si la première commence par la deuxième et false sinon. Par exemple, l'appel start_with("abcd", "ab") retournera true, et start_with("abcd", "-") retournera false.
  2. La fonction read_integer convertissant une chaîne de caractère en un entier. Par exemple, l'appel read_integer("123") retournera l'entier 123. Cette fonction utilisera la fonction prédéfinie stoi. Cette fonction lance une exception (que vous pourrez rattraper sous la forme d'une std::exception) si la chaîne de caractères ne peut être convertie en entier. La fonction read_integer lancera une exception de type std::runtime_error lorsque c'est le cas. Le message assorti à l'exception devra indiquer que la conversion en un entier est impossible et indiquer quel donnée n'a pas pu être convertie en entier (voir les exemples d'exécution ci-dessous).
  3. La fonction compute prenant des arguments identiques au main plus un troisième argument booléen prenant une valeur par défaut. Si la valeur de cet argument vaut true la fonction compute affichera une somme sinon une moyenne (le type de retour de la fonction compute sera void). La fonction compute doit itérer sur toutes les entrées de argv depuis la troisième pour en calculer et afficher la somme ou la moyenne. Les messages affichés par compute lorsqu'aucune exception n'est lancée seront : La somme de vos nombres est : <la_somme> ou La moyenne de vos nombres est : <la_moyenne>.
    Chaque argv[i] est une chaîne de caractère à la C. Pour la convertir en string de sorte à pouvoir utiliser la fonction read_integer, vous utiliserez la tournure suivante : std::string(argv[i]).
  4. La fonction process, conforme à l'utilisation qui en est faite dans le main fourni. Cette fonction a pour rôle de traiter les arguments du main pour voir s'ils sont en accord avec l'utilisation prévue pour le programme, et appelera la fonction compute le cas échéant. Les situations d'erreurs seront signalées par des exceptions standards (soit des std::runtime_error soit des std::invalid_argument) en les assortissant de messages appropriés (voir les exemples d'exécution ci-dessous). Vous utiliserez la fonction start_with pour tester si la formulation de l'option est correctement faite.

Exemples d'exécution

./traiter_nombres -
Erreur: Il n'y a pas suffisamment d'arguments

./traiter_nombres -s
Erreur: Il n'y a pas suffisamment d'arguments

./traiter_nombres -m 12
La moyenne de vos nombres est : 12

./traiter_nombres -s 12
La somme de vos nombres est : 12

./traiter_nombres -a 12
Erreur: option inconnue: -a

./traiter_nombres -s 12 13 w   
Erreur: conversion en entier impossible pour w

./traiter_nombres -s 1 -9 10 22 -2
La somme de vos nombres est : 22

./traiter_nombres -m 1 -9 10 22 -2
La moyenne de vos nombres est : 4.4

./traiter_nombres -moyenne 1 -9 10 22 -2
Erreur: les options possibles sont -m ou -s et non pas -moyenne


Exercice 3 : Neurone artificiel (rappels, exceptions, arguments de main, espaces de nommage niveau 1, 2 et 3)

Cet exercice exige un travail relativement important (environ 300 lignes de code à écrire). Essayez d'aller le plus loin possible d'ici au prochain TP. Si vous finalisez l'exercice, vous aurez fait une révision complète de tous les concepts importants du semestre passé et également pratiqué les nouveautés vues en cours cette semaine. Bon entraînement avant le démarrage du projet :-)

Pour accéder à l'énoncé suivez ce lien.


Dernière mise à jour : 2024/02/22 16:46