Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Commits on Source (7)
Showing
with 1327 additions and 240 deletions
No preview for this file type
GRAPHIC_PROGS=$(wildcard exemple-graphisme*.cpp segment*.cpp cercle*.cpp premier-dessin*.cpp disque*.cpp souris*.cpp)
OTHER_PROGS=$(wildcard factorielle-*.cpp) fibonacci-exemple fibonacci-test
OTHER_PROGS=$(wildcard factorielle-*.cpp) fibonacci-exemple.cpp fibonacci-test.cpp programme1.cpp programme2.cpp max-test.cpp puissance4.cpp
PROGS=$(GRAPHIC_PROGS) $(OTHER_PROGS)
TARGET=$(PROGS:%.cpp=%)
......@@ -30,5 +30,5 @@ $(GRAPHIC_PROGS:%.cpp=%): %: %.o primitives.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ -lsfml-window -lsfml-graphics -lsfml-system
clean:
-rm -rf $(TARGET) *.o
-rm -rf $(TARGET) *.o puissance-quatre.s
......@@ -33,30 +33,29 @@ rise:
## Résumé de la séance
**Programmes et compilation :**
:::{admonition} Programmes et compilation
- Algorithme, programme, sources, binaire, assembleur
- Interpréteur, compilateur
- Cycle de vie d'un programme
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Compilation séparée pour la modularité :**
:::{admonition} Compilation séparée pour la modularité
- Découper un programme non seulement en fonctions, mais en fichiers
- Bibliothèque de fonctions réutilisables entre programmes
- Définir des bibliothèque de fonctions réutilisables entre programmes :
- fichier d'entêtes : `max.hpp`
- fichier source : `max.cpp`
- fichier de tests : `maxTest.cpp`
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Digressions :**
:::{admonition} Digressions
- Surcharge : un nom, plusieurs fonctions
- Templates : une fonction, plusieurs types
- Espaces de noms
- Espaces de noms : pour éviter les conflits de noms
:::
+++ {"slideshow": {"slide_type": "slide"}}
......@@ -64,14 +63,14 @@ rise:
+++ {"slideshow": {"slide_type": "fragment"}}
**Développement incrémental :**
:::{hint} Bonne pratique : développement incrémental
- Toujours être «proche de quelque chose qui marche»
- Gestion de version (`git`, `mercurial`, ...)
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Spécifications et tests :**
:::{admonition} Bonnes pratiques : spécifications et tests
- Spécification : définir précisément la sémantique des fonctions :
qu'est-ce qu'elles doivent faire?
......@@ -80,38 +79,39 @@ rise:
+++ {"slideshow": {"slide_type": "fragment"}}
**Modularité :**
:::{hint} Bonne pratique : modularité
- Découpage d'un programme en fonctions : [**cours 4**](../Semaine4/cours.md)
- Découpage d'un programme en modules : **aujourd'hui !**
- Découpage d'un programme en espace de noms : **plus tard**
- Découpage d'un programme en espaces de noms : **plus tard**
:::
+++ {"slideshow": {"slide_type": "slide"}}
### Conclusion : qu'avez-vous vu ce semestre?
### Conclusion : qu'avons nous vu ce semestre?
+++ {"slideshow": {"slide_type": "fragment"}}
**Les bases de la programmation impérative**
:::{admonition} Les bases de la programmation
- Contrôle du flot d'exécution : instructions conditionnelles et itératives, fonctions
- Gestion des données : variables, tableaux, collections, entrées et sorties, fichiers
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Méthodologie de développement**
:::{admonition} Méthodologie de développement
- Développement incrémental
- Spécifications et tests
- Modularité
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Une esquisse de quelques thèmes de l'informatique**
:::{admonition} Une esquisse de quelques thèmes de l'informatique
- Programmation modulaire (S2)
- Algorithmes et structures de données, complexité (S2)
- Science des données (S2)
- Web, graphisme, architecture, réseau, ...
:::
+++ {"slideshow": {"slide_type": "fragment"}}
......
......@@ -29,21 +29,19 @@ rise:
## Revenons à la recette de la mousse au chocolat
**Ingrédients :**
:::{admonition} Ingrédients
:icon: false
250 g de chocolat, 125 g de beurre, 6 œufs, 50 g de sucre, café
:::
**Étapes :**
:::{admonition} Étapes
:icon: false
- Faire fondre le chocolat avec deux cuillères d'eau
- Ajouter le beurre, laisser refroidir puis ajouter les jaunes
- Ajouter le sucre et comme parfum un peu de café
- Battre les blancs jusqu'à former une neige uniforme
- Ajouter au mélange
:::
+++ {"slideshow": {"slide_type": "fragment"}}
......@@ -53,9 +51,11 @@ rise:
Pour répondre à cette question, revenons à la définition :
**Programme** (rappel) : séquence d'**instructions** qui spécifie,
:::{prf:definition} **Programme** (rappel)
Séquence d'**instructions** qui spécifie,
étape par étape, les opérations à effectuer pour obtenir, à partir des
**entrées**, un résultat, la **sortie**.
:::
+++ {"slideshow": {"slide_type": "slide"}}
......@@ -90,12 +90,17 @@ Cela nous amène naturellement à la question suivante :
+++ {"slideshow": {"slide_type": "slide"}}
## Au commencement était l'« assembleur »
## Au commencement était l'assembleur
L'assembleur est le langage que comprend directement l'ordinateur.
:::{prf:definition} Assembleur
L'***assembleur*** est le langage que comprend directement l'ordinateur.
Chaque instruction correspond à une opération élémentaire que peut
effectuer le processeur :
effectuer le processeur.
:::
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
:::{prf:example}
``` nasm
mov -0x1c(%rbp), %edx
mov -0x1c(%rbp), %eax
......@@ -105,12 +110,13 @@ effectuer le processeur :
imul -0x18(%rbp), %eax
mov %eax, -0x14(%rbp)
```
Voyons cet exemple de plus près.
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Exercice :**
Voyons cet exemple de plus près.
:::{exercise}
Exécuter ce fragment d'*assembleur* en suivant les indications
suivantes :
......@@ -122,6 +128,7 @@ suivantes :
- `imul a, b` : multiplier le contenu de a par celui de b et mettre le
résultat dans b
- Initialiser le contenu de la case `%-0x1c(%rbp)` à $3$
:::
+++ {"slideshow": {"slide_type": "fragment"}}
......@@ -139,7 +146,7 @@ bien content de ne pas avoir à programmer tout le temps en assembleur.
**Ce que je veux :**
« Calculer la puissance 4 d'un nombre »
« Calculer la puissance quatrième d'un nombre »
+++ {"slideshow": {"slide_type": "fragment"}}
......@@ -160,7 +167,9 @@ bien content de ne pas avoir à programmer tout le temps en assembleur.
+++ {"slideshow": {"slide_type": "fragment"}}
**Passer de l'un à l'autre ne va pas se faire tout seul**. Il va
falloir un peu de méthode ; c'est le cycle de vie d'un programme.
falloir un peu de méthode.
C'est le **cycle de vie d'un programme**.
+++ {"slideshow": {"slide_type": "slide"}}
......@@ -172,47 +181,48 @@ fonctionnel.
+++ {"slideshow": {"slide_type": "fragment"}}
#### Problème
« Calculer la puissance 4 d'un nombre »
:::{admonition} Problème
« Calculer la puissance quatrième d'un nombre »
:::
+++ {"slideshow": {"slide_type": "fragment"}}
#### Formalisation
:::{admonition} Formalisation
Spécification des **entrées** et des **sorties**
- Spécification des **entrées** et des **sorties**
Scénario d'utilisation : « l'utilisateur rentre au clavier un nombre
entier $x$ ; l'ordinateur affiche en retour la valeur de $x^4$ à l'écran »
- Scénario d'utilisation : « l'utilisateur saisit au clavier un nombre
entier $x$ ; l'ordinateur affiche la valeur de $x^4$ à l'écran »
:::
+++ {"slideshow": {"slide_type": "fragment"}}
#### Recherche d'un algorithme
:::{admonition} Recherche d'un algorithme
- Comment on résout le problème ?
- Quel **traitement** appliquer à l'entrée pour obtenir la sortie
désirée ?
:::
+++ {"slideshow": {"slide_type": "fragment"}}
On note que $x^4=x * x * x * x = (x^2)^2$
Cela nous donne un **algorithme** :
+++ {"slideshow": {"slide_type": "fragment"}}
Cela nous donne un **algorithme** :
- calculer $x*x$
- prendre le résultat et faire de même
+++ {"slideshow": {"slide_type": "slide"}}
#### Digression : La notion d'algorithme
**Définition : Algorithme**
### Digression : La notion d'algorithme
:::{prf:definition} Algorithme
- Description formelle d'un procédé de traitement qui permet, à partir
d'un ensemble d'informations initiales, d'obtenir des informations
déduites
- Succession finie et non ambiguë d'opérations clairement posées
:::
+++ {"slideshow": {"slide_type": "fragment"}}
......@@ -220,7 +230,7 @@ Quelle différence entre un **algorithme** et un **programme** ?
+++ {"slideshow": {"slide_type": "fragment"}}
Un algorithme
Un algorithme:
- doit toujours se terminer !
- est conçu pour communiquer entre humains
- est un concept indépendant du langage dans lequel il est écrit
......@@ -249,7 +259,7 @@ En assembleur ???
+++ {"slideshow": {"slide_type": "fragment"}}
En C++ :
**En C++ :**
Entrée :
......@@ -274,26 +284,26 @@ Sortie :
#### Niveaux de langages de programmation
+++ {"slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
**Langage machine (binaire) :**
Un programme y est directement compréhensible par la machine
+++ {"slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
**Langage d'assemblage (ou assembleur) :**
Un programme y est traduisible mot-à-mot en langage machine
+++ {"slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
**Langage de programmation :**
En général, un programme doit être **transformé** pour être compris
par la machine
+++ {"slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
Comment faire cette transformation ? À la main ?
......@@ -328,10 +338,10 @@ Basic, Javascript, LISP, Perl, Python, C++, ...
**Exemple : compilation en C++ :**
- Programme source : `puissance-quatre.cpp`
- Compilation : `g++ puissance-quatre.cpp -o puissance-quatre`
- Compilation : `clang++ puissance-quatre.cpp -o puissance-quatre`
- Programme objet (ou binaire) : `puissance-quatre`
- Exécution : `./puissance-quatre`
- Fabrication de l'assembleur : `g++ -S puissance-quatre.cpp`
- Fabrication de l'assembleur : `clang++ -S puissance-quatre.cpp`
- Programme en assembleur : `puissance-quatre.s`
+++ {"slideshow": {"slide_type": "fragment"}}
......@@ -357,29 +367,29 @@ ADA, C, C++, FORTRAN, Java, Pascal, ...
### Exécution et mise au point
**Exécuter le programme :**
:::{admonition} Exécuter le programme
- Autant de fois que l'on veut !
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Tester que le programme fonctionne :**
:::{admonition} Tester que le programme fonctionne
- En n'oubliant pas les cas particuliers !!!
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Mise au point :**
:::{admonition} Mise au point
- Correction d'erreurs
- Optimisation du programme (consommation de ressources: temps, mémoire, énergie, ...)
- Optimisation de l'algorithme
- Amélioration du programme (lisibilité, généralisation)
:::
+++ {"slideshow": {"slide_type": "fragment"}}
À chaque fois, on reboucle sur l'étape de compilation, voire de
conception, d'où le terme de cycle de vie.
conception, d'où le terme de **cycle de vie**.
+++ {"slideshow": {"slide_type": "slide"}}
......@@ -391,8 +401,7 @@ s'appuyer sur un peu de
+++ {"slideshow": {"slide_type": "fragment"}}
**Méthodologie :**
:::{admonition} Méthodologie
1. Énoncé du problème
2. Formalisation (quel est le problème précisément ?)
3. Recherche d'un algorithme (comment résoudre le problème ?)
......@@ -400,6 +409,7 @@ s'appuyer sur un peu de
5. Interprétation / Compilation
6. Exécution
7. Mise au point (test, débogage, optimisation, diffusion)
:::
+++ {"slideshow": {"slide_type": "skip"}}
......
......@@ -30,32 +30,27 @@ rise:
# Digressions : surcharge, templates, espaces de noms, ...
Nous allons maintenant faire quelques digressions, pour pointer vers
des fonctionnalités de C++ que nous avons utilisées sans explication
jusqu'ici, et dont l'usage simple est naturel et potentiellement utile
dès maintenant.
des fonctionnalités de C++ que nous avons utilisées sans explications
jusqu'ici, et dont l'usage est naturel et potentiellement utile dès
maintenant.
+++ {"slideshow": {"slide_type": "fragment"}}
+++ {"slideshow": {"slide_type": "slide"}, "tags": []}
## Surcharge de fonctions ♣
```{code-cell}
---
slideshow:
slide_type: fragment
---
using namespace std;
```
+++ {"slideshow": {"slide_type": "fragment"}}
### Exemple : la fonction `monMax`
+++ {"slideshow": {"slide_type": "skip"}, "tags": []}
Nous avons vu maintes fois la fonction `max` sur les entiers :
```{code-cell}
---
slideshow:
slide_type: '-'
slide_type: fragment
tags: []
---
int monMax(int a, int b) {
if ( a < b )
......@@ -63,17 +58,11 @@ int monMax(int a, int b) {
else
return a;
}
```
```{code-cell}
---
slideshow:
slide_type: '-'
---
monMax(1,3)
```
+++ {"slideshow": {"slide_type": "fragment"}}
+++ {"slideshow": {"slide_type": "skip"}, "tags": []}
On remarquera que le code est générique : on peut par exemple calculer
de même le maximum de deux nombres réels :
......@@ -81,7 +70,8 @@ de même le maximum de deux nombres réels :
```{code-cell}
---
slideshow:
slide_type: '-'
slide_type: fragment
tags: []
---
double monMax(double a, double b) {
if ( a < b)
......@@ -89,102 +79,104 @@ double monMax(double a, double b) {
else
return a;
}
```
```{code-cell}
---
slideshow:
slide_type: '-'
---
monMax(1.0, 3.5)
```
+++ {"slideshow": {"slide_type": "fragment"}}
+++ {"slideshow": {"slide_type": "skip"}, "tags": []}
ou même de deux chaînes de caractères :
```{code-cell}
---
slideshow:
slide_type: '-'
slide_type: fragment
tags: []
---
using namespace std;
```
```{code-cell}
:tags: []
string monMax(string a, string b) {
if ( a < b)
return b;
else
return a;
}
```
```{code-cell}
---
slideshow:
slide_type: '-'
---
monMax("toto", "alfred")
```
+++ {"slideshow": {"slide_type": "fragment"}}
Vous remarquerez que l'on a utilisé le même nom de fonction, et que
:::{hint} Observation
Nous avons utilisé chaque fois le même nom de fonction et
`C++` a appelé automatiquement la bonne version.
:::
+++ {"slideshow": {"slide_type": "fragment"}}
:::{hint} Remarque
Il serait de même possible d'utiliser le même nom de fonction pour le
max à trois arguments (et plus!) :
:::
```{code-cell}
---
slideshow:
slide_type: '-'
---
:tags: []
int monMax(int a, int b, int c) {
return monMax(monMax(a, b), c);
}
```
```{code-cell}
---
slideshow:
slide_type: '-'
---
monMax(2,4,3)
```
+++ {"slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
Mais attention aux ambiguïtés :
:::{attention} Attention aux ambiguïtés
<br>
:::
```{code-cell}
---
slideshow:
slide_type: '-'
---
:tags: []
monMax(3, 4.5)
```
+++ {"slideshow": {"slide_type": "slide"}}
### Surcharge de fonction : résumé
+++ {"slideshow": {"slide_type": "slide"}, "tags": []}
:::{prf:definition} ***Surcharge de fonction***
- En C++, on peut avoir plusieurs fonctions avec le même nom et des
signatures différentes
- Idem en Java, mais pas en C ou en Python par exemple!
:::
- Il est recommandé que toutes les fonctions ayant le même nom aient
la même *sémantique*
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
+++ {"slideshow": {"slide_type": "fragment"}}
:::{hint} Bonne pratique
Il est recommandé que toutes les fonctions ayant le même nom aient
la même *sémantique*
:::
+++ {"slideshow": {"slide_type": "slide"}, "tags": []}
## Digression : templates ♣
:::{warning} Problème
L'exemple précédent n'est pas satisfaisant : on a dû implanter la
fonction `monMax` pour chaque type sur lequel on peut faire une
comparaison, en dupliquant le même code.
:::
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
Correctif : les *templates* pour écrire du code *générique*
:::{hint} Solution
Les ******templates****** pour écrire du code *générique*
:::
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
La fonction `monMax` suivante est valide pour tout type sur lequel on
peut faire des comparaisons :
......@@ -216,6 +208,7 @@ monMax(1,3)
slideshow:
slide_type: fragment
---
using namespace std;
monMax(string("toot"), string("alfred"))
```
......@@ -243,27 +236,30 @@ Les détails seront pour un autre cours!
## Digression : espaces de noms ♣
**Problème :**
:::{warning} Problème
Des milliers de développeurs écrivent des bibliothèques, bibliothèques
qui sont par la suite combinées entre elles de multiples façons non
anticipées à l'origine. Comment s'assurer qu'il n'y a pas de conflit
anticipées à l'origine.
Comment s'assurer qu'il n'y a pas de conflit
entre deux fonctions portant le même nom et la même signature dans
deux bibliothèques différentes?
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Solution :**
Isoler chaque bibliothèque dans un *espace de noms*.
:::{hint} Solution
Isoler chaque bibliothèque dans un ******espace de noms******
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Exemple :**
:::{prf:example}
La bibliothèque standard C++ utilise l'espace de nom `std`. Ainsi,
dans le programme suivant, il faudrait en principe mettre `std`
devant `cout`, et `endl` :
devant `cout`, et `endl`.
:::
```{code-cell}
---
......@@ -279,12 +275,14 @@ int main() {
+++ {"slideshow": {"slide_type": "fragment"}}
:::{hint} Explication
Notre incantation magique :
``` c++
using namespace std;
```
dit simplement de définir des raccourcis pour rendre accessible
directement tout ce qui est défini dans l'espace de nom `std`.
:::
+++ {"slideshow": {"slide_type": "fragment"}}
......
......@@ -25,7 +25,7 @@ rise:
width: 90%
---
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "f003d1fe379fe84ce034a14aea0c8147", "grade": false, "grade_id": "cell-bc2bac01a1ae5d6e", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
# Modularité, compilation séparée
......@@ -36,40 +36,39 @@ petit bout, d'éviter les redites, etc.
Nous allons de même **découper un programme en plusieurs fichiers**.
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "c32639e12e6a2b647ff43343efe728db", "grade": false, "grade_id": "cell-bc2bac01a1ae5d6f", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
## Compilation séparée
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "9497653142bbd1f090931e2db5641f75", "grade": false, "grade_id": "cell-eda0e2d6022d648b", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
+++ {"slideshow": {"slide_type": "fragment"}}
### Exemple
Considérons les trois programmes suivants :
+++ {"slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
Dans Jupyter :
```{code-cell}
---
slideshow:
slide_type: '-'
---
#include <iostream>
:tags: []
#include "max_simpliste.hpp"
int monMax(int a, int b) {
if ( a >= b )
return a;
else
return b;
}
```
```{code-cell}
monMax(10, 1)
```
+++ {"slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}, "tags": []}
[programme1.cpp](programme1.cpp) : maximum de deux entiers, avec un exemple
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "1492e87493155542d8d49436f01e4b91", "grade": false, "grade_id": "cell-eda0e2d6022d648c", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "-"}}
``` c++
#include <iostream>
using namespace std;
......@@ -80,20 +79,17 @@ int monMax(int a, int b) {
else
return b;
}
```
``` c++
int main() {
cout << monMax(1, 3) << endl;
return 0;
}
```
+++ {"slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}, "tags": []}
[programme2.cpp](programme2.cpp) : maximum de deux entiers, avec interactivité
+++ {"slideshow": {"slide_type": "-"}}
``` c++
#include <iostream>
using namespace std;
......@@ -104,9 +100,7 @@ int monMax(int a, int b) {
else
return b;
}
```
``` c++
int main() {
cout << "Entrez a et b:" << endl;
int a, b;
......@@ -122,7 +116,7 @@ int main() {
On constate une **répétition** : les trois programmes définissent exactement
la même fonction `monMax`, qu'ils utilisent ensuite différemment.
Pourrait-on partager la fonction `monMax` entre ces trois programmes ?
Pourrait-on **partager** la fonction `monMax` entre ces trois programmes ?
C'est ce que nous allons faire en définissant une mini-bibliothèque.
Voyons à quoi cela ressemble.
......@@ -148,7 +142,7 @@ int monMax(int a, int b) {
+++ {"slideshow": {"slide_type": "fragment"}}
Pour utiliser cette bibliothèque, il suffit de l'***inclure*** :
Pour utiliser cette bibliothèque, il suffit de l'******inclure****** :
```{code-cell}
#include "max_simpliste.hpp"
......@@ -160,25 +154,26 @@ monMax(1, 3)
+++ {"slideshow": {"slide_type": "fragment"}}
<div class="alert alert-warning">
:::{attention}
On appelle cela une bibliothèque en ***entêtes seuls*** (***header only***).
On appelle cela une bibliothèque en ******entêtes seuls****** (******header only******).
En `C++`, il y a des cas d'usage où cela peut être pertinent.
Il y a de sérieuses limitations à cette façon de structurer une bibliothèque.
Dans ce cours on évitera.
:::
</div>
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "579b25dc89bdc9c0252cfe90d3f976b0", "grade": false, "grade_id": "cell-04d9ac7b73aa7155", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
#### Exemple : une bibliothèque `max` dans les règles
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "bcc5994c592a52d4141024a74fe4ad11", "grade": false, "grade_id": "cell-04d9ac7b73aa7156", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
+++ {"slideshow": {"slide_type": "fragment"}}
% TODO: ici et dans les pages suivantes: use literalinclude
Contenu du fichier `max.hpp` :
Contenu du fichier [max.hpp](max.hpp) :
``` c++
/** La fonction max
* @param x, y deux entiers
......@@ -190,7 +185,7 @@ int monMax(int a, int b);
+++ {"slideshow": {"slide_type": "fragment"}}
Contenu du fichier `max.cpp` :
Contenu du fichier [max.cpp](max.cpp) :
``` c++
#include "max.hpp"
......@@ -204,10 +199,11 @@ int monMax(int a, int b) {
+++ {"slideshow": {"slide_type": "slide"}}
#### Exemple : deux programmes utilisant la bibliothèque max
#### Exemple : deux programmes utilisant la bibliothèque `max`
+++ {"slideshow": {"slide_type": "fragment"}}
Contenu du fichier [programme1.cpp](programme1.cpp):
``` c++
#include <iostream>
using namespace std;
......@@ -221,6 +217,7 @@ int main() {
+++ {"slideshow": {"slide_type": "fragment"}}
Contenu du fichier [programme2.cpp](programme2.cpp):
``` c++
#include <iostream>
using namespace std;
......@@ -236,13 +233,13 @@ int main() {
}
```
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "4660ee07cdbb406ba256477ea7c4fc59", "grade": false, "grade_id": "cell-c0ee9ca9166c339f", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
#### Exemple : les tests de la bibliothèque `max`
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "12530a4d02fe03e35ea980f1ee58d2b0", "grade": false, "grade_id": "cell-c0ee9ca9166c339g", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
+++ {"slideshow": {"slide_type": "fragment"}}
Contenu du fichier `max-test.cpp` :
Contenu du fichier [max-test.cpp](max-test.cpp) :
``` c++
#include <iostream>
using namespace std;
......@@ -251,8 +248,7 @@ using namespace std;
/** Infrastructure minimale de test **/
#define CHECK(test) if (!(test)) cerr << "Test failed in file " << __FILE__ << " line " << __LINE__ << ": " #test << endl
```
``` c++
void monMaxTest() {
CHECK( monMax(2,3) == 3 );
CHECK( monMax(5,2) == 5 );
......@@ -264,7 +260,7 @@ int main() {
}
```
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "787972a2428cc04cb9217d9a030d58c4", "grade": false, "grade_id": "cell-fdf12d05bb0ffe32", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
### Qu'avons-nous vu ?
......@@ -274,59 +270,63 @@ int main() {
+++ {"slideshow": {"slide_type": "fragment"}}
**Syntaxe :**
:::{admonition} Syntaxe
``` c++
int monMax(int a, int b);
```
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Sémantique :**
- Le programme *définit* quelque part une fonction `monMax` avec cette
*signature* :
:::{admonition} Sémantique
- Le programme ******définit****** quelque part une fonction `monMax` avec cette
******signature****** :
type des paramètres et type du résultat
- Cette définition n'est pas forcément dans le même fichier
- Si cette définition n'existe pas ou n'est pas unique, une erreur est
déclenchée par le compilateur
- Cette erreur est déclenchée au moment où l'on combine les différents
fichiers
Édition de liens; voir plus loin
fichiers : voir plus loin «Édition de liens»
+++ {"slideshow": {"slide_type": "fragment"}}
**♣ Application :**
:::{hint} ♣ Application
Deux fonctions qui s'appellent réciproquement
:::
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "b3709f14a593cf15abcc96057044e99f", "grade": false, "grade_id": "cell-26e5cd21217b8ec5", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
#### Compilation séparée (1)
- Un programme peut être composé de plusieurs ***fichiers source***
Contenu :
- Des *définitions* de fonctions
- Des définitions de fonctions
- Des variables globales, ...
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
- Chaque fichier source est compilé en un ***fichier objet*** (extension : .o)
Contenu :
- Le code binaire des fonctions, ...
- L'*éditeur de liens* combine plusieurs fichiers objet en un
*fichier exécutable*
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
- L'******éditeur de liens****** combine plusieurs fichiers objet en un
******fichier exécutable******
+++ {"slideshow": {"slide_type": "fragment"}}
Voyons cela pour un programme voulant utiliser la bibliothèque `max` :
Les sources sont `max.cpp` et `programme.cpp`.
Les sources sont [max.cpp](max.cpp) et [programme.cpp](programme.cpp).
+++ {"slideshow": {"slide_type": "fragment"}}
On les compile séparément avec :
```shell
g++ -c max.cpp
g++ -c programme.cpp
clang++ -c max.cpp
clang++ -c programme.cpp
```
Cela produit les fichiers objets `max.o` et `programme.o`. Chacun est
......@@ -334,13 +334,17 @@ un bout incomplet de programmes binaires : `max.o` contient le code
binaire de la fonction `max` mais pas la fonction `main`, et
réciproquement pour `programme.o`.
+++ {"slideshow": {"slide_type": "fragment"}}
Il ne reste plus qu'à combiner ces deux bouts de programmes binaires
pour obtenir un programme complet.
```shell
g++ programme.o max.o -o programme
clang++ programme.o max.o -o programme
```
+++ {"slideshow": {"slide_type": "fragment"}}
Maintenant, on peut exécuter le programme obtenu autant de fois qu'on
le souhaite :
......@@ -348,135 +352,138 @@ le souhaite :
./programme
```
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "0d83630ea4ed4d5d557e122d963571f8", "grade": false, "grade_id": "cell-de97499851e34054", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
#### Compilation séparée (2)
**Au moment de l'édition de lien :**
- Chaque fonction utilisée doit être définie une et une seule fois
- La fonction `main` doit être définie une et une seule fois
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "ce17de7f5b94f7bb286b8110e5437571", "grade": false, "grade_id": "cell-de97499851e34055", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
- Chaque fonction utilisée **doit être définie une et une seule fois**
- La fonction `main` **doit être définie une et une seule fois**
**Quelques variantes autour des fichiers objets :**
+++ {"slideshow": {"slide_type": "fragment"}}
:::{hint} ♣ Quelques variantes autour des fichiers objets
- Bibliothèques (.a) :
Une archive contenant plusieurs fichiers objets .o
- Bibliothèques dynamiques (.so) :
Édition de lien dynamique au lancement du programme
:::
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "52664d050cdb13f6a766e3cbcc175719", "grade": false, "grade_id": "cell-e568b9b55cb70a3b", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
#### Fichiers d'entête
:::{prf:definition} Fichier d'entête
Fichier `.hpp` (ou `.h` en C) contenant la *déclaration* des fonctions *définies* dans
le fichier `.cpp` correspondant
:::
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "caf19989e2817546698bf5fbf404d630", "grade": false, "grade_id": "cell-e568b9b55cb70a3c", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
**Exemple :** Fichier d'entête `max.hpp`
+++ {"slideshow": {"slide_type": "fragment"}}
:::{prf:example} Fichier d'entête `max.hpp`
``` c++
int monMax(int a, int b);
```
:::
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "1e9959987853b8d9ed69ad76b649bbe2", "grade": false, "grade_id": "cell-e568b9b55cb70a3d", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
**Syntaxe :** Utilisation d'un fichier d'entête
+++ {"slideshow": {"slide_type": "fragment"}}
#### Utilisation d'un fichier d'entête
:::{admonition} Syntaxe
``` c++
#include "max.hpp"
```
**Sémantique :**
:::
:::{admonition} Sémantique
Utiliser la bibliothèque `max`
:::
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "7c7bbb13cb5d1fe766e13d181ac0e393", "grade": false, "grade_id": "cell-e568b9b55cb70a3e", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
+++ {"slideshow": {"slide_type": "fragment"}}
**Implantation en C++ :**
:::{hint} Implantation en C++
- Équivalent à copier-coller le contenu de `max.hpp` à l'emplacement du
`#include "max.hpp"`
- ♣ Géré par le préprocesseur (cpp)
:::
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "ff72d7aa40bd416b2c3dacc17f4839cb", "grade": false, "grade_id": "cell-1501d26cad5b60f2", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "slide"}}
#### Inclusion de fichiers d'entêtes standards
**Syntaxe :**
:::{admonition} Syntaxe
``` c++
#include <iostream>
```
:::
**Sémantique :**
:::{admonition} Sémantique
- Charge la déclaration de toutes les fonctions définies dans la
bibliothèque standard `iostream` de C++
- Le fichier `iostream` est recherché dans les répertoires standards
du système
- Sous linux : `/usr/include`, ...
:::
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "eeb3f33e690b970c5a4138874c58ed52", "grade": false, "grade_id": "cell-208ec2ed61304261", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "skip"}, "tags": []}
## Résumé
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "84c2764e1ac634a4c126e1fb2c9ed6f8", "grade": false, "grade_id": "cell-208ec2ed61304262", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
+++ {"slideshow": {"slide_type": "slide"}, "tags": []}
### Résumé : implantation d'une bibliothèque en C++
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "d26c3cdec520f8f76b0624b17f950fe6", "grade": false, "grade_id": "cell-208ec2ed61304263", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
**Écrire un fichier d'entête (max.hpp) :**
+++ {"slideshow": {"slide_type": "fragment"}}
:::{admonition} Écrire un fichier d'entête (max.hpp)
- La déclaration de toutes les fonctions publiques
- *Avec leur documentation !*
:::
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "9b390f6d19d63b7222aaf3e9ea2c2733", "grade": false, "grade_id": "cell-208ec2ed61304264", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
**Écrire un fichier source (max.cpp) :**
+++ {"slideshow": {"slide_type": "fragment"}}
:::{admonition} Écrire un fichier source (max.cpp)
- La définition de toutes les fonctions
- *Inclure le fichier .hpp !*
:::
+++ {"deletable": false, "editable": false, "nbgrader": {"cell_type": "markdown", "checksum": "b16ddc2f444fbd91507b32f1ad2bb135", "grade": false, "grade_id": "cell-208ec2ed61304265", "locked": true, "schema_version": 3, "solution": false, "task": false}, "slideshow": {"slide_type": "fragment"}}
**Écrire un fichier de tests (maxTest.cpp) :**
+++ {"slideshow": {"slide_type": "fragment"}}
:::{admonition} Écrire un fichier de tests (maxTest.cpp)
- Les fonctions de tests
- Une fonction `main` lançant tous les tests
:::
+++ {"slideshow": {"slide_type": "slide"}}
### Résumé : utilisation d'une bibliothèque en C++
**Inclusion des entêtes :**
:::{admonition} Inclusion des entêtes
```c++
#include <iostream> // fichier d'entête standard
#include "max.hpp" // fichier d'entête perso
```
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**Compilation :**
:::{admonition} Compilation
```shell
g++ -c max.cpp
g++ -c programme1.cpp
g++ max.o programme1.o -o programme1
clang++ -c max.cpp
clang++ -c programme1.cpp
clang++ max.o programme1.o -o programme1
```
:::
+++ {"slideshow": {"slide_type": "fragment"}}
**En une seule étape :**
:::{admonition} En une seule étape
```shell
g++ max.cpp programme1.cpp -o programme1
clang++ max.cpp programme1.cpp -o programme1
```
:::
+++ {"slideshow": {"slide_type": "skip"}, "tags": []}
## Suite
......
File added
---
jupytext:
text_representation:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.15.2
kernelspec:
display_name: C++17
language: C++17
name: xcpp17
---
### Objectif pédagogique : division entière
```{code-cell}
:editable: false
:tags: [hide-cell]
#include <iostream>
#include "jupyter_exercizer_helpers.hpp"
using namespace std;
```
+++
```{code-cell}
:tags: [hide-cell, variable]
CONST I1 = RANDOM_CHOICE(3, 5, 7);
I1
```
+++
```{code-cell}
:tags: [hide-cell, variable]
CONST I3 = RANDOM_CHOICE(1, 2, 4, 8, 11, 13, 16, 17, 19, 22);
I3
```
+++
```{code-cell}
:tags: [hide-output, substitution]
int r;
r = I3 / I1;
```
+++
:::{admonition} Consigne
Quelle est la valeur attendue de `r`?
:::
```{code-cell}
---
editable: true
nbgrader:
grade: false
grade_id: init
locked: false
schema_version: 3
solution: true
---
int result = INPUT(
/// BEGIN SOLUTION
I3 / I1
/// END SOLUTION
);
```
+++
```{code-cell}
---
editable: false
nbgrader:
grade: true
grade_id: check
locked: true
points: 1
schema_version: 3
solution: false
tags: [hide-cell]
---
CHECK( result == r );
```
---
jupytext:
text_representation:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.15.2
kernelspec:
display_name: C++17
language: C++17
name: xcpp17
---
### Objectif pédagogique : reste de la division entière
```{code-cell}
:editable: false
:tags: [hide-cell]
#include <iostream>
#include "jupyter_exercizer_helpers.hpp"
using namespace std;
```
+++
```{code-cell}
:tags: [hide-cell, variable]
CONST I1 = RANDOM_CHOICE(3, 5, 7);
I1
```
+++
```{code-cell}
:tags: [hide-cell, variable]
CONST I3 = RANDOM_CHOICE(1, 2, 4, 8, 11, 13, 16, 17, 19, 22);
I3
```
+++
```{code-cell}
:tags: [hide-output, substitution]
int r;
r = I3 % I1;
```
+++
:::{admonition} Consigne
Quelle est la valeur attendue de `r`?
:::
```{code-cell}
---
editable: true
nbgrader:
grade: false
grade_id: init
locked: false
schema_version: 3
solution: true
---
int result = INPUT(
/// BEGIN SOLUTION
I3 % I1
/// END SOLUTION
);
```
+++
```{code-cell}
---
editable: false
nbgrader:
grade: true
grade_id: check
locked: true
points: 1
schema_version: 3
solution: false
tags: [hide-cell]
---
CHECK( result == r );
```
---
jupyter:
jupytext:
text_representation:
extension: .md
format_name: myst
kernelspec:
display_name: C++17
language: C++17
name: xcpp17
---
### Objectif pédagogique : priorité des opérations
```{code-cell} c++
---
editable: false
tags: [hide-cell]
---
#include <iostream>
#include "jupyter_exercizer_helpers.hpp"
using namespace std;
```
+++
```{code-cell} c++
---
tags: [hide-cell, variable]
---
CONST I1 = RANDOM_INT(1, 7);
I1
```
+++
```{code-cell} c++
---
tags: [hide-cell, variable]
---
CONST I2 = RANDOM_INT(5, 12);
I2
```
+++
```{code-cell} c++
---
tags: [hide-cell, variable]
---
CONST I3 = RANDOM_INT(1, 7);
I3
```
+++
```{code-cell} c++
---
tags: [hide-output,substitution]
---
int r;
r = I2 + I1 * I3;
```
+++
:::{admonition} Consigne
Quelle est la valeur attendue de `r`?
:::
```{code-cell}
---
editable: true
nbgrader:
grade: false
grade_id: init
locked: false
schema_version: 3
solution: true
---
int result = INPUT(
/// BEGIN SOLUTION
I2 + I1 * I3
/// END SOLUTION
);
```
+++
```{code-cell}
---
editable: false
nbgrader:
grade: true
grade_id: check
locked: true
points: 1
schema_version: 3
solution: false
tags: [hide-cell]
---
CHECK( result == r );
```
---
jupyter:
jupytext:
text_representation:
extension: .md
format_name: myst
kernelspec:
display_name: C++17
language: C++17
name: xcpp17
---
### Objectif pédagogique : priorité des opérations
```{code-cell} c++
---
editable: false
tags: [hide-cell]
---
#include <iostream>
#include "jupyter_exercizer_helpers.hpp"
using namespace std;
```
+++
```{code-cell} c++
---
tags: [hide-cell, variable]
---
CONST I1 = RANDOM_INT(1, 5);
I1
```
+++
```{code-cell} c++
---
tags: [hide-cell, variable]
---
CONST I2 = RANDOM_INT(1, 3);
I2
```
+++
```{code-cell} c++
---
tags: [hide-cell, variable]
---
CONST I3 = RANDOM_INT(1, 7);
I3
```
+++
```{code-cell} c++
---
tags: [hide-output,substitution]
---
int r;
r = (I2 PLUSOUMOINS I1) * I3;
```
+++
:::{admonition} Consigne
Quelle est la valeur attendue de `r`?
:::
```{code-cell}
---
editable: true
nbgrader:
grade: false
grade_id: init
locked: false
schema_version: 3
solution: true
---
int result = INPUT(
/// BEGIN SOLUTION
(I2 PLUSOUMOINS I1) * I3
/// END SOLUTION
);
```
+++
```{code-cell}
---
editable: false
nbgrader:
grade: true
grade_id: check
locked: true
points: 1
schema_version: 3
solution: false
tags: [hide-cell]
---
CHECK( result == r );
```
---
jupytext:
text_representation:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.15.2
kernelspec:
display_name: C++17
language: C++17
name: xcpp17
---
### Objectif pédagogique : alternative aux parenthèses
```{code-cell}
:editable: false
:tags: [hide-cell]
#include <iostream>
#include "jupyter_exercizer_helpers.hpp"
using namespace std;
```
+++
```{code-cell}
:tags: [hide-cell, variable]
CONST I1 = RANDOM_INT(1, 5);
CONST I2 = RANDOM_INT(1, 7);
CONST I3 = RANDOM_INT(1, 5);
```
+++
```{code-cell}
:tags: [hide-output, substitution]
int I, J, K, N;
I = I2 - I1;
J = I3 + I2;
K = I * J;
N = I2 - I1 * I3 + I2;
bool r = K == N;
```
+++
:::{admonition} Consigne
Quelle est la valeur attendue de `r`?
:::
```{code-cell}
---
editable: true
nbgrader:
grade: false
grade_id: init
locked: false
schema_version: 3
solution: true
---
bool result = INPUT(
/// BEGIN SOLUTION
r
/// END SOLUTION
);
```
+++
```{code-cell}
---
editable: false
nbgrader:
grade: true
grade_id: check
locked: true
points: 1
schema_version: 3
solution: false
tags: [hide-cell]
---
CHECK( result == r );
```
#ifndef RANDOMIZATION_H
#define RANDOMIZATION_H
#include <iostream>
#include <cstdlib>
#include <vector>
#include <functional>
/** Infrastructure minimale de test **/
#ifndef ASSERT
#define ASSERT(test) if (!(test)) { throw std::runtime_error("\\x1b[48;5;224mTest failed: "#test); }
#endif
#ifndef CHECK
#define CHECK(test) if ( !(test) ) { throw std::runtime_error("\\x1b[48;5;224mTest failed: "#test); }
#endif
// TODO: how to initialize the seed?
// TODO: randomize ???
#define PLUSOUMOINS +
#define CONST const auto
// TODO: randomize ???
#define X x
#define Y y
#define Z z
int RANDOM_INT(int min, int max) {
return min + (rand() % (max - min + 1));
}
template<typename T, typename ... Args>
T RANDOM_CHOICE(const T arg0, const Args... args) {
const std::vector<T> v({arg0, args...});
return v[rand() % v.size()];
}
template<typename ... Args>
auto RANDOM_CHOICE(const char * arg0, const Args... args) {
const std::vector<std::string> v({arg0, args...});
return v[rand() % v.size()];
}
class RANDOM_VECTOR_CLASS {
public:
template <typename F, typename ... Args>
auto operator ()(int N, F f, Args ... args) {
using invoke_result_t = typename std::invoke_result<F, Args ...>::type;
std::vector<invoke_result_t> v(N);
for (auto &value: v)
value = f(args...);
return v;
}
/*template<typename ... Args>
auto operator ()(int N, RANDOM_VECTOR_CLASS f, Args... args) {
std::vector<std::vector<int>> v(N);
for (auto &value: v)
value = f(args...);
return v;
}*/
};
RANDOM_VECTOR_CLASS RANDOM_VECTOR;
template<typename T>
std::ostream & operator << (std::ostream& o, const std::vector<T> &v) {
o << "{";
if ( v.size() >= 0 ) {
o << v[0];
for ( unsigned int i=1; i<v.size(); i++ )
o << ", " << v[i];
}
o << "}";
return o;
}
template<class T>
T INPUT(T t) {
return t;
}
#endif
from typing import Any
from random import randint, choice
CONST = Any
def INPUT(default: Any) -> Any:
return default
def RANDOM_INT(min: int, max: int):
return randint(min, max+1)
def RANDOM_CHOICE(*args):
r"""
Return a random element of `args`
>>> RANDOM_CHOICE("alice", "bob", "charlie") # doctest: +SKIP
'charlie'
>>> RANDOM_CHOICE("alice")
'alice'
"""
return choice(args)
---
jupyter:
jupytext:
text_representation:
extension: .md
format_name: myst
kernelspec:
display_name: C++17
language: C++17
name: xcpp17
---
### Objectif pédagogique : opération "and"
```{code-cell} c++
---
editable: false
tags: [hide-cell]
---
#include <iostream>
#include "jupyter_exercizer_helpers.hpp"
using namespace std;
```
+++
```{code-cell} c++
---
tags: [hide-cell, variable]
---
CONST I1 = RANDOM_INT(3, 9);
I1
```
+++
```{code-cell} c++
---
tags: [hide-output, substitution]
---
int x = I1;
bool r = x >= 0 and x <= 2;
```
+++
:::{admonition} Consigne
Quelle est la valeur attendue de `r`?
:::
```{code-cell}
---
editable: true
nbgrader:
grade: false
grade_id: init
locked: false
schema_version: 3
solution: true
---
bool result = INPUT(
/// BEGIN SOLUTION
r
/// END SOLUTION
);
```
+++
```{code-cell}
---
editable: false
nbgrader:
grade: true
grade_id: check
locked: true
points: 1
schema_version: 3
solution: false
tags: [hide-cell]
---
CHECK( result == r );
```
---
jupyter:
jupytext:
text_representation:
extension: .md
format_name: myst
kernelspec:
display_name: C++17
language: C++17
name: xcpp17
---
### Objectif pédagogique : opération "or"
```{code-cell} c++
---
editable: false
tags: [hide-cell]
---
#include <iostream>
#include "jupyter_exercizer_helpers.hpp"
using namespace std;
```
+++
```{code-cell} c++
---
tags: [hide-cell, variable]
---
CONST I1 = RANDOM_INT(-1, 4);
I1
```
+++
```{code-cell} c++
---
tags: [hide-output, substitution]
---
int x = I1;
bool r = x < 0 or x > 2;
```
+++
:::{admonition} Consigne
Quelle est la valeur attendue de `r`?
:::
```{code-cell}
---
editable: true
nbgrader:
grade: false
grade_id: init
locked: false
schema_version: 3
solution: true
---
bool result = INPUT(
/// BEGIN SOLUTION
r
/// END SOLUTION
);
```
+++
```{code-cell}
---
editable: false
nbgrader:
grade: true
grade_id: check
locked: true
points: 1
schema_version: 3
solution: false
tags: [hide-cell]
---
CHECK( result == r );
```
#ifndef RANDOMIZATION_H
#define RANDOMIZATION_H
#include <iostream>
#include <cstdlib>
#include <vector>
#include <functional>
/** Infrastructure minimale de test **/
#ifndef ASSERT
#define ASSERT(test) if (!(test)) { throw std::runtime_error("\\x1b[48;5;224mTest failed: "#test); }
#endif
#ifndef CHECK
#define CHECK(test) if ( !(test) ) { throw std::runtime_error("\\x1b[48;5;224mTest failed: "#test); }
#endif
// TODO: how to initialize the seed?
// TODO: randomize ???
#define PLUSOUMOINS +
#define CONST const auto
// TODO: randomize ???
#define X x
#define Y y
#define Z z
int RANDOM_INT(int min, int max) {
return min + (rand() % (max - min + 1));
}
template<typename T, typename ... Args>
T RANDOM_CHOICE(const T arg0, const Args... args) {
const std::vector<T> v({arg0, args...});
return v[rand() % v.size()];
}
template<typename ... Args>
auto RANDOM_CHOICE(const char * arg0, const Args... args) {
const std::vector<std::string> v({arg0, args...});
return v[rand() % v.size()];
}
class RANDOM_VECTOR_CLASS {
public:
template <typename F, typename ... Args>
auto operator ()(int N, F f, Args ... args) {
using invoke_result_t = typename std::invoke_result<F, Args ...>::type;
std::vector<invoke_result_t> v(N);
for (auto &value: v)
value = f(args...);
return v;
}
/*template<typename ... Args>
auto operator ()(int N, RANDOM_VECTOR_CLASS f, Args... args) {
std::vector<std::vector<int>> v(N);
for (auto &value: v)
value = f(args...);
return v;
}*/
};
RANDOM_VECTOR_CLASS RANDOM_VECTOR;
template<typename T>
std::ostream & operator << (std::ostream& o, const std::vector<T> &v) {
o << "{";
if ( v.size() >= 0 ) {
o << v[0];
for ( unsigned int i=1; i<v.size(); i++ )
o << ", " << v[i];
}
o << "}";
return o;
}
template<class T>
T INPUT(T t) {
return t;
}
#endif
from typing import Any
from random import randint, choice
CONST = Any
def INPUT(default: Any) -> Any:
return default
def RANDOM_INT(min: int, max: int):
return randint(min, max+1)
def RANDOM_CHOICE(*args):
r"""
Return a random element of `args`
>>> RANDOM_CHOICE("alice", "bob", "charlie") # doctest: +SKIP
'charlie'
>>> RANDOM_CHOICE("alice")
'alice'
"""
return choice(args)
import random
import re
from typing import Dict, Tuple
from jupyter_exercizer_helpers import RANDOM_INT, RANDOM_CHOICE
STRING_QUOTE = '"'
VECTOR_OPEN = "{"
VECTOR_CLOSE = "}"
def_regexp = {
"C++": r"CONST\s+(\w+)\s+=\s+(.*?);?\s*$",
"python": r"(\w+):\s+CONST\s+=\s+(.*?);?\s*$"
}
for language in ['C++11', 'C++14', 'C++17']:
def_regexp[language] = def_regexp['C++']
def to_language(value):
"""
Return `value` as a string representing a C++ constant
.. TODO:: make the output language configurable
>>> to_language(3)
'3'
>>> to_language("alice")
'"alice"'
>>> to_language([1,2,3])
'{1, 2, 3}'
>>> to_language([[1,2],["alice", "bob"]])
'{{1, 2}, {"alice", "bob"}}'
"""
if isinstance(value, str):
if value == "REF":
return "&"
if value == "VAL":
return ""
return STRING_QUOTE + value + STRING_QUOTE
elif isinstance(value, list):
return VECTOR_OPEN + ", ".join(to_language(v) for v in value) + VECTOR_CLOSE
else:
return str(value)
def RANDOM_VECTOR(n, generator, *args):
r"""
Return a random vector of length `n` and whose elements are
generated by calling `generator(*args)`
This return a random vector of integers of length 5, with
elements between 1 and 3:
>>> RANDOM_VECTOR(5, RANDOM_INT, 1, 3) # doctest: +SKIP
[3, 1, 2, 1, 3]
>>> RANDOM_VECTOR(5, RANDOM_INT, 1, 1)
[1, 1, 1, 1, 1]
"""
return [generator(*args) for i in range(n)]
def RANDOM_VALOUREF():
r"""
pas sur que ce soit la meilleur des methodes....
"""
return str(random.choice(["REF", "VAL"]))
locals = {
"RANDOM_INT": RANDOM_INT,
"RANDOM_CHOICE": RANDOM_CHOICE,
"RANDOM_VECTOR": RANDOM_VECTOR,
"RANDOM_VALOUREF": RANDOM_VALOUREF,
}
test_code = """CONST N = RANDOM_INT(3,3);
CONST M = RANDOM_INT(4,4);
CONST V = RANDOM_VECTOR(N, RANDOM_INT, 5, 5);
CONST VV = RANDOM_VECTOR(N, RANDOM_VECTOR, M, RANDOM_INT, 1, 1);
int main () {
int a = N + M;
vector<int> v = V;
vector<vector<int>> vv = VV;
}"""
class Randomizer:
def __init__(self, language='C++'):
consts = {}
consts["R"], consts["S"], consts["T"] = random.sample("rst", 3)
consts["X"], consts["Y"], consts["Z"] = random.sample("xyz", 3)
consts["I"], consts["J"], consts["K"], consts["N"] = random.sample("ijkn", 4)
consts["PLUSOUMOINS"] = str(random.choice(["+", "-"]))
consts["NAME"] = str(
random.choice(
["Alexandre", "Yasmine", "Albert", "Alice", "Antoine", "Anna"]
)
)
self.consts = consts
self.def_regexp = re.compile(def_regexp[language])
def randomize(self, text: str, is_code: bool = True) -> str:
result = []
for line in text.splitlines():
pattern = re.compile(r"\b(" + "|".join(self.consts.keys()) + r")\b")
if is_code:
match = re.match(self.def_regexp, line)
else:
match = None
if match:
# Define new constant
variable, value = match.groups()
# Substitutes all constants in the value
value = pattern.sub(lambda i: self.consts[i.group()], value)
# Evaluates the value in a context containing all the RANDOM_*
# functions
self.consts[variable] = to_language(eval(value, {}, locals))
else:
# Substitutes all constants
line = pattern.sub(lambda i: self.consts[i.group()], line)
result.append(line)
return "\n".join(result)
def randomize_code(code: str) -> Tuple[str, Dict]:
r"""
Randomize the given code
Examples:
>>> import random
>>> random.seed(0)
>>> randomize_code("int XX=3;")[0]
'int XX=3;'
>>> randomize_code("int X=3; int Y=4; int Z=5;")[0]
'int z=3; int x=4; int y=5;'
>>> randomize_code("I, J, K, N")[0]
'n, k, j, i'
>>> randomize_code("int X=1;\nint Y=2;")[0]
'int z=1;\nint y=2;'
>>> print(test_code)
CONST N = RANDOM_INT(3,3);
CONST M = RANDOM_INT(4,4);
CONST V = RANDOM_VECTOR(N, RANDOM_INT, 5, 5);
CONST VV = RANDOM_VECTOR(N, RANDOM_VECTOR, M, RANDOM_INT, 1, 1);
int main () {
int a = N + M;
vector<int> v = V;
vector<vector<int>> vv = VV;
}
>>> print(randomize_code(test_code)[0])
int main () {
int a = 3 + 4;
vector<int> v = {5, 5, 5};
vector<vector<int>> vv = {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};
}
"""
randomizer = Randomizer()
code = randomizer.randomize(code)
return code, randomizer.consts
---
jupytext:
text_representation:
extension: .md
format_name: myst
format_version: 0.13
kernelspec:
display_name: Python 3 (ipykernel)
language: python
name: python3
---
# Exercices d'entraînement
Exécutez la cellule suivante, puis choisissez le thème sur lequel
vous souhaitez vous entraîner.
```{code-cell} ipython3
---
editable: true
slideshow:
slide_type: ''
---
from entraîneur import entraîneur
entraîneur
```
```{code-cell} ipython3
```