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 (1)
......@@ -6,6 +6,8 @@ attic
.ipynb_checkpoints
*.pyc
__pycache__
_build
myst
*~
core*
*.avi
......
No preview for this file type
......@@ -4,7 +4,6 @@ jupytext:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.15.1
kernelspec:
display_name: Python 3 (ipykernel)
language: python
......
......@@ -7,12 +7,10 @@ exports:
output: TDmd.tex
template: ../../template/TD
jupytext:
notebook_metadata_filter: exports, myst
text_representation:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.15.2
kernelspec:
display_name: C++17
language: C++17
......
---
jupytext:
notebook_metadata_filter: rise
text_representation:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.15.1
kernelspec:
display_name: C++17
language: C++17
......@@ -31,23 +29,32 @@ rise:
# Collections et boucle «pour tout ... dans ...»
+++ {"slideshow": {"slide_type": "subslide"}}
+++ {"slideshow": {"slide_type": "slide"}}
## Collections : définition et exemples
+++ {"slideshow": {"slide_type": "fragment"}}
## Quelques exemples de collections
:::{prf:definition} Collection
Une ***collection*** est une **valeur composite homogène**
(elle regroupe plusieurs valeurs du même type).
:::
+++ {"slideshow": {"slide_type": "fragment"}}
### Rappel : tableaux (`vector`)
:::{prf:example}
Un tableau (`vector`) est une collection
:::
+++ {"slideshow": {"slide_type": "fragment"}}
Nous avons vu qu'un tableau (`vector` en C++) regroupe plusieurs
valeurs dans un ordre donné, en tenant compte des répétitions :
Dans un tableau, les valeurs sont **dans un ordre donné**, **en tenant compte des répétitions** :
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
#include<vector>
using namespace std;
......@@ -56,7 +63,8 @@ using namespace std;
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
vector<int> v = { 3, 2, 5, 2 };
```
......@@ -64,7 +72,8 @@ vector<int> v = { 3, 2, 5, 2 };
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
v
```
......@@ -76,20 +85,19 @@ Cela donne un sens au i-ième élément d'un tableau :
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
v[3]
```
+++ {"slideshow": {"slide_type": "fragment"}}
Un tableau est un exemple de **valeur composite homogène**,
ou **collection** qui regroupe plusieurs valeurs
d'un même type.
:::{note}
Il existe d'autres types de collections. Voyons quelques exemples.
:::
+++ {"slideshow": {"slide_type": "subslide"}}
+++ {"slideshow": {"slide_type": "slide"}}
### Ensembles (`set`)
......@@ -102,7 +110,8 @@ utiliser un `set` :
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
#include <set>
using namespace std;
......@@ -111,7 +120,8 @@ using namespace std;
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
set<int> s = { 3, 2, 5, 2};
```
......@@ -119,7 +129,8 @@ set<int> s = { 3, 2, 5, 2};
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
s
```
......@@ -131,12 +142,13 @@ Du coup, accéder au i-ième élément n'a pas de sens :
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
s[1]
s[0]
```
+++ {"slideshow": {"slide_type": "subslide"}}
+++ {"slideshow": {"slide_type": "slide"}}
### Multi-ensembles (`multiset`)
......@@ -148,7 +160,8 @@ des répétitions, on peut utiliser un multi-ensemble (`multiset`) :
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
multiset<int> m = { 3, 2, 5, 2 };
```
......@@ -156,12 +169,19 @@ multiset<int> m = { 3, 2, 5, 2 };
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
m
```
+++ {"slideshow": {"slide_type": "subslide"}}
```{code-cell}
:tags: []
m[0]
```
+++ {"slideshow": {"slide_type": "slide"}, "tags": []}
## Boucle `for each`
......@@ -186,10 +206,12 @@ vector<int> v = { 3, 2, 5, 2 };
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
for ( int i=0; i < v.size(); i++ )
for ( int i=0; i < v.size(); i++ ) {
cout << v[i] << endl;
}
```
+++ {"slideshow": {"slide_type": "fragment"}}
......@@ -207,8 +229,9 @@ généralisera pas aux ensembles! (pourquoi?).
slideshow:
slide_type: fragment
---
for ( auto valeur: v )
for ( auto valeur: v ) {
cout << valeur << endl;
}
```
+++ {"slideshow": {"slide_type": "fragment"}}
......@@ -224,26 +247,74 @@ set<int> s = { 3, 2, 5, 2 };
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
for ( auto valeur: s )
for ( auto valeur: s ) {
cout << valeur << endl;
}
```
```{code-cell}
---
slideshow:
slide_type: fragment
tags: []
---
multiset<int> m = { 3, 2, 5, 2 };
```
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
for ( auto valeur: m )
for ( auto valeur: m ) {
cout << valeur << endl;
}
```
+++ {"slideshow": {"slide_type": "subslide"}}
+++ {"slideshow": {"slide_type": "slide"}, "tags": []}
:::{prf:example}
Quelle est la valeur de `m` après l'instruction suivante?
:::
```{code-cell}
:tags: []
#include<vector>
using namespace std;
vector<int> m = { 3, 2, 5, 2 };
```
```{code-cell}
:tags: []
for ( auto valeur: m ) {
valeur = 1;
}
```
```{code-cell}
:tags: []
m
```
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
:::{attention}
Pour être complètement précis, `valeur` ne parcourt pas les valeurs de la collection,
mais des copies de celles-ci. Aussi, une affectation `valeur=...` ne change
pas le tableau d'origine.
Vous verrez au second semestre comment changer cela lorsque souhaitable,
en utilisant une **référence**.
:::
+++ {"slideshow": {"slide_type": "slide"}}
### Digression : à propos de `auto` ♣
......@@ -252,7 +323,7 @@ signification de `auto`?
On est en train de déclarer une nouvelle variable.
Il faut donc préciser son type. On pourrait très
bien mettre `int` ci-dessus puisque l'on manipule
bien mettre `int` comme type puisque l'on manipule
des collections d'entiers :
```{code-cell}
......@@ -260,15 +331,23 @@ des collections d'entiers :
slideshow:
slide_type: fragment
---
for ( int valeur: v )
for ( int valeur: v ) {
cout << valeur << endl;
}
```
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
Mais c'est redondant.
+++ {"slideshow": {"slide_type": "fragment"}}
`auto` est un type spécial qui indique à C++ de
:::{prf:definition} `auto`
***auto*** est un type spécial qui indique à C++ de
sélectionner automatiquement le type adéquat en
fonction du contexte, ce qui est facile ici.
fonction du contexte. On appelle cela de
l'[inférence de type](https://fr.wikipedia.org/wiki/Inf%C3%A9rence_de_types).
:::
```{code-cell}
---
......
......@@ -4,7 +4,6 @@ jupytext:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.15.1
kernelspec:
display_name: C++17
language: C++17
......@@ -30,9 +29,10 @@ vous pouvez ignorer la distinction pour le moment.
**Instructions:**
1. Essayez le programme suivant en saisissant successivement
les mots de passe «`coucou`» et «`s3*iA3`».
les mots de passe «`coucou`» et «`s3*iA3`». Que constatez vous?
2. Essayez le programme suivant en saisissant successivement
les mots de passe «`ouvre!`», «`Sesame,ouvre!`», et «`ouvre!`».
Que constatez vous?
```{code-cell}
---
......@@ -46,16 +46,18 @@ using namespace std;
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
char motDePasse [] = "XXXXXX";
char motDePasse[] = "XXXXXX";
char motDePasseSecret[] = "s3*iA3";
```
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
do {
cout << "Entrez le mot de passe: " << endl;
......@@ -65,20 +67,22 @@ do {
cout << "Connexion réussie. Bienvenue chef!" << endl;
```
+++ {"slideshow": {"slide_type": "slide"}}
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
## Explications
<div class="alert alert-primary">
+++ {"slideshow": {"slide_type": "notes"}, "tags": []}
:::{hint} Un tour de magie?
Bien sûr, «Sésame» n'est pas une incantation magique. Il y a une
explication derrière ce piratage réussi. Pour la comprendre, il vous
faudra d'abord avoir lu le début du cours
[Modèle de mémoire et tableaux](cours-memoire-tableaux.md).
</div>
:::
+++ {"slideshow": {"slide_type": "fragment"}}
+++ {"slideshow": {"slide_type": "notes"}, "tags": []}
Les deux tableaux sont de longueurs fixes, et le début du tableau
`motDePasseSecret` se trouve être 7 cases après le début du tableau
......@@ -94,7 +98,7 @@ slideshow:
motDePasseSecret - motDePasse
```
+++ {"slideshow": {"slide_type": "fragment"}}
+++ {"slideshow": {"slide_type": "notes"}, "tags": []}
De ce fait, lorsque l'attaquant saisit «Sesame,ouvre!», cela déborde de
`motDePasse`: le caractère «,» est écrit juste après `motDePasse`, et
......@@ -110,7 +114,7 @@ slideshow:
motDePasseSecret
```
+++ {"slideshow": {"slide_type": "fragment"}}
+++ {"slideshow": {"slide_type": "notes"}, "tags": []}
Du coup, à la tentative de connexion suivante, le mot de passe
«ouvre!» est accepté.
......
---
jupytext:
notebook_metadata_filter: rise
text_representation:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.15.2
kernelspec:
display_name: C++17
language: C++17
......@@ -31,10 +29,12 @@ rise:
# Modèle de mémoire et tableaux
:::{prf:definition} Pile et tas
L'espace mémoire d'un programme est partagé en deux zones :
- La *pile* : variables locales des fonctions
- Le *tas* : le reste
- La ***pile*** : variables locales des fonctions
- Le ***tas*** : le reste
:::
+++ {"slideshow": {"slide_type": "fragment"}}
......@@ -65,7 +65,9 @@ t[4] = 9;
0. État initial
<img src="media/pile-tas-etat-initial.png" style="margin: auto" height="25ex" />
%<img src="media/pile-tas-etat-initial.png" style="margin: auto" height="25ex" />
:::{image} media/pile-tas-etat-initial.png
:::
+++ {"slideshow": {"slide_type": "fragment"}}
......@@ -75,7 +77,9 @@ t[4] = 9;
vector<int> t;
```
<img src="media/pile-tas-declaration.png" style="margin: auto" height="25ex" />
%<img src="media/pile-tas-declaration.png" style="margin: auto" height="25ex" />
:::{image} media/pile-tas-declaration.png
:::
+++ {"slideshow": {"slide_type": "fragment"}}
......@@ -85,7 +89,9 @@ t[4] = 9;
t = vector<int>(6);
```
<img src="media/pile-tas-allocation.png" style="margin: auto" height="25ex" />
%<img src="media/pile-tas-allocation.png" style="margin: auto" height="25ex" />
:::{image} media/pile-tas-allocation.png
:::
+++ {"slideshow": {"slide_type": "fragment"}}
......@@ -96,11 +102,13 @@ t[4] = 9;
...
```
<img src="media/pile-tas-initialisation-1.png" style="margin: auto;" height="25ex" />
%<img src="media/pile-tas-initialisation-1.png" style="margin: auto;" height="25ex" />
:::{image} media/pile-tas-initialisation-1.png
:::
+++ {"slideshow": {"slide_type": "slide"}}
## Sémantique : allocation d'un tableau
:::{admonition} Sémantique : allocation d'un tableau
``` c++
t = vector<int>(6);
......@@ -109,18 +117,20 @@ t = vector<int>(6);
1. Une suite contiguë de cases est allouée sur le tas
2. La taille et une référence vers la première des cases est stockée
dans `t`
:::
+++ {"slideshow": {"slide_type": "fragment"}}
## Sémantique : lecture et écriture dans un tableau
:::{admonition} Sémantique : lecture et écriture dans un tableau
``` c++
t[i]
```
- Donne la `i`-ème case du tableau
- La `i`-ème case du tableau
- Obtenue en suivant la référence et se décalant de $i$ cases
- Rappel : *pas de vérifications!!!*
:::
+++ {"slideshow": {"slide_type": "slide"}}
......@@ -130,49 +140,69 @@ t[i]
### Heartblead expliqué (<http://xkcd.com/1354/>)
<img src="media/xkcd_heartbleed_explanation_1.jpg" style="margin: auto" height="40ex" /><img src="media/xkcd_heartbleed_explanation_2.jpg" style="margin: auto" height="40ex" />
:::::{grid}
::::{grid-item-card}
:::{image} media/xkcd_heartbleed_explanation_1.jpg
:::
::::
::::{grid-item-card}
:::{image} media/xkcd_heartbleed_explanation_1.jpg
:::
::::
:::::
%<img src="media/xkcd_heartbleed_explanation_1.jpg" style="margin: auto" height="40ex" /><img src="media/xkcd_heartbleed_explanation_2.jpg" style="margin: auto" height="40ex" />
+++ {"slideshow": {"slide_type": "slide"}}
## Tableaux et allocation mémoire
**À retenir :**
:::{hint} À retenir
- Une valeur de type tableau ne contient pas directement les cases du
tableau, mais l'adresse en mémoire de celles-ci (référence) et la
taille du tableau.
:::
+++ {"slideshow": {"slide_type": "fragment"}}
:::{hint} À retenir
- Une variable de type tableau se construit en trois étapes :
1. Déclaration
2. Allocation
2. Allocation
Sans cela : *faute de segmentation* (au mieux!)
3. Initialisation
3. Initialisation
Sans cela : même problème qu'avec les variables usuelles
:::
+++ {"slideshow": {"slide_type": "fragment"}}
:::{hint} À retenir
- Lors de l'accès à une case `i` d'un tableau `t`, il faut toujours
vérifier les bornes : `0 <= i` et `i < t.size()`
Sans cela : *faute de segmentation* (au mieux!)
:::
+++ {"slideshow": {"slide_type": "slide"}}
## Sémantique : affectation de tableaux
**Exemple :**
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
:::{prf:example}
Quelles sont les valeurs de `t[0]` et `t2[0]` après l'exécution du
programme suivant?
:::
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
vector<int> t = { 1, 4, 1, 5, 9, 2 };
vector<int> t2;
......@@ -180,50 +210,127 @@ t2 = t; // Affectation
t2[0] = 0;
```
```{code-cell}
:tags: []
t[0]
```
```{code-cell}
:tags: []
t2[0]
```
+++ {"slideshow": {"slide_type": "fragment"}}
**À retenir :**
:::{hint} À retenir
- En C++, lors d'une affectation, un `vector` est *copié*!
- On dit que `vector` a une **sémantique de copie**.
- Différent de Java, Python ou des tableaux en C!
- Différent de Java, Python ou des tableaux C!
:::
+++ {"slideshow": {"slide_type": "slide"}}
## Sémantique : tableaux et fonctions ♣
**Exemple :**
+++ {"slideshow": {"slide_type": "fragment"}, "tags": []}
:::{prf:example}
Quelle est la valeur de `tableau[0]` après l'exécution du programme
suivant?
:::
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
void modifie(vector<int> tableau) {
tableau[0] = 42;
}
#include <vector>
using namespace std;
using tableau = vector<int>;
```
```{code-cell}
---
slideshow:
slide_type: fragment
slide_type: null
tags: []
---
void modifie(vector<int> t) {
t[0] = 42;
}
```
```{code-cell}
:tags: []
vector<int> tableau = { 1, 2, 3, 4 };
modifie(tableau);
modifie(tableau)
```
+++ {"slideshow": {"slide_type": "fragment"}}
```{code-cell}
:tags: []
**Fonctions et tableaux :**
tableau[0]
```
+++ {"slideshow": {"slide_type": "fragment"}}
- Affectation des paramètres $\Longrightarrow$ copie
:::{hint} Fonctions et tableaux
En combinant la sémantique de l'appel de fonction et celle d'affectation de tableaux, on déduit que :
% TODO: liens croisés
- Appel de fonction $\Longrightarrow$ Affectation des paramètres $\Longrightarrow$ copie
- Donc, les `vector` de C++ sont passés **par valeur** aux fonctions
:::
+++ {"slideshow": {"slide_type": "fragment"}}
- Mais la fonction peut renvoyer le tableau modifié!
:::{tip} Astuce
La fonction peut **renvoyer** le tableau modifié!
:::
```{code-cell}
---
slideshow:
slide_type: null
tags: []
---
#include <vector>
using namespace std;
using tableau = vector<int>;
```
```{code-cell}
---
slideshow:
slide_type: null
tags: []
---
tableau modifie(vector<int> t) {
t[0] = 42;
return t;
}
```
```{code-cell}
:tags: []
vector<int> tableau = { 1, 2, 3, 4 };
tableau = modifie(tableau)
```
```{code-cell}
:tags: []
tableau[0]
```
+++ {"slideshow": {"slide_type": "notes"}, "tags": []}
:::{note}
Vous verrez au second semestre comment passer les tableaux par référence aux fonctions, notamment pour des questions de performances.
:::
---
jupytext:
notebook_metadata_filter: rise
text_representation:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.15.1
kernelspec:
display_name: C++17
language: C++17
......@@ -35,7 +33,7 @@ rise:
## Prélude
+++ {"slideshow": {"slide_type": "subslide"}}
+++ {"slideshow": {"slide_type": "slide"}}
### Résumé de l'épisode précédent
......@@ -49,8 +47,8 @@ rise:
#### Tableaux
- Un **tableau** est une valeur **composite** formée de plusieurs
valeurs du même type
- Un **tableau** est une valeur **composite** **homogène**
c'est à dire formée de plusieurs valeurs du même type
- Construction :
1. Déclaration
2. Allocation
......@@ -64,7 +62,7 @@ rise:
**<div style="color: red; text-align: center; font-weight:bold;">Généralisations?</div>**
+++ {"slideshow": {"slide_type": "subslide"}}
+++ {"slideshow": {"slide_type": "slide"}}
### Au programme
......@@ -79,7 +77,10 @@ rise:
+++ {"slideshow": {"slide_type": "fragment"}}
- Motivation: un exemple de piratage par débordement
- Un modèle de mémoire raffiné avec pile et tas
+++ {"slideshow": {"slide_type": "fragment"}}
- Un modèle de mémoire raffiné avec **pile** et **tas**
- Sémantique:
- Allocation des tableaux sur le tas
- Accès à `t[i]`
......@@ -88,8 +89,11 @@ rise:
+++ {"slideshow": {"slide_type": "fragment"}}
- Notion de collection
- Autres collections
- Notion de **collection**
- Autres exemples de collections: `set`, `multiset`, ...
+++ {"slideshow": {"slide_type": "fragment"}}
- Boucle `for each`
- `auto`
......@@ -4,7 +4,6 @@ jupytext:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.15.2
kernelspec:
display_name: C++17
language: C++17
......
notebook_metadata_filter="kernelspec,jupytext,exports,math,rise,semantic,-jupytext.text_representation.jupytext_version"
cell_metadata_filter="all,-autoscroll,-collapsed,-scrolled,-trusted,-ExecuteTime,-jp-MarkdownHeadingCollapsed"
\ No newline at end of file
......@@ -4,7 +4,6 @@ jupytext:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.15.1
kernelspec:
display_name: C++17
language: C++17
......
......@@ -4,7 +4,6 @@ jupytext:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.15.2
kernelspec:
display_name: C++17
language: C++17
......