--- jupytext: text_representation: extension: .md format_name: myst format_version: 0.13 kernelspec: display_name: C++17 language: C++17 name: xcpp17 --- +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "cbfcf0b3ffc220e808f50d1280312939", "grade": false, "grade_id": "cell-415f04d27b610548", "locked": true, "schema_version": 3, "solution": false, "task": false}} # Semaine 10 : modularité, compilation séparée +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "f117371d70884a7bf3ba7d2cd02a4af7", "grade": false, "grade_id": "cell-6d952c4decd8c707", "locked": true, "schema_version": 3, "solution": false, "task": false}} ## Objectifs pédagogiques Cette semaine, comme la précédente, notre objectif est de gérer de **« gros » programmes**, notamment pour continuer à vous préparer au projet. Nous avions eu un premier aperçu du concept de **modularité**, en découpant un programme en **fonctions**. Nous allons en rajouter une couche en découpant un programme en plusieurs fichiers, grâce à la **compilation séparée**. En prélude, nous discuterons le **cycle de vie d'un programme**, notamment pour clarifier ce qu'est la **compilation**. Comme application nous utiliserons <!-- si les conditions techniques à distance nous le permettent !-->la **bibliothèque multimédia SFML** pour faire des dessins et des interfaces graphiques. Cela pourra servir pour certaines parties optionnelles du projet. En TD et TP, nous mettrons d'abord en application la compilation séparée, observant en détail un programme découpé en plusieurs fichiers, puis reproduisant le schéma pour découper un autre programme en plusieurs fichiers. Puis nous étudierons quelques exemples de programmes utilisant la bibliothèque SFML et nous en inspirerons pour programmer des dessins et interagir avec l'utilisateur. +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "1944ac8026cc545a57bcc39a8d55fe63", "grade": false, "grade_id": "cell-6d952c4decd8c706", "locked": true, "schema_version": 3, "solution": false, "task": false}} ## <a name=Cours>Cours</a> - Cours : [Cycle de vie d'un programme](cours-cycle-de-vie-d-un-programme.md) - Cours : [Modularité et compilation séparée](cours-modularite.md) - Cours : [Digressions: surcharge, templates, espaces de noms](cours-digressions.md) - Cours : [Conclusion](cours-conclusion.md) +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "1159f167ae813029628d5129a8ac8a3a", "grade": false, "grade_id": "cell-6d952c4decd8c705", "locked": true, "schema_version": 3, "solution": false, "task": false}} ## [TD : compilation séparée, graphiques](TD.md) +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "a19c3f9a54cc2b0f7cb7ec988963186c", "grade": false, "grade_id": "cell-666b2425eb568c70", "locked": true, "schema_version": 3, "solution": false, "task": false}} ## TP +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "b3fecc2d15e9c0ee06eddcefbb2ad19a", "grade": false, "grade_id": "cell-88edc2f254ba7294", "locked": true, "schema_version": 3, "solution": false}} ### Exercice : préliminaires : compilation séparée 1. Consultez le contenu des fichiers suivants : [factorielle.hpp](factorielle.hpp), [factorielle.cpp](factorielle.cpp), [factorielle-exemple.cpp](factorielle-exemple.cpp). 2. Compilez le programme entier en suivant les instructions suivantes. Commencez par compiler chacun des bouts de programme (fichiers `.cpp`). Pour cela on utilise l'option `-c` : ```shell clang++ -c factorielle.cpp clang++ -c factorielle-exemple.cpp ``` Ceci nous a créé deux fichiers, `factorielle.o` et `factorielle-exemple.o` qui sont des bouts de programme binaires. Vérifiez avec `ls` que ces fichiers ont bien été créés. Combinez ensuite (en anglais: *link* pour «édition de liens») ces deux bouts de programme de la façon suivante : ```shell clang++ factorielle.o factorielle-exemple.o -o factorielle-exemple ``` Vérifiez avec `ls` que cette commande crée bien un exécutable `factorielle-exemple`. 4. Exécutez le programme `factorielle-exemple`. 5. Consultez le fichier [factorielle-test.cpp](factorielle-test.cpp). Créez un exécutable `factorielle-test` en adaptant les étapes ci-dessus, puis testez ce nouveau programme. 6. Une autre méthode pour compiler `factorielle-exemple` est de remplacer les trois commandes de la question (2) par la seule commande : ```shell clang++ factorielle.cpp factorielle-exemple.cpp -o factorielle-exemple ``` Supprimez les fichiers `factorielle.o`, `factorielle-exemple.o` et `factorielle-exemple` de votre dossier avec `rm`. Testez alors la commande précédente. Quel(s) fichier(s) ont été créés ? En déduire les différences avec la méthode précédente. Selon le cas vous pourrez être amené à choisir l'une ou l'autre, notamment dans le projet. +++ {"deletable": false, "nbgrader": {"cell_type": "markdown", "checksum": "59273bbf62585665b44663bfd10af06c", "grade": true, "grade_id": "cell-4234cd29242a210b", "locked": false, "points": 0, "schema_version": 3, "solution": true, "task": false}} % REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "f49d0ae7077b8d73d8bb2d37e0d9b548", "grade": false, "grade_id": "cell-41bec4fdd73fc56d", "locked": true, "schema_version": 3, "solution": false}} ### Exercice : compilation séparée +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "0aa22e643a0731f21a052d645349ad26", "grade": false, "grade_id": "cell-89f33130471fc08e", "locked": true, "schema_version": 3, "solution": false}} - Ouvrez le fichier [fibonacci.cpp](fibonacci.cpp) et regardez son contenu. Remarquez que la fonction `main` mélange deux actions de nature très différente : d'une part lancer les tests de la fonction `fibonacci`, et d'autre part utiliser cette fonction pour interagir avec l'utilisateur. Ceci n'est pas très satisfaisant. - Réorganisez le fichier [fibonacci.cpp](fibonacci.cpp) en plusieurs fichiers en suivant le modèle de l'exercice précédent. Il y aura donc quatre fichiers : - [fibonacci.hpp](fibonacci.hpp), - [fibonacci.cpp](fibonacci.cpp), - [fibonacci-test.cpp](fibonacci-test.cpp), - [fibonacci-exemple.cpp](fibonacci-exemple.cpp). Faites attention à ne pas dupliquer de code. +++ {"deletable": false, "nbgrader": {"cell_type": "markdown", "checksum": "a4f6c0ddadb36456443415b37c208e20", "grade": true, "grade_id": "cell-465531ee3287b0fd", "locked": false, "points": 0, "schema_version": 3, "solution": true, "task": false}} % REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "ed2c4d1d7c8b563e2a33580c914aa9d6", "grade": false, "grade_id": "cell-89f33130471fc08f", "locked": true, "schema_version": 3, "solution": false}} - Quels exécutables allez-vous construire? Pour chaque exécutable, quels fichiers allez-vous combiner pour l'obtenir ? Vérifiez pour chaque exécutable que chaque fonction utilisée (dont la fonction `main`) est définie une et une seule fois dans l'ensemble de fichiers correspondant. +++ {"deletable": false, "nbgrader": {"cell_type": "markdown", "checksum": "281b7879783dc8e34eb42c3ff453b1d7", "grade": true, "grade_id": "cell-465531ee3287b0fe", "locked": false, "points": 0, "schema_version": 3, "solution": true, "task": false}, "tags": []} % REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "eb352fd592187fcac4ce19570c7bc952", "grade": false, "grade_id": "cell-89f33130471fc08g", "locked": true, "schema_version": 3, "solution": false}} - Compilez chacun des deux programmes (test et exemple) grâce à la compilation séparée, exécutez les et vérifiez que tout fonctionne correctement. En cas d'erreur, lisez le message d'erreur puis comparez attentivement vos fichiers et commandes avec ceux donnés pour la fonction `factorielle` (si vous avez la feuille de TD sous la main, l'énoncé de l'exercice 1 permet de visualiser facilement tous les fichiers pour factorielle). Notez ci-dessous les commandes utilisées pour la compilation : +++ {"deletable": false, "nbgrader": {"cell_type": "markdown", "checksum": "1f1981e9323fd07e1e67885afb851325", "grade": true, "grade_id": "cell-465531ee3287b0ff", "locked": false, "points": 0, "schema_version": 3, "solution": true, "task": false}} % REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "7c740bf5fd075394305a0f98d1dd0422", "grade": false, "grade_id": "cell-96bafcc3c30ace6e", "locked": true, "schema_version": 3, "solution": false}} ### Exercice : Premiers graphiques avec Jupyter 1. Refaites l'exercice 2 du [TD](TD.md) en complétant la feuille [premier-dessin](premier-dessin.md). Implantez chacun des items en vérifiant à chaque fois le résultat. +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "e883c664c0706a830228145c1004b74a", "grade": false, "grade_id": "cell-96bafcc3c30ace6f", "locked": true, "schema_version": 3, "solution": false}} ### Exercice : Premiers graphiques avec SFML ♣ :::{attention} Il n'est à l'heure actuelle pas encore possible d'utiliser le serveur JupyterHub pour cet exercice. Il est donc à effectuer en local en salle de TP (ou sur votre machine personnelle si vous avez les logiciels requis). Si vous n'avez pas eu le temps de le faire en séance de TP, ce n'est pas critique pour l'avancement de votre projet. Aussi est-il marqué d'un ♣. ::: Pour installer les logiciels requis sur votre machine personnelle, voir les sections « Aide à l'installation » sur la [page logiciels du site du cours](http://nicolas.thiery.name/Enseignement/Info111/logiciels/#aide-installation). À noter que, pour utiliser la SFML sur CodeBlocks ou tout autre environnement de développement intégré (IDE), il faut configurer l'IDE. Plus encore que d'habitude, nous recommandons de compiler en ligne de commande dans le terminal. Pour l'instant, en salle de TP, il est nécessaire d'utiliser `info-111 compile` pour compiler un programme utilisant SFML. 1. Ouvrez les fichiers [exemple-graphisme1.cpp](exemple-graphisme1.cpp) et [primitives.hpp](primitives.hpp) et consultez le premier. 2. Compilez ce programme depuis le terminal avec (en une seule ligne !) : ```shell info-111 compile exemple-graphisme1.cpp primitives.cpp -o exemple-graphisme1 -lsfml-system -lsfml-window -lsfml-graphics ``` Explication : le code binaire de SFML est réparti dans trois bibliothèques `sfml-system`, `sfml-window` et `sfml-graphics`. Les arguments `-lsfml-system`, ... indiquent au compilateur de les lier au programme (`-l` pour *link*). 3. Lancez le programme obtenu avec : ```shell ./exemple-graphisme1 ```` Vous obtenez une fenêtre blanche, avec un (tout petit!) point rouge un peu à gauche, près du bord haut. 4. Compilez le programme fourni [premier-dessin.cpp](premier-dessin.cpp) en adaptant la commande utilisée plus haut pour compiler [exemple-graphisme1.cpp](exemple-graphisme1.cpp). Complétez [premier-dessin.cpp](premier-dessin.cpp) à partir de la feuille [premier-dessin](premier-dessin.md). N'hésitez pas à changer la valeur de la variable `delai` pour voir le résultat s'afficher plus longtemps. +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "851f78b272e43edba563532592fc2279", "grade": false, "grade_id": "cell-eaefcdbc75785adb", "locked": true, "schema_version": 3, "solution": false}} ### Exercice ♣ : Souris et clavier 1. Pour vous donner une idée de l'utilisation de la SFML et de notre bibliothèque de primitives, lisez attentivement [primitives.hpp](primitives.hpp) et sa documentation. 2. Consultez ensuite [exemple-graphisme2.cpp](exemple-graphisme2.cpp) et [exemple-graphisme3.cpp](exemple-graphisme3.cpp) pour en voir des exemples d'utilisation. 3. Implantez l'exercice 4 du TD. <!-- Solutions dans le TD !--> +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "5917c7b9cfd1dcba875ca0c00faa1060", "grade": false, "grade_id": "cell-5858dbcffa05aed3", "locked": true, "schema_version": 3, "solution": false}} ### Exercice ♣: Couche d'abstraction Pour vous approprier la couche d'abstraction, consultez son implantation dans `primitives.cpp`. En vous inspirant de ce qui est déjà fait, complétez l'implantation de la fonction `draw_filled_rectangle` (documentée dans `primitives.hpp`). Vous pouvez vous aider de la [documentation en ligne de la SFML](https://www.sfml-dev.org/learn-fr.php). +++ {"deletable": false, "nbgrader": {"cell_type": "markdown", "checksum": "61093ad3aeea2b37d7ce02c5c02d54cb", "grade": true, "grade_id": "cell-48f3d0b08106b27d", "locked": false, "points": 0, "schema_version": 3, "solution": true, "task": false}} % REMPLACEZ CETTE LIGNE PAR VOTRE RÉPONSE +++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "346c0470eb0efbaa0d4446698ec913d5", "grade": false, "grade_id": "cell-48f3d0b08106b27e", "locked": true, "schema_version": 3, "solution": false, "task": false}} ### Exercice ♣: Jeu du Yams Reprenez le jeu du Yams du TP 6 en ajoutant une interface graphique. On affichera les dés (soit avec du texte, soit avec des points) dans la fenêtre. Revoyez [exemple-graphisme3.cpp](exemple-graphisme3.cpp) pour des fonctions rapides. L'utilisateur pourra cliquer sur les dés à combiner pour former une figure. (Utiliser par exemple `wait_mouse()` pour cliquer sur les dés, et `wait_keyboard()` pour valider.) Le nombre de points sera ensuite affiché. À vous de concevoir les fonctions à introduire pour décomposer le problème.