User Tools

Site Tools


in204:tds:sujets:td7:part3

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
in204:tds:sujets:td7:part3 [2020/10/20 10:59]
bmonsuez [Question n° 2.2]
in204:tds:sujets:td7:part3 [2022/11/18 10:48] (current)
Line 1: Line 1:
-====== Partie III – Algorithmes génériques======+====== Partie III –  ​Augmenter l’expressivité des exceptions======
  
-Dans la conclusion du cours, nous affirmons qu’un intérêt du polymorphisme,​ c’est de pouvoir écrire un algorithme « générique », c’est à dire un algorithme qui pourra fonctionner pour des objets représentant des données de plusieurs types.+[[in204:​tds:​sujets:​td7|TD8]]
  
-Nous considérons un algorithme ​de tri très simple ​qui fonctionne sur des entiers ​:+Nous souhaitons créer une nouvelle classe d’exception qui dérive ​de la classe exception et qui compte le nombre de fois qu’une exception est capturée. 
 +Nous proposons que cette exception extended_exception dérive de la classe de base std::​exception et fournisse en complément ​des méthodes offertes par la classe de base les méthodes suivantes ​:
  
 <code cpp> <code cpp>
-void insertion_sort(std::vector<​int>&​ anArray)+#​include<​exception>​ 
 +... 
 + 
 +class extended_exception : public ​std::runtime_error
 { {
- for (int i = 0; i < anArray.size(); i++) +  public: 
- { +    void catched(); 
- for (int j = i + 1; j < anArray.size(); j++) +      // Est appelé chaque fois que l’on souhaite indiqué à la classe qu’elle a été 
- +      // capturée.  
- if (anArray[i] > anArray[j]) +   int getCatchNumber() const
- std::​swap(anArray[i],​ anArray[j]); +      // Retourne le nombre de fois que l’exception a été capturée. 
- +};
- } +
-}+
 </​code>​ </​code>​
  
-Cet algorithme fonctionne uniquement pour des entiers. Nous nous proposons de transformer cette fonction afin qu’elle puisse aussi bien trier des entiers mais aussi des réels ou des complexes. +===== Question ​n°1 ===== 
- +
-===== Question ​n° 1===== +
- +
-Pour ce faire, nous concevons une classe « abstraite » ayant comme nom « Base » qui expose les fonctions nécessaires à l’écriture de l’algorithme de tri.  +
- +
-Nous souhaitons utiliser l’algorithme avec la signature suivante : +
- +
-<code cpp> +
-void insertion_sort(std::​vector<​Base*>&​ anArray) +
-</​code>​+
  
-Quelles sont les méthodes virtuelles que la classe ​abstraite doit exposer ? +Proposer une implantation de cette classe
  
 <hidden Correction>​ <hidden Correction>​
  
-La classe doit exposée une méthode permettant de déterminer si un élément est plus grand que l'​autre. Il peut s'agit soit d'une méthode testant si un élément est plus grand que l'​autre : 
  
 +Nous proposons d'​ajouter un compteur qui est incrémenté à chaque fois que l'​exception a été capturée, ie. que la méthode ''​catched''​ a été appellée. Par défaut ce compteur est initialisé à zéro.
 <code cpp> <code cpp>
-class Base+#​include<​exception>​ 
 +... 
 +  
 +class extended_exception:​ public std::​runtime_error
 { {
-public:  +private: 
-    ​virtual bool isGreater(const Base&const = 0;  +    private unsigned m_catched = 0;     
-        // Retourne true si l'objet courant est plus grand. +public: 
-    ...+    ​void catched() { m_catched ++} 
 +      // Est appelé chaque fois que l’on souhaite indiqué à la classe qu’elle a été 
 +      // capturée 
 +   int getCatchNumber() const { return m_catched; } 
 +      // Retourne le nombre de fois que l’exception a été capturée.
 }; };
 </​code>​ </​code>​
  
-Nous pouvons ajouter éventuellement des méthodes complémentaires comme : +Il est nécessaire de définir les constructeurs pour cette classe ​:
 <code cpp> <code cpp>
-    virtual bool isGreaterOrEqual(const Base&) const = 0;  +class extended_exception:​ public std::​runtime_error 
-    ​virtual bool isLess(const ​Base&​) ​const = 0;  +
-    ​virtual bool isLessOrEqual(const Base&const = 0;  +... 
-    ​virtual bool isEqual(const Base&) const = 0;  +public: 
-    ​virtual bool isNotEqual(const ​Base&const = 0;  +    ​explicit extended_exception(const ​std::stringaMessage) 
-</​code>​ +        ​runtime_error(aMessage
- +    ​{} 
-Voire éventuellement une fonction ''​compareTo''​+    ​explicit extended_exception(const ​char* aMessage):  
- +        ​runtime_error(aMessage
-<code cpp> +    {} 
-    virtual int compareTo(const Base&const = 0; +...
-       // retourne -1 si l'​instance courante est plus petite que l'​instance passée en paramètre +
-       // retourne 0 si elles sont égales +
-       // retourne 1 si l'​instance courante est plus grande que l'​instance passée en paramètre.+
 </​code>​ </​code>​
  
 </​hidden>​ </​hidden>​
  
 +===== Question n°2 ===== 
  
-===== Question n° 2===== +Nous proposons ​de créer une classe exception ​''​extended_divide_by_zero'' ​qui se comporte comme la classe ​''​divide_by_zero'' ​mais qui dérive ​de la classe ​''​extended_exception''​.
- +
-==== Question n° 2.1==== +
- +
-Ajouter à la classe ​de base ''​Base'' ​une méthode purement virtuelle ​''​print()''​ qui affiche le contenu ​de la classe ​sur la console.+
  
 +Réaliser une implantation de la classe extended_divide_by_zero.
  
 <hidden Correction>​ <hidden Correction>​
  
-Il suffit d'ajouter ​la méthode suivante:+ 
 +La nouvelle classe ​''​extended_divide_by_zero''​ dérive directement de la classe ''​extended_exception''​. Ce qui nous donne le code suivant ​:
  
 <code cpp> <code cpp>
-class Base+class extended_divide_by_zero:​ public extended_exception
 { {
-    ... +public:  
-public: +    ​division_by_zero(): extended_exception("​Division by zero") 
-    ​... +    ​{} 
-    virtual void print() const = 0; +};
-     +
-}+
 </​code>​ </​code>​
 +
 </​hidden>​ </​hidden>​
  
-==== Question ​n° 2.2 ====+===== Question ​n°3 ===== 
  
-Créer une fonction ''​print(std::​vector<​Base*>​ anArray)'' ​qui prend un tableau en paramètre et affiche lensemble des éléments contenus dans le tableau sur la console.+Nous proposons de modifier la fonction ''​divide'' ​pour quelle lance non plus une exception ''​divide_by_zero''​ mais ''​extended_divide_by_zero''​.
  
 +Nous souhaitons tester cette nouvelle fonction avec le code suivant :
  
-<hidden Correction>+<code cpp> 
 +double successive_division(double i) nexcept(false)
  
-Il suffit d'​énumérer les éléments dans le tableau ou dans le containeur. +void test_succesive_division() noexcept
- +
-Nous pouvons faire une version orientée tableau qui ressemblera à cette version. +
- +
-void print(std::​vector<​Base*>​ anArray)+
 { {
-    ​std::cout << "["; + double i; 
-    int lastIndex = anArray.size()-1+ std::cout << "The numerator: ​"; 
-    ​if(lastIndex >= 0) + std::cin >> i
-    ​+ try 
-        for(int i = 0; < lastIndex; i+++ successive_division(i); 
-        +
-            ​anArray[i]->​print();  + catch (extended_division_by_zero e) 
-            std::cout << ""+ e.catched(); 
-        } + std::cout << "Division by zero occurred after "  
-        ​anArray[lastIndex]->​print() + << e.getCatchNumber() 
-    } + << " ​divisions" ​<< std::endl; 
-    std::​cout ​<< "]";+ }
 } }
  
-Si nous souhaitons être un peu plus "​C++"​ dans l'​esprit,​ nous accéderons par des itérateurs. +double successive_division(double i)  
- + noexcept(false)
-<code cpp> +
- +
-template<​typename iterator>​ +
-void print(iterator theStart, iterator theEnd)+
 { {
-    ​std::cout << "["; +  double j; 
-    if (theStart !theEnd+  ​std::cout << "Next divisor (-1 to stop sequence): ​"; 
-    +  ​std::​cin >> j; 
-        ​*theStart->​print(); +  ​if (== -1
-        ​theStart+++ return i; 
-        ​while ​(theStart != theEnd+  try 
-        + successive_division(j); 
-            ​std::​cout << ", "; + return divide(i,j)
-            *theStart->​print(); +  } 
-        +  catch(division_by_zero e
-        ​std::​cout << "​]"​+  
-    }+   throw extended_division_by_zero(); 
 +  
 +  catch (extended_division_by_zero e)  
 +  { 
 + e.catched();​ 
 + throw e
 +  }
 } }
 </​code>​ </​code>​
  
-</​hidden>​+Commentez le résultat de l’exécution.
  
-===== Question n° 3 ===== +<hidden Correction>​
- +
-===== Question n° 3.1 ==== +
- +
-Créer une classe Entier qui dérive de la classe « abstraite » ''​Base''​ et qui contient un champ ''​m_value''​ ayant comme type le type ''​int''​.+
  
-==== Question n° 3.2 ====+Si nous effectuons un appel à la fonction avec la séquence de chiffres suivante : 
 +''​20 4 4 1 0 3 6 -1'',​ nous allons avoir 5 captures de l'​exception de type ''​extended_divide_by_zero''​. Cependant, nous allons avoir comme message que l'​exception s'est produite après ''​5''​ divisions. Ce qui est conforme.
  
-Créer une fonction qui crée un tableau de ''​theNumberOfValues''​ entiers de type Entier+Ceci est effectivement logique, puisque quand nous effectuons la capture :
  
 <code cpp> <code cpp>
-std::​vector<​Base*>​ create_integer_array+  try { 
- size_t theNumberOfValues)+    successive_division(j); 
 +    ​return divide(i,j)
 +  } 
 +  catch(extended_divide_by_zero e) { 
 +    e.catched() ;  
 +    throw e;  
 +  } 
 +  ...
 </​code>​ </​code>​
-qui crée un tableau de ''​theNumberOfValues''​ valeurs commençant par la valeur ''​0''​ et se terminant à la valeur ''​theNumberOfValues-1''​. 
  
-==== Question n° 3.3 ====+l'​argument de la clause ''​catch''​ est ''​extended_divide_by_zero'',​ ce qui signifie que nous **dupliquons** l'​argument. Nous créons une copie de l'​ancienne exception qui ensuite sera détruite. Ensuite, nous augmentons la valeur du champ ''​m_catched''​ qui a été recopié. En conséquence,​ nous comptons bien le nombre de fois que l'​exception a été capturée à partir du moment où elle a été générée.
  
-Créer une fonction qui crée un tableau de ''​theNumberOfValues''​ entiers de type ''​Entier''​ dont les éléments sont des nombres aléatoires compris entre ''​theMinValue''​ et ''​theMaxValue''​. +Cependantnous pouvons éviter ​de recopier l'exception en effectuant un passage non pas par recopie ​mais par référence ​:
- +
-Cette fonction peut s’implanter comme suit.  +
-<code cpp>  +
-std::​vector<​Base*>​ create_random_integer_array( +
- size_t theNumberOfValuesint theMinValue,​ int theMaxValue) +
-+
- std::​random_device rd; +
- std::​mt19937 gen(rd());​  +
- std::​uniform_int_distribution<>​ distr(theMinValue,​ theMaxValue);​ +
- std::​vector<​Entier*>​ array(theNumberOfValues);​ +
- for (size_t i = 0; i < theNumberOfValues;​ i++) +
- array[i] = new Entier(distr(gen));​ +
- return array; +
-+
-</​code>​ +
- +
-===== Question n°4 ===== +
- +
-Modifier la fonction ​de tri ''​insertion_sort(std::​vector<​int>&​ anArray)''​ afin de ne plus travailler sur des entiers ​mais sur des objets dérivant de la classe « abstraite » ''​Base'' ​:+
  
 <code cpp> <code cpp>
-void insertion_sort(std::​vector<​Base*>​anArray)+  try { 
 +    successive_division(j); 
 +    return divide(i,​j);​ 
 +  } 
 +  catch(extended_divide_by_zeroe) { 
 +    e.catched(;  
 +    throw e;  
 +  } 
 +  ...
 </​code>​ </​code>​
  
-Tester la fonction avec le tableau d’entiers que vous avez créé à la question n°3.3.+Dans ce cas, l'​exception n'est pas recopiée et supprimée mais modifiée et ensuite propagée.
  
-===== Question n° 5 ===== +</hidden>
-Nous souhaitons étendre le code à une classe de réel. +
- +
-==== Question n° 5.1 ==== +
- +
-Ecrire une nouvelles classe ''​Reel''​ qui dérive de ''​Base''​ et qui contient un champ  ''​m_value''​ de type ''​double''​. +
- +
-==== Question n° 5.2 ==== +
- +
-Créer une fonction qui crée un tableau de ''​theNumberOfValues''​ objets de type ''​Reel''​ dont les éléments sont des nombres aléatoires compris entre ''​theMinValue''​ et ''​theMaxValue''​. +
- +
-Cette fonction peut s’implanter comme suit.  +
-  +
-<code cpp> +
-std::​vector<​Base*>​ create_random_double_array( +
- size_t theNumberOfValues,​ double theMinValue,​ double theMaxValue) +
-+
- std::​random_device rd; +
- std::​mt19937 gen(rd());​ +
- std::​uniform_real_distribution<>​ distr(theMinValue,​ theMaxValue);​ +
- std::​vector<​Base*>​ array(theNumberOfValues);​ +
- for (size_t i = 0; i < theNumberOfValues;​ i++) +
- array[i] = new Real(distr(gen));​ +
- return array; +
-+
-</code> +
- +
-Vérifier que l’algorithme de tri fonctionne aussi pour cette nouvelle nouvelle classe.+
  
in204/tds/sujets/td7/part3.1603191569.txt.gz · Last modified: 2020/10/20 10:59 by bmonsuez