diff --git a/Cours/01-bases.pdf b/Algorithmique/Cours/01-bases.pdf similarity index 100% rename from Cours/01-bases.pdf rename to Algorithmique/Cours/01-bases.pdf diff --git a/Algorithmique/Cours/02-intro-c.md b/Algorithmique/Cours/02-intro-c.md new file mode 100644 index 0000000000000000000000000000000000000000..116489ce45e5c5b00b8cc6728148ba74cf97d44b --- /dev/null +++ b/Algorithmique/Cours/02-intro-c.md @@ -0,0 +1,683 @@ +--- +title: "Module Algorithmie et programmation" +patat: + eval: + tai: + command: fish + fragment: false + replace: true + ccc: + command: fish + fragment: false + replace: true + images: + backend: auto +subtitle: "Introduction au langage C" +author: "Pierre Künzli" +institute: "Inspiré des cours de Paul Albuquerque, Guido Bologna et Orestis Malaspinas" +lang: fr-CH +revealjs-url: /reveal.js +mathjaxurl: "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_HTML" +--- + +## Le langage C, historique + +- Conçu initialement pour la programmation des systèmes d’exploitation (UNIX). +- Créé par Dennis Ritchie à Bell Labs en 1972 dans la continuation de CPL, BCPL et B. +- Standardisé entre 1983 et 1988 (ANSI C). +- La syntaxe de C est devenue la base d’autres langages comme C++, Objective-C, Java, Go, C#, Rust, etc. +- Révisions plus récentes, notamment C99, C11, puis C18. + +## Le langage C, historique + +- Développement de C lié au développement d’UNIX. +- UNIX a été initialement développé en assembleur: + - instructions de très bas niveau, + - instructions spécifiques à l’architecture du processeur. +- Pour rendre UNIX portable, un langage de *haut niveau* (en 1972) était nécessaire. +- Comparé à l’assembleur, le C est : + - Un langage de "haut niveau": C offre des fonctions, des structures de données, des constructions de contrôle de flots (`while`{.C}, `for`{.C}, etc). + - Portable: un programme C peut être exécuté sur un *très grand nombre* de plateformes (il suffit de recompiler le *même code* pour l’architecture voulue). + +## Qu'est-ce que le C? + +- "Petit langage simple" (en 2022). +- Langage compilé, statiquement (et faiblement) typé, procédural, portable, très efficace. +- Langage "bas niveau" (en 2022): gestion explicite et manuelle de la mémoire (allocation/désallocation), grande liberté pour sa manipulation. +- Pas de structures de haut niveau: chaînes de caractères, vecteurs dynamiques, listes, ... +- Aucune validation ou presque sur la mémoire (pointeurs, overflows, ...). + + +# La simplicité de C? + +## 32 mots-clé et c'est tout + +---------------- -------------- ---------------- --------------- +`auto`{.C} `double`{.C} `int`{.C} `struct`{.C} +`break`{.C} `else`{.C} `long`{.C} `switch`{.C} +`case`{.C} `enum`{.C} `register`{.C} `typedef`{.C} +`char`{.C} `extern`{.C} `return`{.C} `union`{.C} +`const`{.C} `float`{.C} `short`{.C} `unsigned`{.C} +`continue`{.C} `for`{.C} `signed`{.C} `void`{.C} +`default`{.C} `goto`{.C} `sizeof`{.C} `volatile`{.C} +`do`{.C} `if`{.C} `static`{.C} `while`{.C} +---------------- -------------- ---------------- --------------- + +# Déclaration et typage + +En C lorsqu'on veut utiliser une variable (ou une constante), on doit déclarer son type + +```C +const double two = 2.0; // déclaration et init. +int x; // déclaration (instruction) +char c; // déclaration (instruction) +x = 1; // affectation (expression) +c = 'a'; // affectation (expression) +int y = x; // déclaration et initialisation en même temps +int a, b, c; // déclarations multiples +a = b = c = 1; // init. multiples +``` + +# Les variables + +## Variables et portée + +- Une variable est un identifiant, qui peut être liée à une valeur (une expression). +- Une variable a une **portée** qui définit où elle est *visible* (où elle peut être accédée). +- La portée est **globale** ou **locale**. +- Une variable est **globale** est accessible à tout endroit d'un programme et doit être déclarée en dehors de toute fonction. +- Une variable est **locale** lorsqu'elle est déclarée dans un **bloc**, `{...}`{.C}. +- Une variable est dans la portée **après** avoir été déclarée. + +## Exemple + +```C +float max; // variable globale accessible partout +int foo() { + // max est visible ici + float a = max; // valide + // par contre les varibles du main() ne sont pas visibles +} +int main() { + // max est visible ici + int x = 1; // x est locale à main + { + // x est visible ici, y pas encore + // on peut par exemple pas faire x = y; + int y = 2; + } // y est détruite à la sortie du bloc +} // x est dàtruite à la sortie de main + +``` + +# Représentation des variables en mémoire + +## La mémoire + +* La mémoire est: + - ... un ensemble de bits, + - ... accessible via des adresses, + + +------+----------+----------+------+----------+------+------+ + | bits | 00110101 | 10010000 | .... | 00110011 | .... | .... | + +======+==========+==========+======+==========+======+======+ + | addr | 2000 | 2001 | .... | 4000 | .... | .... | + +------+----------+----------+------+----------+------+------+ + + - ... gérée par le système d'exploitation. + - ... séparée en deux parties: **la pile** et **le tas**. + +## Une variable + +* Une variable, `type a = valeur`{.C}, possède: + - un type (`char`{.C}, `int`{.C}, ...), + - un contenu (une séquence de bits qui encode `valeur`{.C}), + - une adresse mémoire (accessible via `&a`{.C}), + - une portée. + + +## Représentation des variables en mémoire + +{width=100%} + +# Types de base + +## Numériques + +Type Signification (**gcc pour x86-64**) +---------------------------------- --------------------------------------------- +`char`{.C}, `unsigned char`{.C} Entier signé/non-signé 8-bit +`short`{.C}, `unsigned short`{.C} Entier signé/non-signé 16-bit +`int`{.C}, `unsigned int`{.C} Entier signé/non-signé 32-bit +`long`{.C}, `unsigned long`{.C} Entier signé/non-signé 64-bit +`float`{.C} Nombre à virgule flottante, simple précision +`double`{.C} Nombre à virgule flottante, double précision +---------------------------------- --------------------------------------------- + +**La signification de `short`{.C}, `int`{.C}, ... dépend du compilateur et de l'architecture.** + +## Numériques + +Voir `<stdint.h>` pour des représentations **portables** + +Type Signification +---------------------------------- --------------------------------------------- +`int8_t`{.C}, `uint8_t`{.C} Entier signé/non-signé 8-bit +`int16_t`{.C}, `uint16_t`{.C} Entier signé/non-signé 16-bit +`int32_t`{.C}, `uint32_t`{.C} Entier signé/non-signé 32-bit +`int64_t`{.C}, `uint64_t`{.C} Entier signé/non-signé 64-bit +---------------------------------- --------------------------------------------- + + + +## Booléens + +- Le ANSI C n'offre pas de booléens. +- L'entier `0`{.C} signifie *faux*, tout le reste *vrai*. +- Depuis C99, la librairie `stdbool` met à disposition un type `bool`{.C}. +- En réalité c'est un entier: + - $1 \Rightarrow$ `true`{.C} + - $0 \Rightarrow$ `false`{.C} +- On peut les manipuler comme des entier (les sommer, les multiplier, ...). + +## Void + +Le type `void` est un type particulier, qui représente l'absence de donnée, de type ou un type indéterminé. On ne peut pas déclarer une variable de type `void`. + +## Conversions + +- Les conversions se font de manière: + - Explicite: + ```C + int a = (int)2.8; + double b = (double)a; + int c = (int)(2.8+0.5); + ``` + - Implicite: + ```C + int a = 2.8; // warning, si activés, avec clang + double b = a + 0.5; + char c = b; // pas de warning... + int d = 'c'; + ``` + +# Expressions et opérateurs + +Une expression est tout bout de code qui est **évalué**. + +## Expressions simples + +- Pas d'opérateurs impliqués. +- Les littéraux, les variables, et les constantes. + +```C +const int L = -1; // 'L' est une constante, -1 un littéral +int x = 0; // '0' est un litéral +int y = x; // 'x' est une variable +int z = L; // 'L' est une constante +``` + +## Expressions complexes + +- Obtenues en combinant des *opérandes* avec des *opérateurs* + +```C +int x; // pas une expression (une instruction) +x = 4 + 5; // 4 + 5 est une expression + // dont le résultat est affecté à 'x' +``` + + +## Opérateurs relationnels + +Opérateurs testant la relation entre deux *expressions*: + + - `(a opérateur b)` retourne `1`{.C} si l'expression s'évalue à `true`{.C}, `0`{.C} si l'expression s'évalue à `false`{.C}. + +| Opérateur | Syntaxe | Résultat | +|-----------|--------------|----------------------| +| `<`{.C} | `a < b`{.C} | 1 si a < b; 0 sinon | +| `>`{.C} | `a > b`{.C} | 1 si a > b; 0 sinon | +| `<=`{.C} | `a <= b`{.C} | 1 si a <= b; 0 sinon | +| `>=`{.C} | `a >= b`{.C} | 1 si a >= b; 0 sinon | +| `==`{.C} | `a == b`{.C} | 1 si a == b; 0 sinon | +| `!=`{.C} | `a != b`{.C} | 1 si a != b; 0 sinon | + + +## Opérateurs logiques + +| Opérateur | Syntaxe | Signification | +|-----------|--------------|----------------------| +| `&&`{.C} | `a && b`{.C} | ET logique | +| `||`{.C} | `a || b`{.C} | OU logique | +| `!`{.C} | `!a`{.C} | NON logique | + + +## Opérateurs arithmétiques + +| Opérateur | Syntaxe | Signification | +|-----------|--------------|----------------------| +| `+`{.C} | `a + b`{.C} | Addition | +| `-`{.C} | `a - b`{.C} | Soustraction | +| `*`{.C} | `a * b`{.C} | Multiplication | +| `/`{.C} | `a / b`{.C} | Division | +| `%`{.C} | `a % b`{.C} | Modulo | + + +## Opérateurs d'assignation + +| Opérateur | Syntaxe | Signification | +|-----------|--------------|---------------------------------------------| +| `=`{.C} | `a = b`{.C} | Affecte la valeur `b` à la variable `a` | +| | | et retourne la valeur de `b` | +| `+=`{.C} | `a += b`{.C} | Additionne la valeur de `b` à `a` et | +| | | assigne le résultat à `a`. | +| `-=`{.C} | `a -= b`{.C} | Soustrait la valeur de `b` à `a` et | +| | | assigne le résultat à `a`. | +| `*=`{.C} | `a *= b`{.C} | Multiplie la valeur de `b` à `a` et | +| | | assigne le résultat à `a`. | +| `/=`{.C} | `a /= b`{.C} | Divise la valeur de `b` à `a` et | +| | | assigne le résultat à `a`. | +| `%=`{.C} | `a %= b`{.C} | Calcule le modulo la valeur de `b` à `a` et | +| | | assigne le résultat à `a`. | + + +## Opérateurs d'assignation (suite) + +| Opérateur | Syntaxe | Signification | +|-----------|--------------|---------------------------------------------| +| `++`{.C} | `++a`{.C} | Incrémente la valeur de `a` de 1 et | +| | | retourne le résultat (`a += 1`). | +| `--`{.C} | `--a`{.C} | Décrémente la valeur de `a` de 1 et | +| | | retourne le résultat (`a -= 1`). | +| `++`{.C} | `a++`{.C} | Retourne `a`{.C} et incrémente `a` de 1. | +| `--`{.C} | `a--`{.C} | Retourne `a`{.C} et décrémente `a` de 1. | + + +# Structures de contrôle: `if`{.C} .. `else if`{.C} .. `else`{.C} + +## Syntaxe + +```C +if (expression) { + instructions; +} else if (expression) { // optionnel + // il peut y en avoir plusieurs + instructions; +} else { // optionnel + instructions; +} +``` + +```C +if (x) { // si x s'évalue à `vrai` + printf("x s'évalue à vrai.\n"); +} else if (y == 8) { // si y vaut 8 + printf("y vaut 8.\n"); +} else { + printf("Ni l'un ni l'autre.\n"); +} +``` + + + +## Pièges + +```C +int x, y; +x = y = 3; +if (x = 2) // affectation au lieu de comparaison + printf("x = 2 est vrai.\n"); +else if (y < 8) + printf("y < 8.\n"); +else if (y == 3) // n'entrera jamais dans cette branche + printf("y vaut 3 mais cela ne sera jamais affiché.\n"); +else + printf("Ni l'un ni l'autre.\n"); + x = -1; // toujours évalué +``` + +# Structures de contrôle: `switch`{.C} .. `case`{.C} + +```C +switch (expression) { + case constant-expression: + instructions; + break; // optionnel + case constant-expression: + instructions; + break; // optionnel + // ... + default: + instructions; +} +``` + +**Que se passe-t-il si `break`{.C} est absent?** + +## Structures de contrôle: `switch`{.C} .. `case`{.C} + +```C +int x = 0; +switch (x) { + case 0: + case 1: + printf("0 ou 1\n"); + break; + case 2: + printf("2\n"); + break; + default: + printf("autre\n"); +} +``` + +**Dangereux, mais c'est un moyen d'avoir un "ou" logique dans un case.** + + +# Structures de contrôle: `while`{.C} + +## La boucle `while`{.C} + +```C +while (condition) { + instructions; +} +``` + +ou + +```C +do { + instructions; +} while (condition); +``` + +## La boucle `while`{.C}, un exemple + +```C +int sum = 0; // syntaxe C99 +while (sum < 10) { + sum += 1; +} +do { + sum += 10; +} while (sum < 100) +``` + + + +# Structures de contrôle: `for`{.C} + +## La boucle `for`{.C} + +```C +for (expression1; expression2; expression3) { + instructions; +} +``` + +## La boucle `for`{.C} + +```C +int sum = 0; // syntaxe C99 +for (int i = 0; i < 10; i++) { + sum += i; +} + +for (int i = 0; i != 1; i = rand() % 4) { // ésotérique + printf("C'est plus ésotérique.\n"); +} +``` + + + +# Structures de contrôle: `continue`{.C}, `break`{.C} + +- `continue`{.C} saute à la prochaine itération d'une boucle. + + ```C + int i = 0; + while (i < 10) { + if (i == 3) { + continue; + } + printf("%d\n", i); + i += 1; + } + ``` + +- `break`{.C} quitte le bloc itératif courant d'une boucle. + + ```C + for (int i = 0; i < 10; i++) { + if (i == 3) { + break; + } + printf("%d\n", i); + } + ``` + +# Exercice: la factorielle + +Écrire un programme qui calcule la factorielle d'un nombre +$$ +N! = 1\cdot 2\cdot ... \cdot (N-1)\cdot N. +$$ + +## Ecrire un pseudo-code + +. . . + +```C +int factorielle(int n) { + i = 1; + fact = 1; + pour i <= n { + fact *= i; + i += 1; + } +} +``` + + +## Ecrire un code en C + + +. . . + +```C +#include <stdio.h> +int main() { + int nb = 10; + int fact = 1; + int iter = 1; + while (iter <= nb) { + fact *= iter; + iter++; + } +} +``` + +. . . + +### Comment améliorer ce code ? A faire en exercice. + + +# Entrées/sorties: `printf()`{.C} + +## Généralités + +- La fonction `printf()`{.C} permet d'afficher du texte sur le terminal: + + ```C + int printf(const char *format, ...); + ``` +- Nombre d'arguments variables. +- `format`{.C} est le texte, ainsi que le format (type) des variables à afficher. +- Les arguments suivants sont les expressions à afficher. + + +## Exemple + +```C +#include <stdio.h> +#include <stdlib.h> + +int main() { + printf("Hello world.\n"); + int val = 1; + printf("Hello world %d time.\n", val); + printf("%f squared is equal to %f.\n", 2.5, 2.5*2.5); + return EXIT_SUCCESS; +} +``` + +. . . + +### Remarque : ici la fonction `main` retourne `int` au lieu de `void` pour pouvoir retourner un code d'erreur. + +# Entrées/sorties: `scanf()`{.C} + +## Généralités + +- La fonction `scanf()`{.C} permet de lire du texte formaté entré au clavier: + + ```C + int scanf(const char *format, ...); + ``` + +- `format`{.C} est le format des variables à lire (comme `printf()`{.C}). +- Les arguments suivants sont les variables où sont stockées les valeurs lues. + + +## Exemple + +```C +#include <stdio.h> +#include <stdlib.h> + +int main() { + printf("Enter 3 numbers: \n"); + int i, j, k; + scanf("%d %d %d", &i, &j, &k); + printf("You entered: %d %d %d\n", i, j, k); + + return EXIT_SUCCESS; +} +``` + + +# Les fonctions + +- Les parties indépendantes d'un programme. +- Permettent de modulariser et compartimenter le code. +- Syntaxe: + + ```C + type identificateur(paramètres) { + // variables optionnelles + instructions; + // type expression == type + return expression; + } + ``` + + +## Exemple + +```C +int max(int a, int b) { + if (a > b) { + return a; + } else { + return b; + } +} + +int main() { + int c = max(4, 5); +} +``` + +## Les fonctions + +- Il existe un type `void`{.C}, "sans type", en C. +- Il peut être utilisé pour signifier qu'une fonction ne retourne rien, ou qu'elle n'a pas d'arguments. +- `return`{.C} utilisé pour sortir de la fonction. +- Exemple: + + ```C + void show_text(void) { // second void optionnel + printf("Aucun argument et pas de retour.\n"); + return; // optionnel + } + + void show_text_again() { // c'est pareil + printf("Aucun argument et pas de retour.\n"); + } + ``` + +## Prototypes de fonctions + +- Le prototype donne la **signature** de la fonction, avant qu'on connaisse son implémentation. +- L'appel d'une fonction doit être fait **après** la déclaration du prototype. + + ```C + int max(int a, int b); // prototype + + int max(int a, int b) { // implémentation + if (a > b) { + return a; + } else { + return b; + } + } + ``` + + +## Arguments de fonctions + +- Les arguments d'une fonction sont toujours passés **par copie**. +- Les arguments d'une fonction ne peuvent **jamais** être modifiés. + + ```C + void set_to_two(int a) { // a: nouvelle variable + // valeur de a est une copie de x + // lorsque la fonction est appelée, ici -1 + + a = 2; // la valeur de a est fixée à 2 + } // a est détruite + + int main() { + int x = -1; + set_to_two(x); // -1 est passé en argument + // x vaudra toujours -1 ici + } + ``` + + +## Arguments de fonctions: pointeurs + +- Pour modifier un variable, il faut passer son **adresse mémoire**. +- L'adresse d'une variable, `x`{.C}, est accédé par `&x`{.C}. +- Un **pointeur** vers une variable entière a le type, `int *x`{.C}. +- La syntaxe `*x`{.C} sert à **déréférencer** le pointeur (à accéder à la mémoire pointée). + + +## Exemple + +```C +void set_to_two(int *a) { + // a contient une copie de l'adresse de la + // variable passée en argument + + *a = 2; // on accède à la valeur pointée par a, + // et on lui assigne 2 +} // le pointeur est détruit, pas la valeur pointée +int main() { + int x = -1; + set_to_two(&x); // l'adresse de x est passée + // x vaudra 2 ici +} +``` \ No newline at end of file diff --git a/Algorithmique/Cours/02-intro-c.pdf b/Algorithmique/Cours/02-intro-c.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1601fef5b7bee8b33491469319e3eba43e87708a Binary files /dev/null and b/Algorithmique/Cours/02-intro-c.pdf differ diff --git a/Programmation/Cours/01-command_line.pdf b/Programmation/Cours/01-command_line.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5cc87faeef93a77235e0c05e1df8aee186089205 Binary files /dev/null and b/Programmation/Cours/01-command_line.pdf differ diff --git a/Exercices/serie_01.md b/Programmation/Exercices/serie_01.md similarity index 100% rename from Exercices/serie_01.md rename to Programmation/Exercices/serie_01.md diff --git a/Exercices/serie_01.pdf b/Programmation/Exercices/serie_01.pdf similarity index 100% rename from Exercices/serie_01.pdf rename to Programmation/Exercices/serie_01.pdf diff --git a/Exercices/serie_02.md b/Programmation/Exercices/serie_02.md similarity index 100% rename from Exercices/serie_02.md rename to Programmation/Exercices/serie_02.md diff --git a/Exercices/serie_02.pdf b/Programmation/Exercices/serie_02.pdf similarity index 100% rename from Exercices/serie_02.pdf rename to Programmation/Exercices/serie_02.pdf diff --git a/Programmation/Exercices/serie_03.md b/Programmation/Exercices/serie_03.md new file mode 100644 index 0000000000000000000000000000000000000000..5870e6e7240b76df186c6bd5c94b15b6dd18cf04 --- /dev/null +++ b/Programmation/Exercices/serie_03.md @@ -0,0 +1,47 @@ +--- +title: "Programmation séquentielle" +subtitle: "Série 3 - Estimation de la valeur de pi" +date: 27.09.2022 +--- + +# Buts + +- Utilisation de boucles, tests et nombres aléatoires + +# 1 - Estimation de $\pi$ à l'aide de séries numériques + +Ecrire un programme qui calcule différentes approximations de la valeur de $\pi$ en vous servant des formules +ci-dessous. La constante `M_PI` est déclaré dans le header `<math.h>`, utiliser cette valeur comme référence pour estrimer l'erreur +dans les approximations. + +## Formules + +\begin{equation} +\sum_{n=1}^{\infty} {1 \over {n^4}} = {\pi^4 \over 90} +\end{equation} + +\begin{equation} +\sum_{n=1}^{\infty} {{(-1)^{n+1}} \over {n^2}} = {\pi^2 \over 12} +\end{equation} + +\begin{equation} +\prod_{n=1}^{\infty} \left( {2n \over {2n-1}} \right) \left( {2n \over {2n+1}} \right) = {\pi \over 2} +\end{equation} + +Pour exécuter votre programme, vous aurez besoin de la librairie `math` : + + `#include <math.h>` et compiler avec l'option `-lm`. + +Vous aurez également besoin des fonctions `pow` et `sqrt`. Utiliser `man 3 pow` et `man 3 sqrt` pour obtenir la documentation de ces fonctions. + +# 2 - Estimation de $\pi$ par la méthode de Monte-Carlo + +Considérons le carré $C = [-1, 1] x [-1, 1]$. Si on tire une probabilité uniforme un point (x, y), quelle est la +probabilité que ce point tombe dans le disque $D$ de rayon 1 centré en (0, 0) ? Cette probabilité est en fait +égale au rapport de l’aire du disque sur l’aire du carré. + +En effectuant $N$ tirages et en comptabilisant la variable $cpt$ de fois pour laquelle le point tombe dans $D$, le +rapport $cpt/N$ donne une estimation de la probabilité de tomber dans le disque et donc du rapport de l’aire +du disque sur l’aire du carré. Si vous faites un dessein vous vous apercevrez que $cpt/N \rightarrow \pi/4$. Cette +estimation est d’autant meilleure que N est grand. Pour déterminer si un point tiré aléatoirement est dans le +disque $D$ pensez au théorème de Pythagore. \ No newline at end of file diff --git a/Programmation/Exercices/serie_03.pdf b/Programmation/Exercices/serie_03.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0a2779a1d08cc896e9f7e60f47b8f1f67e64c550 Binary files /dev/null and b/Programmation/Exercices/serie_03.pdf differ