Makefiles
.
Makefiles
(plus dans la projet !) ;
N'oubliez pas non plus de vous inscrire (et commencez à naviguer) sur le MOOC correspondant : https://www.coursera.org/learn/programmation-orientee-objet-cpp/
.
Avant de commencer les exercices décrits dans cette série,
créez le répertoire ~/Desktop/myfiles/cpp/serie14
(c.-à-d.
créez le sous-répertoire serie14
dans le
répertoire ~/Desktop/myfiles/cpp
; j'ai mis « 14 » pour faire suite au premier semestre si vous utilisez le même endroit).
Travaillez dans ce répertoire.
Je vous rappelle également que ces exercices ont des niveaux :
Les exercices de ce niveau peuvent sans problème être sauté par tous ceux qui estiment avoir une suffisamment bonne compréhension du cours.
niveau 1 : ces exercices élémentaires devraient pouvoir être faits par tous dans un temps raisonnable (20 à 30 minutes maximum). Ils permettent de travailler les bases.
niveau 2 (pas cette fois) : ces exercices plus avancés devraient être abordés par tous, sans forcément être finis. La reprise de l'exercice avec la correction devrait constituer un bon moyen de progresser.
niveau 3 (pas cette fois) : ces exercices d'un niveau avancé sont pour les plus motivés/habiles d'entre vous. Ils peuvent dans un premier temps être ignorés. Ils devraient être repris, si nécessaire avec la correction, lors des révisions.
En général, la totalité de la série n'est pas prévue pour être finie en 2 heures ! La série est à considérer comme un regroupement de plusieurs exercices, un peu comme un chapitre de livre d'exercices, où chacun peut choisir (à l'aide des indications ci-dessus) ce qui lui semble adapté à sa progression.
Le niveau moyen pour 2 heures d'exercice correspond à deux exercices niveau 1 et un exercice niveau 2.
Pour finir, je vous conseille également, en plus des 2 heures d'exercices à l'emploi du temps, de travailler par vous-même chez vous, typiquement sur votre projet. Ce travail supplémentaire devrait en moyenne correspondre à 3 heures hebdomadaires pour un étudiant de niveau moyen.
La nouveauté de ce second semestre est l'introduction du projet et de certains exercices spécifiques dédiées à la progression du projet.
Le but de cet exercice, destiné à vous « remettre en jambes », est de coder les bases de l'arithmétique des nombres rationnels. C'est la copie de l'exercice 1 de la dernière série du premier semestre (si vous ne l'avez pas fait....)
Un autre but, moins direct, est que cet exercice pourrait (libre à vous) vous servir de base pour pratiquer les concepts de la Programmation Orientée Objet que nous allons voir pendant le semestre : faites évoluer votre solution chaque semaine avec les nouveaux concepts présentés.
Un nombre rationnel est défini par deux entiers p
et
q
, tels que :
p
représente le numérateur et q
le dénominateur
Par exemple : 1/2 : p=1, q=2 ; -3/5 : p=-3, q=5 ; 2 : p=2, q=1.
Quelle type de données utiliser pour représenter les nombres rationnels ?
Écrivez un programme rationnels.cc
, contenant
cette structure de donnée et une fonction affiche()
permettant d'afficher un tel rationnel.
Testez votre programme avec les 3 rationnels donnés en exemple ci-dessus. Le programme devra afficher :
1/2 -3/5 2
On veut maintenant implémenter les 4 opérations élémentaires :
Rationnel addition(Rationnel r1, Rationnel r2);définie par
p1/q1 + p2/q2 = reduction(p1*q2+p2*q1/(q1*q2))où
reduction(p/q)
trouve les nombres p0 et q0 tels
que
p0/q0 = p/q et p0 et q0 vérifient la définition donnée plus
haut
(en particulier sont premier entre eux)
Pour la fonction reduction()
, on utilisera le calcul de PGDC
implémenté dans l'exercice 6 de
la série 5 du premier semestre
Exemples :
1/2 + -3/5 = -1/10 2 + -3/5 = 7/5 2 + 2 = 4
Remarque : toute sophistication de la formule
ci-dessus (en particulier si q1 = q2) peut évidemment être
implémentée pour la fonction addition()
.
Rationnel soustraction(Rationnel r1, Rationnel r2);définie par
p1/q1 - p2/q2 = reduction(p1*q2-p2*q1/(q1*q2))
Exemples :
1/2 - -3/5 = 11/10 2 - -3/5 = 13/5 -3/5 - -3/5 = 0
Rationnel multiplication(Rationnel r1, Rationnel r2);définie par
p1/q1 * p2/q2 = reduction(p1*p2/(q1*q2))
Exemples :
1/2 * -3/5 = -3/10 2 * -3/5 = -6/5 -3/5 * -3/5 = 9/25
Rationnel division(Rationnel r1, Rationnel r2);définie par
p1/q1 / (p2/q2) = reduction(p1*q2/(q1*p2))si
p2 > 0
, par
p1/q1 / (p2/q2) = reduction((-p1)*q2/(q1*(-p2)))si
p2 < 0
et non définie si p2 = 0
.
Exemples :
1/2 / (-3/5) = -5/6 2 / (-3/5) = -10/3 -3/5 / (-3/5) = 1
Le but de cet exercice facultatif est de vous faire pratiquer la compilation séparée.
[ Si nécessaire, pour une présentation complémentaire à celle du cours des concepts de base de la compilation séparée, consultez le début de la mini-référence sur les 'Makefiles' et revenez ici lorsque cette mini-référence vous y renvoit. ]
On va pour cela reprendre l'exercice 2
de la série 6 du premier semestre (si vous ne l'avez pas fait, c'est l'occasion !), mais au lieu de définir toutes les fonctions
(demander_nombre()
, factorielleIterative()
et factorielleRecursive()
)
dans un même fichier, nous allons créer 4 fichiers sources :
factmain.cc
qui sera le corps du programme
principal ;
factorielleIterative.cc
qui définira une
fonction
int factorielle(int n)implémentant l'algorithme itératif du calcul des factorielles ;
factorielleRecursive.cc
qui définira aussi une
fonction
int factorielle(int n)mais implémentant la version récursive ;
demander_nombre.cc
qui définira la
fonction du même nom.
Ces fichiers sources vont nous permettre de créer deux programmes :
factorielleIterative
qui utilisera la version itérative,
et factorielleRecursive
qui utilisera la version récursive de
l'algorithme.
Séparez votre programme factorielle.cc
de
l'exercice 2 de la série 6 du premier semestre en ces quatre fichiers et renommez les fonctions
factorielleIterative()
et factorielleRecursive()
simplement factorielle()
(oui, le même nom pour les deux).
Modifiez le corps de main
(dans factmain.cc
) de sorte à n'avoir qu'un seul appel
à la fonction factorielle()
.
Essayez de compiler factmain.cc
: ça ne
joue pas car il manque à ce fichier les prototypes des fonctions demander_nombre()
,et
factorielle()
.
Il faut pour cela inclure les fichiers "entête" (.h
) correspondants.
Créez le fichier demander_nombre.h
contenant le
prototype de la fonction demander_nombre()
, puis ajoutez
#include "demander_nombre.h"au début de
factmain.cc
.
Créez ensuite le fichier factorielle.h
contenant le
prototype de la fonction factorielle()
(les deux
fonctions implémentées ont bien le même prototype, seul l'algorithme
change, mais ce n'est justement pas le « problème » du fichier .h
qui, lui, n'a qu'un seul prototype à fournir). Puis ajoutez l'inclusion de ce fichier dans factmain.cc
.
Il faut encore inclure les définitions et prototypes nécessaires à la compilation des trois autres fichiers :
demander_nombre.cc
, ajoutez
#include <iostream> using namespace std;(et d'autres si nécessaire en fonction de ce que vous utilisez dans
demander_nombre()
).
Il ne nous reste plus qu'à « compiler » (compiler et faire l'édition de liens de) nos programmes :
g++ -c -o demander_nombre.o demander_nombre.cc g++ -c -o factorielleRecursive.o factorielleRecursive.cc g++ -c -o factorielleIterative.o factorielleIterative.cc g++ -c -o factmain.o factmain.cc g++ factmain.o factorielleRecursive.o demander_nombre.o -o factorielleRecursive g++ factmain.o factorielleIterative.o demander_nombre.o -o factorielleIterative
Cela étant fastidieux, on va maintenant chercher à écrire un Makefile
qui
effectue toutes ces étapes pour nous.
[ Pour une présentation plus détaillée de l'outil make
et du
fonctionnement des Makefile
, consultez la
mini-référence 'Makefiles'. ]
Note: comme évoqué à la fin du cours, il existe des outils plus modernes et de plus haut niveau que make (qui est vraiment la base). L'un d'entre eux très répendu de nos jours est CMake. Si vous préférez continuer cet
exercice avec CMake
vous pouvez aller voir notre mini-tutoriel sur comment compiler avec CMake.
[fin de note.]
Dans un fichier (texte) qui s'appelle simplement « Makefile
» (oui, comme ça, tout seul, sans extension), écrivez les deux
lignes des dépendances de chacun des programmes factorielleRecursive
et
factorielleIterative
(revoir le cours correspondant si nécessaire).
Ajoutez ensuite les lignes recommandées en cours:
CC = $(CXX) CXXFLAGS = -std=c++11 -pedantic -Wall
La première va faire que l'édition de liens se fasse en C++ et non pas en C (qui est l'option par défaut).
La seconde vous permet de spécifier vos options de compilation (changez les comme vous le souhaitez).
Pour finir ajouter la dépendance
all: factorielleRecursive factorielleIterativeau début de votre
Makefile
Essayer de compiler en tapant simplement
make
ou en lançant cette commande depuis votre IDE («Build» puis «Make all» dans Geany; voir la note ci-dessous).
Si vous avez un message comme
make: Nothing to be done for `all'.c'est que vos programmes
factorielleRecursive
et factorielleIterative
existent
déjà (et donc make
dit qu'il n'y a plus rien à faire).
.o
,
tant qu'on y est) puis relancez make
:
rm *.o factorielleRecursive factorielleIterative make
NOTES :
make
dans Geany:
Shift F9
pour faire « make
» ;
Ctrl Shift F9
pour faire « make qqchose
» (une fenêtre s'ouvre pour que vous puissiez entrer « qqchose »).
Pour continuer à vous replonger dans le bain de la programmation, faîtes divers exercices que vous n'avez pas fait au premier semestre.
Quelques exemples :
Concernant l'utilisation de débogueur (outil pratique pour trouver des fautes), vous pouvez aller voir (ou revoir) l'exercice 3 de la dernière série du 1er semestre (aussi disponible ici sur ce site).
Autre possibilité pour vous occuper : si vous souhaitez passer à Qt Creator comme EDI pour le projet (et que vous ne l'avez pas utilisé au premier semestre), voyez:
Allez lire ici, la présentation du projet.