User Tools

Site Tools


in204:tds:sujets:td6:part1

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:td6:part1 [2020/11/01 10:48]
bmonsuez
in204:tds:sujets:td6:part1 [2022/11/18 10:49] (current)
Line 1: Line 1:
-====== Partie I – Manipulation ​des Exceptions======+====== Partie I – Définitions ​des exigences ​======
  
 [[in204:​tds:​sujets:​td6|TD6]] [[in204:​tds:​sujets:​td6|TD6]]
  
-===== Question n°1 : Gestion simple des exceptions en C++ ===== 
  
-==== Question n°1.1 ==== +===== Question n°1=====
  
-Implanter le code suivant dans un nouveau ​projet. ​+Créer ​un projet ​dans lequel vous intégrez le fichier "​simple_sort.hpp" qui contient la fonction de comparaison suivante:
  
 <code cpp> <code cpp>
 +#pragma once
 +#​include<​algorithm>​
  
-#​include ​<iostream+template<typename ​ iterator
- +void simple_sort(iterator startiterator end)
-double divide(double adouble b); +
-void test_divide();​ +
- +
-void test_divide()+
 { {
-  double i, j; +    ​for(;start != endstart ++
-  ​for(;;​) ​{ +    ​{ 
-    ​std::cout << "Le numerateur (0 pour arreter): "; +        auto it = start; it++
-    ​std::​cin >> i+        for(;it !end; it ++
-    if(== 0+        { 
-      ​break;​ +            // Compare si les deux elements sont dans le bon ordre. 
-    ​std::​cout << " Le denominateur : "; +            if (*start ​*it) 
-    ​std::​cin ​>> j; +                std::swap(*start*it); 
-    std::cout << "​Resultat:​ " << divide(i,j<< std::endl+        } 
-  +    ​}
 } }
 +</​code>​
  
-double divide(double a, double b) 
-{ 
-  try { 
-    if(!b) throw b;  
-  } 
-  catch (double b) { 
-    std::cout << "Ne peut pas diviser par zero.\n";​ 
-    return b; 
-  } 
-  return a/b; 
-} 
- 
-void main() 
-{ 
-    test_divide() ; 
-} 
- 
-</​code>​ 
  
-==== Question n°1.==== +==== Question n°1.1 =====
  
-Procéder à une exécution et regarder ce qui se passe quand une division par 0 se produit.+Déterminer quel type d'​itérateur est requis pour effectuer les opérations ?
  
 <hidden Correction>​ <hidden Correction>​
 +Il s'agit d'un itérateur:
 + 
 +  * devant offrir une itération croissante,
 +  * devant offrir la possibilité de reprendre l'​itération à partir d'une position antérieurement stockée.
  
-Lors d'une division par zéro se produit, le code  +Si nous regardons les caractéristiques des itérateurs[[https://en.cppreference.com/​w/​cpp/​iterator|Iterator library]], nous constatons que: 
-<code cpp> +  
-    std::cout << "Ne peut pas diviser par zero.\n"; +  ​* ​//​LegacyInputIterator//:​ ne supporte pas plusieurs passes ​et ne supporte pas l'écriture,​ 
-    ​return b; +  * //​LegacyForwardIterator//:​ supporte plusieurs passes mais ne supporte pas obligatoire ​l'écriture,​ 
-</code> +  * //​LegacyOuputIterator//:​ supporte l'écriture.
-est exécuté ​et la fonction retourne ''​0''. Ceci signifie que l'exception de type ''​double''​ ayant pour valeur ''​0''​ a été générée et a été capturée par la clause ''​catch(double)'​'.+
  
-<​code>​ +De faitnous devons garantir à la fois la lecture et l'​écriture,​ ce qui signifie que nous devons nous assurer que l'​itérateur respect les contracts requis pour un //​LegacyForwardIterator//​ et un //​LegacyOuputIterator//​.
-try { +
-    if(!b) throw b;  +
-  } +
-  catch (double b) { +
-    std::cout << "Ne peut pas diviser par zero.\n";​ +
-    return b; +
-  } +
-</​code>​ +
- +
-Dans les autres casc'est bien le résultat de la division qui est retournée par la fonction.+
  
 </​hidden>​ </​hidden>​
-==== Question n°1.3 ====  
  
-Exécuter en mode débogage et placer un point d’arrêt sur le code de capture de l’exception. 
  
-<hidden Correction>​ +==== Question n°1.2 =====
-L'​objectif de cette question est de vous faire manipuler vos outils pour utiliser l'​environnement de dévogage de votre environnement de développement. Bien entendu, en fonction de votre environnement,​ vous avez des procédures différentes pour positionner un point d'​arrêt+
  
-Pour mémoire, voici quelques références pour placer des points ​d'arrêts sur les différents outils (sans garantie aucune d'​exhaustivité).+Ajouter une contrainte imposant que le type passé à la fonction correspond bien au type d'itérateur que vous avez identifié.
  
-  * [[https://code.visualstudio.com/​docs/​cpp/​cpp-debug|Debug C++ in Visual Studio Code]] +<hidden Correction>​ 
- +<code cpp> 
-  * [[http://​wiki.codeblocks.org/​index.php/​Debugging_with_Code::Blocks|Debugging with Code::Blocks]] +template<​typename ​ iterator>​ 
- +void simple_sort(iterator start, iterator end)  
-  * [[https://​docs.microsoft.com/​fr-fr/​visualstudio/​debugger/​quickstart-debug-with-cplusplus?​view=vs-2019|Quickstart:​ Debug with C++ using the Visual Studio debugger]] +    requires(std::forward_iterator<​iterator>​ && std::input_or_output_iterator<​iterator>​) 
- +{ 
-  * [[https://​medium.com/​yay-its-erica/​xcode-debugging-with-breakpoints-for-beginners-5b0d0a39d711|Xcode Debugging with Breakpoints ​(for Beginners)]] +    std::cout << "​Insertion Sort\n";​ 
- +    for(;start !end; start ++) 
-  * [[https://www.cs.swarthmore.edu/​~newhall/​unixhelp/​howto_gdb.php|gdb ​(and dddGuide]] +    { 
- +        auto it = start; it++; 
-  * [[https://​www.emacswiki.org/​emacs/​DebuggingWithEmacs|Debugging with Emacs]]+        ​for(;it != end; it ++
 +        { 
 +            // Compare si les deux elements sont dans le bon ordre. 
 +            if (*start > *it
 +                ​std::​swap(*start,​ *it); 
 +        } 
 +    } 
 +
 +</code>
 </​hidden>​ </​hidden>​
-===== Question n°2 : Création d’une classe d’exception ===== 
  
-Nous envisageons désormais faire les choses correctement. Nous souhaitons définir une classe exception qui dérive de la classe [[https://​en.cppreference.com/​w/​cpp/​error/​exception|std::​exception]] se trouvant définie dans le fichier d'​entête [[https://​en.cppreference.com/​w/​cpp/​header/​exception|<​exception>​]]. Plus spécifiquement,​ nous souhaitons la faire dériver de la classe ​ [[https://​en.cppreference.com/​w/​cpp/​error/​runtime_error|std::​runtime_error]] qui elle-même dérive de [[https://​en.cppreference.com/​w/​cpp/​error/​exception|std::​exception]]. ​ 
  
-Cette classe devra s’appeler ''​division_by_zero''​.+==== Question n°1.3 ====
  
-==== Question n°2.1 ====+Nous souhaitons ajouter l'​opérateur suivant qui liste l'​ensemble des éléments d'un conteneur:
  
-Créer la classe ''​division_by_zero''​Elle pourra être définie dans un fichier d’entête ''​math.hpp''​ qui contiendra aussi l’entête de la fonction ''​divide''​. Le fichier associé ''​math.cpp''​ contiendre la code de la fonction divide.+<code cpp> 
 +template<​typename ​ containerT, typename charT, typename traits = std::​char_traits<​charT>>​ 
 +std::​basic_ostream<​charT,​ traits>&​ operator << (std::​basic_ostream<​charT,​ traits>&​ aStream, const containerT&​ aContainer) 
 +
 +    aStream << "​{";​ 
 +    auto end = aContainer.end(); 
 +    for(auto it = aContainer.begin(); it != end;) 
 +    { 
 +        aStream << *it ++; 
 +        if(it != end) 
 +            aStream << ", "; 
 +    } 
 +    aStream << "​}";​ 
 +}  
 +</code>
  
-Penser ​à fournir un message d’erreur cohérent. +Ajouter ce code à votre fichier 'simple_sort.hpp' ​et puis tester ensuite à la fois la précédente fonction et cette nouvelle fonction avec le code suivant :
- +
-<hidden Correction>​ +
- +
-Nous nous proposons de créer un fichier ''math.hpp'' qui a le contenu ​suivant :+
  
 <code cpp> <code cpp>
-#ifndef mathHPP 
-#define mathHPP 
  
-#​include<​exception+#​include<​list
-#include<​stdexcept>​+#include"​simple_sort.hpp"​
  
-class division_by_zero:​ public std::​runtime_error+int main() ​
 { {
-public:  +    std::​list<​int>​ v = {1, 7, 3, 4, 9, 2, 5}; 
-    ​division_by_zero(): std::​runtime_error("​Division by zero"+    ​simple_sort(v.begin(), v.end()); 
-    ​{} +    ​std::cout << v
-}+    ​return 0
- +}
-double divide(double a, double b);  +
-#endif+
 </​code>​ </​code>​
  
-Ainsi que le fichier ''​math.cpp''​ qui contient le code de la fonction ​''​divide''.+ 
 +==== Question n°1.4 ==== 
 + 
 +Dans la question précédente,​ nous avons défini une nouvelle surcharge ​de l'opérateur %%<<​%%. En fait, cette surcharge n'est pas optimale, puisqu'il suffit que je définisse un type quelconque non supporté et cela ne fonctionne plus :
  
 <code cpp> <code cpp>
-#include "math.hpp"+#​include<​list>​ 
 +#​include"​sort.hpp"
  
-double divide(double a, double b+struct Toto {}; 
 +int main() 
 { {
-  try +    std::​list<​int>​ v = {1, 7, 3, 4, 9, 2, 5}; 
-    ​if(!bthrow b;  +    ​simple_sort(v.begin(), v.end()); 
-  } +    std::cout << ​v
-  catch (double b{ +    ​std::cout << Toto() << std::endl
-    std::cout << ​"Ne peut pas diviser par zero.\n"​+    return ​0;
-    ​return b+
-  } +
-  ​return ​a/b;+
 } }
- 
 </​code>​ </​code>​
-</​hidden>​ 
  
-==== Question n°2.2 ==== +Expliquer pourquoi le compilateur génére ​une erreur ?
- +
-Modifier les fonctions ''​divide''​ et ''​test_divide''​ pour prendre ne plus lancer et capturer ​une exception de type ''​double''​ mais de type ''​division_by_zero''​.+
  
 <hidden Correction>​ <hidden Correction>​
- +En fait, il n'y a pas de surcharge de l'​opérateur %%<<​%% pour le type `Toto`, en conséquence,​ le compilateur va rechercher dans les opérateurs qui n'ont pas de contraintes sur les types, vous vous souvenez qu'on essaye d'​abord les opérateurs les plus généraux et ensuite les moins généraux. Il trouve donc dans l'​espace de nom courant l'​opérateur ​ 
-La fonction modifiée s'écrit dorénavant comme suit :+
  
 <code cpp> <code cpp>
-inline double divide(double adouble b) +template<​typename ​ containerT, typename charTtypename traits ​std::​char_traits<​charT>>​ 
-+std::​basic_ostream<​charT,​ traits>&​ operator << ​(std::basic_ostream<charT, traits>&​ aStream, const containerT&​ aContainer) {...}
-  try { +
-    if(b == 0)  +
-        throw division_by_zero();  +
-  } +
-  catch (division_by_zero) { +
-    ​std::cout << "Ne peut pas diviser par zero.\n"; +
-    return 0; +
-  } +
-  return a/b; +
-}+
 </​code>​ </​code>​
 +
 +et ne sait pas que cet opérateur n'est définit que pour les objets qui sont des conteneurs au sens de la STL. En conséquence de quoi, il génère une erreur puisqu'​il essaye d'​instancier un code qui ne supporte pas des objets de type `Toto`.
  
 </​hidden>​ </​hidden>​
 +
 +
 +[[in204:​tds:​sujets:​td6:​part2|Partie 2]]
 +
  
in204/tds/sujets/td6/part1.1604227721.txt.gz · Last modified: 2020/11/01 10:48 by bmonsuez