IN204
Programmation Orientée Objet – Les Composants
Séances de Travaux Dirigés du 25 septembre et 2 octobre 2019
B. Monsuez
Partie I – Classe & Fonction Générique
La classe de la bibliothèque C++ standard dite STL (Standard Template Library) std::vector est définie comme suit :
template < class T, class Alloc = allocator<T> > class vector;
vous trouverez en plus des éléments décrivant la classe dans l’annexe du TD plus d’informations à l’URL suivante : http://www.cplusplus.com/reference/vector/vector/.
Pour l’instant, nous ignorons le paramètre Alloc.
Pour pouvoir utiliser cette classe, il est impératif de charger le fichier qui contient la définition de la classe :
#include<vector>
Question n°1
Nous nous intéressons pour trier des éléments dans un tableau dynamique de type std::vector<int>.
L’ensemble des fonctions sera créé dans un nom d’espace appelé monomorphic.
Le fichier d’entête « simple_sort.hpp » ressemblera au fichier suivant :
#ifndef simple_sortHPP
#define simple_sortHPP
#include<vector>
namespace monomorphic {
void populate_with_randoms(std::vector<int>& theVector,
int theNumberOfValues, int theMinValue, int theMaxValue);
void print_vector(const std::vector<int>& anArray);
void simple_sort(std::vector<int>& theValues);
}
#endif
Et le fichier de code « simple_sort.cpp » ressemblera au fichier suivant :
#include"simple_sort.hpp"
#include<iostream>
#include<stdlib.h>
namespace monomorphic {
void populate_with_randoms(std::vector<int>& theVector,
int theNumberOfValues, int theMinValue, int theMaxValue) {…}
void print_vector(const std::vector<int>& anArray) {…}
void simple_sort(std::vector<int>& theValues) {…}
}
Question n°1.1
Écrivez une fonction qui prend un objet de type std::vector<int> et qui ajoute a cet objet un certains nombres de valeurs aléatoires number entre minValue et maxValue.
void populate_with_randoms(std::vector<int>& theVector,
int theNumberOfValues, int theMinValue, int theMaxValue) {…}
Un bon moyen pour calculer une valeur aléatoire comprsie entre theMinValue et theMaxValue est : theMinValue + (rand() % width)
avec
int width = theMaxValue - theMinValue;
Question n°1.2
Ecrivez the une fonction qui affiche un objet de type std::vector<int> vers la console qui aura l’entête suivante : void print_vector(const std::vector<int>& anArray)
{…}
Question n°1.3
Ajoutez la fonction de tri sur le tableau.
void simple_sort(std::vector<int>& theValues) {
for (int i = 0; i<theValues.size(); i++) {
for (int j = i + 1; j< theValues.size(); j++) {
// Compare si les deux elements sont dans le bon ordre.
if (theValues[i] > theValues[j]) {
// Procede a la permutation des deux elements int Temp = theValues[i];
theValues[i] = theValues[j];
theValues[j] = Temp;
} }
} }
Question n°1.4
Tester le code que vous avez créé sur un exemple simple, par exemple en créant un tableau de 10 valeurs aléatoires en 1 et 10, l’affichant ensuite, le triant et l’affichant de nouveau.
Question n°2
Nous souhaitons étendre cet algorithme de tri fonctionnant sur des entiers à des objets qui peuvent manipuler d’autres éléments que des entiers.
L’ensemble des fonctions sera créé dans un nom d’espace appelé generic.
Le fichier d’entête « generic_sort.hpp » ressemblera au fichier suivant :
#ifndef generic_sortHPP
#define generic_sortHPP
#include<vector>
namespace generic {
// Version générique des fonctions populate_with_randoms
print_vector;
simple_sort }
#endif
Question n°2.1
Il n’y aura pas de fichier « generic_sort.cpp ». Expliquer pourquoi ? Question n°2.2
Proposer une réécriture des fonctions populate_with_randoms, print_vector et simple_sort pour qu’elles puissent fonctionner avec n’importe quel autre type comme des double, des float, des short, des unsigned. Question n°2.3
Tester vos fonctions génériques pour différents types.
Partie II – Fonction spécialisée
Question n°1
Nous considérons la fonction suivante que nous ajoutons à l’espace de nom. Expliquez ce qu’elle fait et tester là.
template<>
void populate_with_randoms<std::string>(std::vector<std::string>& theVector, int theNumberOfValues, int theMinValue, int theMaxValue)
{
char buffer[20];
int width = theMaxValue - theMinValue;
for (int i = 0; i < theNumberOfValues; i++) {
int randValue = theMinValue + (rand() % width);
std::string stringValue = _itoa(randValue, buffer, 16) theVector.push_back(stringValue);
} }
Question n°2
Nous souhaitons pouvoir choisir la fonction de comparaison utilisée dans le simple_sort. Pour l’instant, la fonction de comparaison fait toujours appel à l’opérateur >.
Nous souhaitons utiliser une classe traits qui fournira l’opération de comparaison. Par défaut, cette opération de comparaison est >.
Question n°2.1 Ecrire la classe greater_traits en complétant ce qui manque.
template<typename T>
struct greater_traits {
public:
static bool is_greater(T aValue, T anotherValue) {...}
};
Question n°2.2 Modifier la fonction simple_sort pour qu’elle prenne un argument supplémentaire qui est la classe fournissant l’opération de comparaison.
Question n°2.3 Proposer une classe lower_traits qui inverse l’ordre de tri.
Question n°2.4 : Tester votre code sur l’exemple suivant : int main()
{
std::vector<int> array;
generic::populate_with_randoms(array, 10, 1, 10);
generic::print_vector(array);
std::cout << "\n";
generic::simple_sort(array);
generic::print_vector(array);
std::cout << "\n";
generic::simple_sort<int, generic::lower_traits<int>>(array);
generic::print_vector(array);
}
ANNEXE
La classe std::vector
Cette classe est définie dans l’entête « exception » de la STL. Il faut donc inclure :
#include<vector>
Quelques types utiles de la classe std::vector<T>
value_type
Type d'élément: seq<objet>::value_type n'est autre que objet reference
value_type& (ici objet &) const_reference
const value_type & (ici const objet & ) size_type
Numéros d'indices, nombre d'éléments, etc.
Quelques fonctions utiles de la classe std::vector<T>
reference front() const, const_reference front() const (vector,list,deque) Renvoie le premier élément
reference operator[](size_type n), const_reference operator[](size_type n) (vector,string,deque )
void push_back(const value_type & x) (string, deque,list,vector) Insère x à la fin.
void pop_back() (string, deque,list,vector)
Supprime x à la fin. Ces fonctions ont un comportement indéfini si le conteneur est vide: utiliser la fonction empty() auparavant.
void clear() (tous sauf stack) Efface tous les éléments.
size_type size() const (tous)
renvoie le nombre d'éléments dans le conteneur.
bool empty() const (tous)
renvoie true si le conteneur est vide.