Académique Documents
Professionnel Documents
Culture Documents
L’opérateur d’extraction peut être surchargé pour un objet obj d’une classe CL existente en utilisant une
fonction globale (non membre de la classe CL) dont le prototype est
std :: istream & operator > >( std :: istream & i , CL & obj );
L’en-tête à inclure est iostream.
3. Plusieurs façons de faire : soit surcharger l’opérateur << de façon générique, soit écrire une fonction affiche. Un
exemple de fonction générique affiche. Ici il suffit que le type des données soit générique.
template < typename T >
2 void affiche ( std :: vector <T > const & v ) {
for ( int i = 0; i < v . size (); ++ i )
4 std :: cout << v [ i ] << std :: endl ;
}
4. Cette fois c’est un peu plus délicat car il faut une fonction générique qui s’applique aux deux types de conteneur
(vector et list).
template < typename T >
2 void affiche ( T const & v ) {
typename T :: const_iterator it ;
4 for ( it = v . begin (); it != v . end (); ++ it )
std :: cout << * it << std :: endl ;
6 }
(Les points sont donnés même si le mot-clé typename -pourtant indispensable car T est générique- est oublié).
Exercice 2
1. Remarques :
– il n’y a pas de type bool en C(à la place on utilise une variable entière et on lui fait prendre 2 valeurs : 0 pour
faux et 1 pour vrai),
– l’opérateur de comparaison est == et non =,
– la boucle interne doit s’arrêter à l’avant-dernier élément, c’est à dire celui d’indice n-2.
Voici une version pour un tableau t d’entiers de taille n.
void tri_bulle ( int t [] , int n ) {
2 int j , tmp , en_desordre ;
do {
4 en_desordre = 0;
for ( j = 0; j < n -1; ++ j ) {
6 if ( t [ j ] > t [ j +1]) {
tmp = t [ j ];
8 t [ j ] = t [ j +1];
t [ j +1] = tmp ;
1
10 en_desordre = 1;
}
12 }
} while ( en_desordre == 1);
14 }
2. Il faut rajouter un compteur k qui compte le nombre de fois qu’on a executé la boucle externe do...while.
void tri_bulle_opt ( int t [] , int n ) {
2 int j , tmp , en_desordre ;
int k = 0;
4 do {
en_desordre = 0;
6 for ( j = 0; j < n -k -1; ++ j ) {
if ( t [ j ] > t [ j +1]) {
8 tmp = t [ j ];
t [ j ] = t [ j +1];
10 t [ j +1] = tmp ;
en_desordre = 1;
12 }
}
14 k ++;
} while ( en_desordre == 1);
16 }
4. struct maillon {
2 int data ;
struct maillon * suivant ;
4 struct maillon * precedent ;
}
5. Pour échanger le maillon (à l’adresse) m et le maillon suivant m->suivant dans une liste doublement chaînée il
faut modifier les 4 maillons aux adresses m->precedent, m, m->suivant, m->suivant->suivant (faire un dessin). On
appelle ces 4 maillons ai, b, c et d et on modifie les liens (faire un dessin). Remarque importante : les adresses
a et d peuvent être l’adresse NULL.
void swap ( struct maillon * m) {
2 struct maillon * a = m - > precedent ;
struct maillon * b = m;
4 struct maillon * c = m - > suivant ;
struct maillon * d = m - > suivant - > suivant ;
6
2
6. Une façon de faire est de placé le pointeur dernier à la fin de la liste (sur le dernier maillon) puis de trier
jusqu’à ce pointeur, puis de le faire avancer à chaque itération de la boucle do...while. On peut aussi utiliser
un compteur et la longueur de la liste...
void t ri _ b ul le_opt_liste ( struct maillon * liste ) {
2 struct maillon * pt = NULL ;
struct maillon * dernier = NULL ;
4 while ( dernier - > suivant != NULL )
dernier = dernier - > suivant ;
6 int en_desordre ;
do {
8 en_desordre = 0;
for ( pt = liste ; pt - > suivant != dernier ; pt = pt - > suivant ) {
10 if ( pt - > data > pt - > suivant - > data ) {
swap ( pt );
12 en_desordre = 1;
}
14 }
dernier = dernier - > precedent ;
16 } while ( en_desordre == 1);
}
Exercice 3
1. Les méthodes operator() et derivee sont qualifiées de « virtuelles pures ». La classe FctR est donc une classe
abstraite dont le but est d’être une classe mère afin d’utiliser le mécanisme de polymorphise dynamique : un
objet d’une classe fille à une adresse compatible avec l’adresse de la classe FctR.
Ces méthodes doivent être redéfinies dans les classes filles.
2. Il ne faut pas oublier de définir le constructeur !
struct Cubique : public FctR {
2 Cubique ( double a , double b ) : a ( a ) , b ( b ) {};
double operator ()( double x ) const {
4 double y = a * x + b ;
return y * y * y ;
6 };
double derivee ( double x ) const {
8 double y = a * x + b ;
return 3* a * y * y ;
10 };
private :
12 double a , b ;
}
3. – ligne 4 : fct(f)
– ligne 8 : *this
– ligne 10 : protected:
Il est nécessaire de définir fct comme une adresse de FctR pour plusieurs raisons : pour utiliser le polymorphisme
dynamique mais aussi parce que FctR est une classe abstraite et ne peut donc pas avoir d’objets. L’instruction
FctR fct est donc impossible et ce quelque soit le contexte.
4. Attention le constructeur de la classe Newton doit appeler explicitement le constructeur de la classe mère
AlgorithmeR.
class Newton : public AlgorithmeR {
2 public :
Newton ( double x_0 , FctR & f ) : AlgorithmeR ( x_0 , f ) {};
4 friend std :: ostream & operator < <( std :: ostream & o , Newton & const algo );
private :
6 void calcul_iter () {
x_n = x_n - fct ( x_n ) / fct . derivee ( x_n );
8 }
}
10
std :: ostream & operator < <( std :: ostream & o , Newton & const algo ) {
12 return o << algo . n_iter << " \ t " << algo . x_n ;
}
3
5. class Secante : public AlgorithmeR {
2 public :
Secante ( double x_0 , FctR & f ) : AlgorithmeR ( x_0 , f ) , x - nm1 ( x_0 -1) {};
4 private :
double x_nm1 ;
6 void calcul_iter () {
double sauve = x_n ;
8 x_n = x_n - ( x_n - x_nm1 )/( fct ( x_n ) - fct ( x_nm1 )) * fct ( x_n );
x_nm1 = sauve ;
10 }
}