Devoir Surveillé en Programmation Orientée Objets

École Nationale des Sciences de l'Informatique (ENSI)
Page 1 sur 10Lecteur de document UniversityLib

Devoir Surveillé en Programmation Orientée Objets

École Nationale des Sciences de l'Informatique (ENSI) · Programming, Math · exam

Voir tous les documents en programmation

UNIVERSITE DE LA MANOUBA

-----¤¤¤¤-----

ECOLE NATIONALE DES SCIENCES

DE L'INFORMATIQUE

ANNEE UNIVERSITAIRE

2010-2011

Matière : Programmation Orientée Objets

Niveau : II1

Enseignants : Y. JAMOUSSI, K. BEN RHOUMA, R.CHEBIL, S. MTIBAA, O. FAKHFAKH

Date : vendredi 8 avril 2011

Durée: 2H

Documents : Non autorisés

Devoir surveillé

  • Nombre de pages = Sujet (2 pages) + 2 formulaires A3 à rendre (de 1/8 à 8/8)
  • Les réponses hors sujet seront notées négativement

Exercice n°1 (6 pts) : (les questions se trouvent dans les pages de 1/8 à 2/8)

Soit les deux classes A et B suivantes :

class A {

private:

int * ptr;

public:

A() : ptr(NULL)

{

cout << "A::A()" << endl;

}

A( int a ) : ptr(new int(a))

{

cout << "A::A(" << a << ")" << endl;

}

class B {

private:

A att;

public:

B() : att(1)

{

cout << "B::B()" << endl;

}

B(int n)

{

att = A(n);

cout << "B::B(" << n << ")" << endl;

Publicité

}

~A() { delete ptr; }

~B() { cout << "B::~B()" << endl; }

void operator = (const A & arg)

{

cout << "operateur =" << endl;

if (&arg != this)

{

ptr = new int( *(arg.ptr) );

}

}

void afficher() const

{

cout << "A::ptr=" << ptr << endl;

}

};

void B::afficher() const

{

cout << "B::";

att.afficher();

}

void f(A arg)

{

att = arg;

afficher();

}

};

Exercice n°2 (5,5 pts) : (les questions se trouvent dans les pages de 2/8 à 4/8)

En mathématiques, un nombre rationnel est celui qui peut être représenté comme une fraction dont le numérateur

et le dénominateur sont deux entiers. 0,5 = ½ et 1,3125 = 21/16 sont deux nombres rationnels. Cependant, la

racine carrée de 2 n’est pas un nombre rationnel; vous ne pouvez pas l'exprimer comme le rapport de deux

entiers.

Certains calculs pourraient bénéficier du type de données fraction, qui préserve le numérateur et le dénominateur

séparément. Par exemple, un problème inhérent à tous les ordinateurs est l’inexactitude de la représentation des

nombres à virgule flottante. En effet, comme les cellules mémoires de l'ordinateur sont limitées dans leur taille, le

réel x = 1 / 3 est représenté par 0.3333333 et donc le réel y = 3 * x est plutôt 0.9999999 et non pas 1 !

A cet effet, on se propose de représenter la fraction 1/3 comme deux entiers distincts (1 et 3), et 3 comme la

fraction 3/1. Ensuite, une multiplication de ces deux fractions donnerait exactement 1 et non pas plus ou moins 1.

1/2

La classe Fraction est définie comme suit :

Publicité

class Fraction {

private:

int numer; // numérateur

int denom; // dénominateur

public:

Fraction(int num=1, int den=1) : numer(num), denom(den)

{ if (denom) == 0 ) denom = 1; }

};

Exercice n°3 (8,5 pts) : (les questions se trouvent dans les pages de 5/8 à 8/8)

On se propose d’écrire en C++ une classe représentant un ensemble d’entiers et de l’utiliser dans un petit

exemple : le calcul des nombres premiers par le crible d’Eratosthène.

Pour trouver tous les nombres premiers de 2 à MAX, le principe du crible d’Eratosthène est le suivant :

1. Construire un ensemble contenant tous les entiers de 2 à MAX;

2. Extraire le plus petit élément de cet ensemble car c’est un nombre premier et l’afficher;

3. Enlever de cet ensemble tous les multiples de ce nombre premier ;

4. Continuer en 2 jusqu’à ce que l’ensemble soit vide.

Pour simplifier, on définira seulement les opérations sur les ensembles qui sont utiles pour le crible

d’Eratosthène : ajouter (add) un élément, supprimer (del) un élément, savoir si un élément est présent

(estPresent) ou non, savoir si l’ensemble est vide (estVide) ou non, donner le plus petit élément (plusPetit) de

l’ensemble. On ne considérera donc pas les opérations sur les ensembles telles que l’union, l’intersection,

l’inclusion, etc.

Un ensemble contient des éléments uniques et on suppose que les éléments sont placés dans un ordre

quelconque. On se propose d’implémenter un ensemble par une liste chaînée. La figure suivante vous aidera à

comprendre la structure de l’implémentation.

Après l’invocation de la méthode “add(4)” l’ensemble reste le même car l’ensemble contient déjà “4”.

Après l’invocation de la méthode “add(3)” l’ensemble se réarrange comme suit (on suppose que l’ajout se fait en

début de liste):

Un exemple d’usage des méthodes de la classe Ensemble.

Ensemble set;

set.add(1);

set.add(8);

set.add(2);

while ( ! set.estVide() )

{

int ppe = set.plusPetit();

cout << ppe << endl ;

set.del(ppe);

}

Le programme affiche :

1

Publicité

2

8

2/2

Devoir « Programmation Orientée Objets » - Avril 2011 / ENSI

Formulaire de réponse (1/2)

Nom …………………………… Prénom …………………………….Classe :……………………..

20

Exercice n°1 (6 pts):

Pour chacune des instructions suivantes appartenant à un même bloc, donner s’il y a lieu : l’affichage

produit et éventuellement la ou les erreurs dans la gestion de la mémoire (violation et/ou fuite) en expliquant

les causes.

A a1;

a1.afficher();

A a2(5);

a1 = a2;

a1.afficher();

A a3 = a2;

a3.afficher();

1/8

B b1;

B b2(2);

b1.afficher();

b1.f(a2);

Fin du bloc

Exercice n°2 (5,5 pts) :

1) Définir et implémenter les opérateurs de multiplication et d’addition de deux fractions. N’oubliez pas de mettre

la fraction en forme réduite (la forme réduite de la fraction 40/60 et 2/3).

Remarque : Vous pouvez utiliser la fonction « int pgcd(int a, int b) » qui retourne le pgcd de deux entiers.

2/8

2) On souhaite multiplier une fraction par un entier et on souhaite multiplier un entier par une fraction. Définir et

implémenter les deux opérateurs de multiplication en tenant compte de l’ordre des arguments. N’oubliez pas de

mettre le résultat sous forme réduite.

3) Définir et implémenter les opérateurs d’égalité et de non égalité de deux fractions.

4) On se propose de faire une affectation de fractions (exple F1 = F2). Est-il nécessaire de redéfinir cet opérateur ?

justifier votre réponse.

3/8

5) Maintenant qu’on dispose de la classe Fraction telle qu’elle a été définie dans l’énoncé et les opérateurs définis

dans les questions précédentes :

a. Donner le corps du programme qui permet de calculer la fraction F3 = 2 * F2 + F1 (sachant que F1 = 1/2

et F2 = 2/3) et d’indiquer si F3 est égale ou non à la fraction 5/6.

Publicité

b. Donner le corps du programme qui permet de calculer la suite suivante (en utilisant impérativement la

classe Fraction):

Un = 1 + 1/2 + 1/3 + 1/4 + …. + 1/100

4/8

Devoir « Programmation Orientée Objets » - Avril 2011 / ENSI

Formulaire de réponse (2/2)

Nom …………………………… Prénom …………………………….Classe :……………………..

Exercice n°3 (8,5 pts):

La structure Noeud est définie comme suit :

struct Noeud {

Noeud * next;

int valeur;

};

1) Concernant la classe Ensemble et sachant qu’on ne souhaite manipuler qu’une seule instance de la

classe Ensemble, dire s’il est nécessaire de définir ou pas un constructeur par défaut (sans arguments),

un constructeur de copie, un destructeur, un opérateur d’affectation. Justifier brièvement chaque

réponse.

2) Donner la déclaration (l’interface) de la classe Ensemble qui décrit un ensemble d’entiers.

class Ensemble

{

private:

public:

};

5/8

3) Donner l’implémentation de toutes les méthodes que vous avez définies dans la question précédente.

6/8

7/8

4) Ecrire un programme principal qui saisit un entier n ≥ 2 et moyennant la classe Ensemble définie

précédemment (bien sûr !):

• Remplit l’ensemble set par les entiers de 2 à n

• Calcule et affiche les nombres premiers ≤ n en utilisant le principe du crible d’Eratosthène.

void main( )

{

Ensemble set;

}

8/8