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
Select Git revision

Target

Select target project
  • programmation_sequentielle/cours
  • yassin.elhakoun/cours-de-prog
2 results
Select Git revision
Show changes
Commits on Source (118)
Showing
with 1177 additions and 206 deletions
...@@ -2,3 +2,4 @@ ...@@ -2,3 +2,4 @@
.vscode .vscode
*.html *.html
*.xopp *.xopp
mermaid-filter.err
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Ce programme prend en argument deux
// entiers se trouvant chacun
// sur une nouvelle ligne et affiche
// la somme des deux entiers en argument
// sur une nouvelle ligne.
// Ex:
// 12
// 19
//
// 31
void sum_two() {
int a, b;
scanf("%d %d", &a, &b);
printf("\n%d\n", a + b);
}
// Ce programme prend en argument 12 nombres à
// virgule flottante se trouvant chacun
// sur une nouvelle ligne. Multiplie chaque
// nombre par deux et affiche leur somme
// sur une nouvelle ligne suivi de CHF.
// Ex:
// 12.2
// 45.5
// 1.5
// 65.1
// 89.4
// 567.6
// 112.8
// 67.0
// 35.1
// 112.2
// 3.3
// 9.8
//
// 2243.000000 CHF
void sum_array() {
float sum = 0.0;
for (int i = 0; i < 12; ++i) {
float a = 0.0;
scanf("%f", &a);
a *= 2.0;
sum += a;
}
printf("\n%f CHF\n", sum);
}
// Ce programme prend en argument 2 chaînes de
// caractères sur des lignes séparées (longueur
// max de 80), les sépare au milieu et retourne
// les 4 chaînes chacune sur une nouvelle ligne
// (si la longueur N est paire on sépare en 2
// chaînes de longueur N/2, sinon la première
// aura une longueur de N/2 et la seconde N/2+1).
// Ex:
// abcdefgh
// asdfghjkl
//
// abcd
// efgh
// asdf
// ghjkl
void split_mid() {
char str_one[2][41], str_two[2][41];
for (int j = 0; j < 2; ++j) {
char str[81];
scanf("%s", str);
int n = strlen(str);
int n1 = n / 2;
int n2 = n - n1;
for (int i = 0; i < n1; ++i) {
str_one[j][i] = str[i];
}
str_one[j][n1] = '\0';
for (int i = 0; i < n2; ++i) {
str_two[j][i] = str[n1 + i];
}
str_two[j][n2] = '\0';
}
printf("\n");
for (int j = 0; j < 2; ++j) {
printf("%s\n", str_one[j]);
printf("%s\n", str_two[j]);
}
}
int main() {
/* sum_two(); */
sum_array();
/* split_mid(); */
}
CC:=clang
CFLAGS:=-Wall -Wextra -pedantic -g -fsanitize=address -fsanitize=leak -std=c2x
LDFLAGS:=-fsanitize=address -fsanitize=leak
main: opaque.o main.o
$(CC) -o $@ $(CFLAGS) $^ $(LDFLAGS)
opaque.o: opaque.h
.PHONY: clean
clean:
rm -f *.o main
\ No newline at end of file
#include "opaque.h"
#include <stdio.h>
int main()
{
table t;
init(&t);
set(t, 10);
printf("%d\n", get(t));
destroy(&t);
}
#include "opaque.h"
#include <stdlib.h>
struct _table
{
int len;
int *data;
};
void init(table *tab)
{
*tab = malloc(sizeof(struct _table));
}
void destroy(table *tab)
{
free(*tab);
*tab = NULL;
}
int get(table tab)
{
return tab->len;
}
void set(table tab, int len)
{
tab->len = len;
}
#ifndef OPAQUE_H
#define OPAQUE_H
struct _table;
typedef struct _table *table;
void init(table *tab);
void set(table tab, int len);
int get(table tab);
void destroy(table *tab);
#endif
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Enter n: "); // affichage chaine de caractères
int n = 0; // déclaration et initialisation de n
scanf("%d", &n); // entrée au clavier
int sum = 0; // déclaration et initialisation de sum
for (int i = 0; i <= n; ++i) { // boucle for
sum += i;
}
printf("The sum of the %d first integers is: %d\n", n, sum); // affichage de n et sum
printf("The analytical formula is %d * (%d + 1) / 2 = %d.\n", n, n, n*(n+1)/2); // on peut mettre n'importe quelle expression
if (sum != n * (n+1) / 2) { // branchement conditionnel
printf("Error: The answer we computed is wrong.\n");
return EXIT_FAILURE; // code d'erreur
}
return EXIT_SUCCESS; // code de réussite
}
\ No newline at end of file
---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -4
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignConsecutiveMacros: true
AlignEscapedNewlines: Left
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortLambdasOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BitFieldColonSpacing: Both
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: MultiLine
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakInheritanceList: AfterColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: AfterColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
SortPriority: 0
- Regex: '^<.*\.h>'
Priority: 1
SortPriority: 0
- Regex: '^<.*'
Priority: 2
SortPriority: 0
- Regex: '.*'
Priority: 3
SortPriority: 0
IncludeIsMainRegex: '([-_](test|unittest))?$'
IncludeIsMainSourceRegex: ''
IndentCaseLabels: false
IndentCaseBlocks: false
IndentGotoLabels: false
IndentPPDirectives: None
IndentExternBlock: AfterExternBlock
IndentWidth: 4
IndentWrappedFunctionNames: true
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Right
RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- 'c++'
- 'C++'
CanonicalDelimiter: ''
BasedOnStyle: google
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
- ParseTestProto
- ParsePartialTestProto
CanonicalDelimiter: ''
BasedOnStyle: google
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard: Auto
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 4
UseCRLF: false
UseTab: Never
WhitespaceSensitiveMacros:
- STRINGIZE
- PP_STRINGIZE
- BOOST_PP_STRINGIZE
...
mermaid-filter.err .puppeteer.json
index.md
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
PDFOPTIONS = -t beamer PDFOPTIONS = -t beamer
PDFOPTIONS += --pdf-engine=xelatex PDFOPTIONS += --pdf-engine=xelatex
PDFOPTIONS += -F mermaid-filter
PDFOPTIONS += --default-image-extension=pdf PDFOPTIONS += --default-image-extension=pdf
PDFOPTIONS += -V theme:metropolis PDFOPTIONS += -V theme:metropolis
PDFOPTIONS += -V themeoptions:numbering=none -V themeoptions:progressbar=foot PDFOPTIONS += -V themeoptions:numbering=none -V themeoptions:progressbar=foot
...@@ -19,9 +20,15 @@ MD=$(wildcard *.md) # Tous les fichiers .md ...@@ -19,9 +20,15 @@ MD=$(wildcard *.md) # Tous les fichiers .md
HTML=$(MD:%.md=%.html) # Pour les fichier html on transforme .md -> .html HTML=$(MD:%.md=%.html) # Pour les fichier html on transforme .md -> .html
PDF=$(MD:%.md=%.pdf) # Pour les fichier pdf on transforme .md -> .pdf PDF=$(MD:%.md=%.pdf) # Pour les fichier pdf on transforme .md -> .pdf
MARKDOWN=$(MD:%.md=%.markdown) # Pour les fichier markdown on transforme .md -> .markdown MARKDOWN=$(MD:%.md=%.markdown) # Pour les fichier markdown on transforme .md -> .markdown
CHROMIUM:=$(shell which chromium || which chromium-browser)
# all: $(PDF) $(HTML) # La cible par défaut (all) exécute les cibles %.html et %.pdf # all: $(PDF) $(HTML) # La cible par défaut (all) exécute les cibles %.html et %.pdf
all: $(PDF) # La cible par défaut (all) exécute les cibles %.html et %.pdf all: puppeteer $(PDF) # La cible par défaut (all) exécute les cibles %.html et %.pdf
puppeteer:
@echo "Setting chromium to $(CHROMIUM) for puppeteer"
# @echo "{\n\"executablePath\":" \"$(CHROMIUM)\" ",\n\"args\": [\"--no-sandbox\"]\n}" > .puppeteer.json
@echo -e "{\n\"executablePath\":" \"$(CHROMIUM)\" ",\n\"args\": [\"--no-sandbox\"]\n}" > .puppeteer.json
markdown: $(MARKDOWN) # La markdown les cibles %.markdown markdown: $(MARKDOWN) # La markdown les cibles %.markdown
......
--- ---
title: "Allocation dynamique de mémoire" title: "Allocation dynamique de mémoire"
date: "2022-11-22" date: "2024-12-03"
--- ---
# Allocation dynamique de mémoire (1/9) # Allocation dynamique de mémoire (1/8)
- La fonction `malloc`{.C} permet d'allouer dynamiquement (pendant l'exécution du programme) une zone de mémoire contiguë. - La fonction `malloc`{.C} permet d'allouer dynamiquement (pendant l'exécution du programme) une zone de mémoire contiguë.
...@@ -15,22 +15,44 @@ date: "2022-11-22" ...@@ -15,22 +15,44 @@ date: "2022-11-22"
- Retourne un pointeur sur la zone mémoire ou `NULL`{.C} en cas d'échec: **toujours vérifier** que la valeur retournée est `!= NULL`{.C}. - Retourne un pointeur sur la zone mémoire ou `NULL`{.C} en cas d'échec: **toujours vérifier** que la valeur retournée est `!= NULL`{.C}.
- Le *type* du retour est `void *`{.C} (un pointeur de type quelconque). - Le *type* du retour est `void *`{.C} (un pointeur de type quelconque).
# Allocation dynamique de mémoire (2/9) # Allocation dynamique de mémoire (2/8)
- Allocation *sur le tas* d'un type de base:
```C
int *val = malloc(sizeof(int)); // réserve 4 octets sur le tas
*val = 4; // les 4 octets contiennent la valeur 4
```
- Presque la même chose que:
```C
int val = 4; // ici l'allocation et l'initialisation
// sont faites en une fois mais se trouve sur
// le *tas* (mémoire managée automatiquement)
```
- Attention:
```C
int *val = 4; // Ca c'est très faux...
```
# Allocation dynamique de mémoire (3/9)
- On peut allouer et initialiser une `fraction_t`{.C}: - On peut allouer et initialiser une `fraction_t`{.C}:
```C ```C
fraction_t *num = malloc(sizeof(fraction_t)); fraction_t *frac = malloc(sizeof(fraction_t));
num->num = 1; frac->num = 1;
num->denom = -1; frac->denom = -1;
``` ```
- La zone mémoire **n'est pas** initialisée. - La zone mémoire **n'est pas** initialisée.
- Désallouer la mémoire explicitement $\Rightarrow$ **fuites mémoires**. - Désallouer la mémoire explicitement, sinon **fuites mémoires**.
- Il faut connaître la **taille** des données à allouer. - Il faut connaître la **taille** des données à allouer.
![La représentation mémoire de `fraction_t` et fuites.](figs/pointer_struct_ok.svg){width=100%} ![La représentation mémoire de `fraction_t` et fuites.](figs/pointer_struct_ok.svg){width=100%}
# Allocation dynamique de mémoire (3/9) # Allocation dynamique de mémoire (4/9)
- La fonction `free()`{.C} permet de libérer une zone préalablement allouée avec `malloc()`{.C}. - La fonction `free()`{.C} permet de libérer une zone préalablement allouée avec `malloc()`{.C}.
...@@ -38,13 +60,13 @@ date: "2022-11-22" ...@@ -38,13 +60,13 @@ date: "2022-11-22"
#include <stdlib.h> #include <stdlib.h>
void free(void *ptr); void free(void *ptr);
``` ```
- Pour chaque `malloc()`{.C} doit correspondre exactement un `free()`{.C}. - A chaque `malloc()`{.C} doit correspondre exactement un `free()`{.C}.
- Si la mémoire n'est pas libérée: **fuite mémoire** (l'ordinateur plante quand il y a plus de mémoire). - Si la mémoire n'est pas libérée: **fuite mémoire** (l'ordinateur plante quand il y a plus de mémoire).
- Si la mémoire est **libérée deux fois**: *seg. fault*. - Si la mémoire est **libérée deux fois**: *seg. fault*.
- Pour éviter les mauvaises surprises mettre `ptr`{.C} à `NULL`{.C} après - Pour éviter les mauvaises surprises mettre `ptr`{.C} à `NULL`{.C} après
libération. libération.
# Allocation dynamique de mémoire (4/9) # Allocation dynamique de mémoire (5/9)
## Tableaux dynamiques ## Tableaux dynamiques
...@@ -64,12 +86,12 @@ date: "2022-11-22" ...@@ -64,12 +86,12 @@ date: "2022-11-22"
```C ```C
int *p = malloc(50 * sizeof(int)); int *p = malloc(50 * sizeof(int));
// initialize somehow // initialize somehow
double a = p[7]; int a = p[7];
double b = *(p + 7); // on avance de 7 "double" int b = *(p + 7); // on avance de 7 "int"
p[0] == *p; // le pointeur est le premier élément p[0] == *p; // le pointeur est le premier élément
``` ```
# Allocation dynamique de mémoire (5/9) # Allocation dynamique de mémoire (6/9)
## Arithmétique de pointeurs ## Arithmétique de pointeurs
...@@ -83,24 +105,6 @@ $$ ...@@ -83,24 +105,6 @@ $$
\mathcal{O}(1). \mathcal{O}(1).
$$ $$
# Allocation dynamique de mémoire (6/9)
## Questions
```C
int *p = malloc(50 * sizeof(int));
for (int i = 0; i < 50; ++i)
p[i] = 0; // ça fait quoi?
sizeof(p); // ça vaut quoi?
sizeof(*p); // ça vaut quoi?
p[10] = -1; // ça fait quoi?
(p + 20) = -1; // ça fait quoi?
*(p + 20) = -1; // ça fait quoi?
p[-1] = -1; // ça fait quoi?
p[50] = -1; // ça fait quoi?
7[p] = 12; // ça fait quoi?
```
# Allocation dynamique de mémoire (7/9) # Allocation dynamique de mémoire (7/9)
## Pointeur de pointeur ## Pointeur de pointeur
...@@ -112,7 +116,9 @@ p[50] = -1; // ça fait quoi? ...@@ -112,7 +116,9 @@ p[50] = -1; // ça fait quoi?
int *b = &a; int *b = &a;
int **c = &b; int **c = &b;
``` ```
- Chaque `*`{.C} ou `&`{.C} rajoute une indirection. - En effet, un pointeur est aussi une variable (une variable qui contient une adresse mémoire).
- Chaque `*`{.C} rajoute une indirection.
# Allocation dynamique de mémoire (8/9) # Allocation dynamique de mémoire (8/9)
...@@ -132,7 +138,59 @@ p[50] = -1; // ça fait quoi? ...@@ -132,7 +138,59 @@ p[50] = -1; // ça fait quoi?
int a = p[5][8]; // on indexe dans chaque dimension int a = p[5][8]; // on indexe dans chaque dimension
``` ```
- Ceci est une matrice (un tableau de tableau). - Ceci est une matrice (un tableau de tableaux).
# Tableau dynamique en argument d'une fonction
## Implémenter la fonction ci-dessous
```C
int32_t *p = malloc(50 * sizeof(*p));
initialize_to(p, 50, -1); // initialise un tableau à -1
free(p); // ne pas oublier
```
. . .
```C
void initialize_to(int32_t *p, size_t size, int32_t val) {
for (size_t i = 0; i < size; ++i) {
p[i] = val;
}
}
```
# Tableau dynamique retourné d'une fonction
## Implémenter la fonction ci-dessous
```C
// alloue un tableau de taille 50 et l'initialise à -1
int32_t *p = initialize_to(50, -1);
free(p); // ne pas oublier
```
. . .
```C
int32_t *initialize_to(size_t size, int32_t val) {
int32_t *p = malloc(size * sizeof(*p));
for (size_t i = 0; i < size; ++i) {
p[i] = val;
}
return p;
}
```
## Pourquoi on peut retourner un tableau dynamique et pas un statique?
. . .
* Le tableau est alloué sur le **tas** et non sur la **pile**.
* La mémoire est gérée manuellement sur le tas, automatiquement sur la pile.
# Les *sanitizers* # Les *sanitizers*
...@@ -148,7 +206,7 @@ Outils pour leur détection: ...@@ -148,7 +206,7 @@ Outils pour leur détection:
* Valgrind (outil externe). * Valgrind (outil externe).
* Sanitizers (ajouts de marqueurs à la compilation). * Sanitizers (ajouts de marqueurs à la compilation).
Ici on utilise les sanitizers (modification de la ligne de compilation): Ici on utilise les sanitizers (modification de la ligne de compilation, modifiez donc vos *Makefile*):
```bash ```bash
gcc -o main main.c -g -fsanitize=address -fsanitize=leak gcc -o main main.c -g -fsanitize=address -fsanitize=leak
...@@ -156,3 +214,69 @@ gcc -o main main.c -g -fsanitize=address -fsanitize=leak ...@@ -156,3 +214,69 @@ gcc -o main main.c -g -fsanitize=address -fsanitize=leak
**Attention:** Il faut également faire l'édition des liens avec les sanitizers. **Attention:** Il faut également faire l'édition des liens avec les sanitizers.
# Questions
## Que fait le code suivant?
```C
int *p = malloc(50 * sizeof(int));
p[10] = 1;
```
. . .
* On alloue de la place pour 50 entiers.
* On initialise le 11ème élément du tableau à 1.
* Les autres éléments sont non-initialisés.
# Questions
## Que fait le code suivant?
```C
float *p = malloc(50);
p[20] = 1.3;
```
. . .
* On déclare un pointeur de floats de taille 50 octets.
* Mais il ne peut contenir que `50 / 4` floats (un float est composé de 32 bits).
* On dépasse la capacité de la mémoire allouée: comportement indéfini.
# Questions
* Soit le code suivant
```C
int *p = malloc(50 * sizeof(int));
for (int i = 0; i < 50; ++i) {
p[i] = 0;
}
```
* Le réécrire en utilisant uniquement l'arithmétique de pointeurs.
. . .
```C
int *p = malloc(50 * sizeof(int));
for (int i = 0; i < 50; ++i) {
*(p+i) = 0;
}
```
# Questions
## Que valent les expressions suivantes?
```C
in32_t *p = malloc(50 * sizeof(int32_t));
sizeof(p);
sizeof(*p);
(p + 20);
*(p + 20);
p[-1];
p[50];
7[p];
```
--- ---
title: "Boucles et conditions" title: "Boucles et conditions"
date: "2022-09-27" date: "2024-09-24"
patat:
wrap: true
margins:
left: 10
right: 10
--- ---
# Quiz # Quiz
...@@ -91,6 +86,7 @@ if (x) { // si x s'évalue à `vrai` ...@@ -91,6 +86,7 @@ if (x) { // si x s'évalue à `vrai`
int i = 0; int i = 0;
while (i < 10) { while (i < 10) {
if (i == 3) { if (i == 3) {
i += 1;
continue; continue;
} }
printf("%d\n", i); printf("%d\n", i);
...@@ -127,11 +123,12 @@ if (x) { // si x s'évalue à `vrai` ...@@ -127,11 +123,12 @@ if (x) { // si x s'évalue à `vrai`
```C ```C
int main() { int main() {
// ... // ...
if (error) if (error) {
return EXIT_FAILURE; return EXIT_FAILURE;
else } else {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
}
``` ```
- Le code d'erreur est lu dans le shell avec `$?`{.bash} - Le code d'erreur est lu dans le shell avec `$?`{.bash}
......
--- ---
title: "Introduction à la l'interface en ligne de commande" title: "Introduction à la l'interface en ligne de commande"
date: "2022-09-27" date: "2024-09-24"
--- ---
# Introduction # Introduction
......
--- ---
title: "Compilation séparée et Makefile" title: "Compilation séparée et Makefile"
date: "2022-11-01" date: "2024-11-19"
patat:
wrap: true
margins:
left: 10
right: 10
--- ---
# Prototypes de fonctions (1/3) # Prototypes de fonctions (1/3)
...@@ -322,7 +317,7 @@ rebuild: clean hello ...@@ -322,7 +317,7 @@ rebuild: clean hello
::: :::
:::::::::::::: ::::::::::::::
# Factorisation <!-- # Factorisation
:::::::::::::: {.columns} :::::::::::::: {.columns}
...@@ -400,4 +395,4 @@ rebuild: clean hello ...@@ -400,4 +395,4 @@ rebuild: clean hello
- `$<` : la première dépendance - `$<` : la première dépendance
- `$*` : le nom de la cible sans extension - `$*` : le nom de la cible sans extension
-->
---
title: "Précisions pour l'examen"
date: "2024-11-05"
---
# Administration
- L'examen se déroule sur `nexus`.
- L'examen dure au plus 4h (il est prévu pour 3 exceptions jusqu'à 4).
- Votre code devra être dans le répertoire prévu à cet effet.
- Chaque exercice dans un répertoire (`ex1`, `ex2`, `ex3`, ...).
- Compilation
- Il est impératif de compiler avec les warnings.
- Vous devez être capables d'écrire la ligne de compilation de votre code:
```console
gcc -o ex1 ex1.c -Wall -Wextra -pedantic
```
# Documents
- On fournit:
- Les slides d'algorithmique.
- Les slides de programmation séquentielle.
- Vous pouvez avoir:
- Une feuille A4 recto-verso ***manuscrite***.
# Les exercices
- Deux ou trois parties à chaque énoncé:
- Une partie "théorique" qui décrit les structures de données et fonctionnalités.
- Une partie "technique" qui propose un exemple d'exécution de votre programme avec entrées et sorties.
- Une partie "exemple" (pas obligatoire) où d'autres exemples sont donnés afin de tester l'exécution de votre programme.
- Votre code doit avoir **exactement** le comportement des exemples donnés **sous peine de sanctions**.
- Chaque code doit être **dans un unique fichier .c** (`ex1.c`, `ex2.c`, ...).
- Donc **inutile** et **interdit** d'écrire d'autres fichiers
# Évaluation (technique)
- L'évaluation se base surtout sur des critères de fonctionnement:
- le code compile-t-il? (on regarde même pas si la réponse est non)
- s'exécute-t-il? (on regarde un peu)
- le code demandé est-il réalisé?
- donne-t-il des résultats corrects?
- votre code possède-t-il des comportements indéfinis?
- Si vous laissez des warnings vous serez pénalisé·e·s.
# Évaluation (style)
- Le code est-il joli?
- Présentation (indentation cohérente, variables nommées de façon raisonnable).
- Modularité (utilisation de fonctions).
- Pas de variables globales inutiles.
- Utilisation de boucles, structures de contrôle, struct, ...
- Fonctions récursives, ...
# Les exemples
- Chaque exemple contient:
- un input à rentrer à la ligne de commande (on peut copier-coller l'input de l'énoncé).
- un output à écrire dans le terminal (on peut comparer la sortie avec celle de l'énoncé).
- La structure de l'input doit être **exactement** la même que celle décrite dans l'énoncé.
- Pour l'input il faut impérativement utiliser `argc` et `argv[]`.
- L'output de vos exercices doit être celui de l'énoncé.
Et maintenant place à des exemples (simplifiés)!
# Exercice 1
Ce programme prend en argument deux entiers et affiche
leur somme sur une nouvelle ligne.
## Exemple
```bash
./prog 12 19
31
```
# Exercice 2
\footnotesize
Ce programme prend en argument un nombre entier `N` puis des nombres à virgule flottante.
Il y aura exactement `N` nombres à virgule flottante.
Ensuite, votre programme multiplie chaque nombre à virgule flottante par deux et affiche la somme
sur une nouvelle ligne suivi de CHF.
## Exemple
```bash
./prog 12 12.2 45.5 1.5 65.1 89.4 567.6 112.8 67.0 35.1 112.2 3.3 9.8
2243.000000 CHF
```
# Exercice 3
Ce programme prend en argument 2 chaînes de caractères (longueur max de 80),
les sépare au milieu et retourne les 4 chaînes chacune sur une nouvelle ligne
(si la longueur N est paire on sépare en 2 chaînes de longueur N/2, sinon la première
aura une longueur de N/2 et la seconde N/2+1).
## Exemple
```bash
./prog abcdefgh asdfghjkl
abcd
efgh
asdf
ghjkl
```
---
title: "Lecture/écriture de fichiers"
date: "2025-03-31"
---
# Les fichier en C
* Un fichier en C est représenté par un pointeur de fichier.
```C
#include <stdio.h>
FILE *fp;
```
* `FILE *`{.C} est une structure de donnée *opaque* contenant les informations sur l'état du fichier.
* Il est manipulé à l'aide de fonctions dédiées.
* Le pointeur de fichier est toujours passé *par copie*.
# Manipulations de fichier
* Pour lire/écrire dans un fichier il faut toujours effectuer trois étapes:
1. Ouvrir le fichier (`fopen()`{.C}).
2. Écrire/lire dans le fichier (`fgets()`{.C}, `fputs()`{.C}, `fread()`{.C}, `fwrite()`{.C}, ...).
3. Fermer le fichier (`fclose()`{.C}).
* Nous allons voir brièvement ces trois étapes.
# Ouverture d'un fichier
* L'ouverture d'un fichier se fait avec la fonction `fopen()`{.C}
```C
FILE *fp = fopen(filename, mode);
```
* `filename`{.C} est une chaîne de caractères (incluant le chemin).
* `mode`{.C} est le mode d'ouverture (`"r"`{.C}, `"w"`{.C}, ... voir `man 3 fopen`{.bash}) qui est une chaîne de caractères.
* Si l'ouverture échoue (pas la bonne permission, ou n'existe pas) `fopen()`{.C} retourne `0`.
* **Toujours** tester le retour de `fopen()`{.C}
```C
if (NULL == fp) {
fprintf(stderr, "Can't open output file %s!\n",
filename); // affiche dans le canal d'erreur
exit(EXIT_FAILURE);
}
```
# Fermeture d'un fichier
* Il faut **toujours** fermer un fichier à l'aide de `fclose()`{.C}
```C
FILE *fp = fopen("mon_fichier", "w");
// écritures diverses
fclose(fp);
```
* Les données sont transférées dans une mémoire tampon, puis dans le disques.
* Si la mémoire tampon est pleine, le fichier est fermé, ... les données sont écrites sur le disque.
* Si la mémoire tampon contient encore des données à la fin du programme les données sont **perdues**.
# Lecture d'un fichier (1/2)
```C
char *fgets(char *s, int size, FILE *stream)
```
* Lit une ligne de taille d'au plus `size-1` et la stocke dans `s`, depuis `stream`.
* Retourne `s` ou `NULL` si échoue.
```C
FILE *fp = fopen("text.txt", "r");
char buffer[100];
fgets(buffer, 37, fp);
// lit 36 caractères au plus et les écrit dans buffer
// s'arrête si rencontre EOF, ou "\n".
// ajoute un "\0" terminal
fclose(fp);
```
# Lecture d'un fichier (2/2)
```C
size_t fread(void *ptr, size_t size, size_t nmemb,
FILE *stream)
```
* Lit `nmemb` éléments de taille `size` octets et les écrit à l'adresse `ptr` dans le fichier `stream`.
* Retourne le nombre d'éléments lus.
```C
FILE *fp = fopen("doubles.bin", "rb");
double buffer[100];
size_t num = fread(buffer, sizeof(double), 4, fp);
// lit 4 double, se trouvant dans le fichier fp au
// format binaire et les écrit dans buffer, puis
// retourne 4
fclose(fp);
```
# Écriture dans un fichier (1/2)
```C
int fprintf(FILE *stream, const char *format, ...)
```
* Écrit la chaîne de caractères `format` dans le fichier stream.
* `format` a la même syntaxe que pour `printf()`.
* Retourne le nombre de caractères écrit sans le `\0` terminal(si réussite).
```C
FILE *fp = fopen("text.txt", "w");
fprintf(fp, "Hello world! We are in %d\n", 2020);
// Écrit "Hello world! We are in 2020"
// dans le fichier fp
fclose(fp);
```
# Écriture dans un fichier (2/2)
```C
size_t fwrite(const void *ptr, size_t size,
size_t nmemb, FILE *stream)
```
* Écrit `nmemb` éléments de taille `size` octets se trouvant à l'adresse `ptr` dans le fichier `stream`.
* Retourne le nombre d'éléments écrits.
```C
FILE *fp = fopen("doubles.bin", "wb");
double buffer[] = {1.0, 2.0, 3.0, 7.0};
size_t num = fwrite(buffer, sizeof(double), 4, fp);
// écrit 4 double, se trouvant à l'adresse
// buffer dans le fichier fp au format binaire
// retourne 4
fclose(fp);
```
# Les pointeurs de fichiers spéciaux
* Il existe trois `FILE *`{.C} qui existent pour tout programme:
* `stdin`{.C}: l'entrée standard.
* `stdout`{.C}: la sortie standard.
* `stderr`{.C}: l'erreur standard.
* Lors d'un fonctionnement dans le terminal:
* l'entrée standard est le *clavier*
* la sortie et erreur standard sont affichés dans le *terminal*.
* Ainsi on a
```C
fprintf(stdout, "texte\n"); // == printf("texte\n");
int a;
fscanf(stdin, "%d", &a); // == scanf("%d", &a);
```
---
title: "Fonctions d'ordre supérieur"
date: "2025-05-16"
---
# Tribute
Rendons à Cesar:
* Ces slides ont été écrits par Michaël El Kharroubi
* J'arrive pas à changer l'auteur simplement sur un slide donc....
* Merci à lui pour ses efforts et qu'il soit crédité comme il se doit!
# Présentation du problème
* Imaginons que nous ayons la structure d'un vecteur en 3 dimensions suivante
```C
typedef struct _vec3 {
double x;
double y;
double z;
} vec3;
```
* On souhaite implémenter 3 opérations différentes
* La somme
* La soustraction
* Le produit de Hadamard (produit composantes à composantes)
# Présentation du problème (suite)
On a donc les fonctions suivantes
* Addition
```c
vec3 add(vec3 lhs, vec3 rhs){
vec3 res;
res.x = lhs.x + rhs.x;
res.y = lhs.y + rhs.y;
res.z = lhs.z + rhs.z;
return res;
}
```
# Présentation du problème (suite)
* Soustraction
```c
vec3 sub(vec3 lhs, vec3 rhs){
vec3 res;
res.x = lhs.x - rhs.x;
res.y = lhs.y - rhs.y;
res.z = lhs.z - rhs.z;
return res;
}
```
# Présentation du problème (suite)
* Produit de Hadamard
```c
vec3 mul(vec3 lhs, vec3 rhs){
vec3 res;
res.x = lhs.x * rhs.x;
res.y = lhs.y * rhs.y;
res.z = lhs.z * rhs.z;
return res;
}
```
* Quel est le problème avec ces trois fonctions?
# Présentation du problème (suite)
* Le problème avec ces fonctions c'est la **répétition**.
* La seule chose qui change, c'est l'opérateur (+,-,*).
* Problèmes possibles
* Tentation de copier-coller du code (donc risque d'erreurs)
* Faible résilience au changement (imaginons que je veuille des vecteurs 2d, 4d, nd)
# Présentation du problème (solution)
* Vecteur de taille dynamique
```c
typedef struct _vecn {
int size;
double *xs;
} vecn;
```
* Règle le problème de résilience du code, mais ne règle pas le problème de répétition...
# Fonction d'ordre supérieur (solution au problème)
* Pour notre problème, nous aimerions donc découpler l'opération (opération entre deux termes : +,-,*) de l'itération sur les composantes.
* Ce qui nous donne conceptuellement en pseudo c
```c
// Attention pseudo c, ne compile pas !!!!!
vec3 apply_operator(operator op, vec3 lhs, vec3 rhs){
vec3 res;
res.x = lhs.x op rhs.x;
res.y = lhs.y op rhs.y;
res.z = lhs.z op rhs.z;
return res;
}
```
# Fonction d'ordre supérieur (solution au problème)
* Avec notre fonction conceptuelle `apply_operator`, on pourrait faire (toujours en pseudo c)
```c
// Attention pseudo c, ne compile pas !!!!!
vec3 add(vec3 lhs, vec3 rhs){
return apply_operator(+, lhs, rhs);
}
vec3 sub(vec3 lhs, vec3 rhs){
return apply_operator(-, lhs, rhs);
}
vec3 mul(vec3 lhs, vec3 rhs){
return apply_operator(*, lhs, rhs);
}
```
* En fait, on vient de créer ce qu'on appelle une fonction d'ordre supérieur.
# Fonction d'ordre supérieur (définition)
* Une fonction d'ordre supérieur est une fonction qui prend en paramètre et/ou retourne une(des) autre(s) fonction(s).
* Si on essayait de définir `operator`, c'est en fait une fonction qui prend deux paramètres (un terme de gauche et un terme de droite). On s'en aperçoit clairement avec la notation préfix (polonaise).
* `L + R -> + L R`
* `L - R -> - L R`
* `L * R -> * L R`
* Comment l'implémenter concrètement en C?
# Implémentation
* Si on reprend la signature de notre fonction d'exemple, on a
```c
vec3 apply_operator(operator op, vec3 lhs, vec3 rhs);
```
* Nous avons déterminé que les `operator` étaient des fonctions qui prennaient deux paramètres.
* Pour passer une fonction en paramètre en C, nous devons la passer par référence, c'est à dire à l'aide d'un pointeur de fonction.
# Pointeur de fonctions
* Un pointeur de fonction se définit ainsi
```c
<type retour> (*<nom ptr fonc>)(<type params(s)>);
```
* Ou encore avec un `typedef`
```c
typedef <type retour> (*<nom ptr fonc>)(<type params(s)>);
```
* Dans notre cas, nous avons donc un type de fonction nommé `operator`, qui prend en entrée deux `double`{.c} et qui retourne un `double`{.c}. Ce qui nous donne
```c
typedef double (*operator)(double, double);
```
# Implémentation (suite)
* En reprenant notre fonction `apply_operator`, on a donc
```c
vec3 apply_operator(operator op, vec3 lhs, vec3 rhs){
vec3 res;
res.x = op(lhs.x, rhs.x);
res.y = op(lhs.y, rhs.y);
res.z = op(lhs.z, rhs.z);
return res;
}
```
* NB : On voit que pour appeler notre fonction passée en paramètre, nous avons pu le faire comme avec n'importe quelle fonction.
# Résultat
```c
typedef double (*operator)(double, double);
vec3 apply_operator(operator op, vec3 lhs, vec3 rhs){
vec3 res;
res.x = op(lhs.x, rhs.x);
res.y = op(lhs.y, rhs.y);
res.z = op(lhs.z, rhs.z);
return res;
}
double add_dbl(double lhs, double rhs){
return lhs + rhs;
}
vec3 add(vec3 lhs, vec3 rhs){
return apply_operator(add_dbl, lhs, rhs);
}
```
# Fonctions d'ordre supérieur appliquées aux tableaux
* Comment appliquer des opérations sur un vecteur de taille n?
* Map (application d'une fonction)
* `add_one`, `square`
* Filter (discrimination selon un prédicat)
* `is_even`, `is_lower_than_five`
* Reduce (réduction d'un vecteur à un seul élément)
* `sum`, `multiply`
# Le map
* Exemple d'application
```c
typedef double (*operator)(double);
double *map(operator op, double *tab, size_t size) {
double *res = malloc(sizeof(*res) * size);
for (int i = 0; i < size; ++i) {
res[i] = op(tab[i]);
}
return res;
}
double add_one(double val) {
return val + 1;
}
double sqr(double val){
return val * val;
}
double tab[] = {1.0, 2.0, 3.0};
double *square = map(sqr, tab, 3);
double *and_one = map(add_one, square, 3);
```
# Le map
* Permettrait le chaînage.
```C
double *sqr_and_one = map(add_one, map(sqr, tab, 3), 3);
```
. . .
* Problème?
. . .
* Allocation dynamique... fuite mémoire.
. . .
* Solution?
. . .
```c
typedef double (*operator)(double);
double *map(operator op, double *tab, size_t size) {
double *res = malloc(sizeof(*res) * size);
for (int i = 0; i < size; ++i) {
res[i] = op(tab[i]);
}
free(tab);
return res;
}
```
* Problème potentiel?
* **Attention au double free!**
---
title: "La généricité"
date: "2025-05-16"
---
# Problématique
* En C on doit écrire chaque algorithme/structures de données pour des types
précis (`int`, `double`, `char`, ...).
```
void int_sort(int size, int tab[size]); // tri d'entiers
void double_sort(int size, int tab[size]); // tri de double
void char_sort(int size, char tab[size]); // tri de char
```
* Duplication du code pour chaque type possible et imaginable.
* On aimerait un moyen pour pouvoir représenter "n'importe quel type" sans
réécrire tout le code.
# La généricité
## Une "solution": `void *`{.C}
* En général, un pointeur connaît son **adresse** et le **type** des données sur lesquelles il pointe.
```C
int *a = malloc(sizeof(*a));
int *b = malloc(sizeof(int));
```
* Un `void *`{.C} le connaît **que** son adresse, au programmeur de pas faire n'importe quoi.
* Vous avez déjà utilisé des fonctions utilisant des `void *`{.C}
```C
void *malloc(size_t size);
void free(void *);
```
# Attention danger
* Ne permet pas au compilateur de vérifier les types.
* Les données pointées n'ayant pas de type, il faut déréférencer avec précaution:
```C
int a = 2;
void *b = &a; //jusqu'ici tout va bien
double c = *b; // argl!
```
* Une attention accrue est nécessaire.
# Cas particuier: on sait pas comment libérer la mémoire
## Exemple
```C
struct tab {
int *t;
}
struct tab *tmp = malloc(sizeof(*tmp));
tmp->t = malloc(10 * sizeof(*(tmp->t)));
free(tmp); // memory leak of tmp->t...
```
. . .
## Solution: tout faire à la main
```C
free(tmp->t);
free(tmp);
```
# Exemple simple
* On souhaite échanger deux pointeurs
```C
int *a = malloc();
int *b = malloc();
swap(&a, &b);
```
* Comment écrire `swap()` pour que le code ci-dessus marche pour n'importe quel
type?
. . .
```C
void swap(void **a, void **b) {
void *tmp = *a;
*a = *b;
*b = tmp;
}
```
# Cas d'utilisation (1/4)
\footnotesize
* La somme d'un tableau de type arbitraire (facile non?)
```C
void sum(void *tab, int length, size_t size_elem, void *zero,
void (*add)(void *, void *)) {
for (int i = 0; i < length; ++i) {
void *rhs = (void *)((char *)tab + i * size_elem);
add(zero, rhs);
} // de combien on "saute" avec un void *?
}
```
* Pour des entiers
```C
void int_add(void *lhs, void *rhs) {
*((int *)lhs) += *((int *)rhs); // cast d'entiers
}
int zero = 0;
int tab[] = {1, -2, 4, 5};
sum(tab, 4, sizeof(int), &zero, int_add);
printf("%d\n", zero);
```
# Cas d'utilisation (2/4)
## Que fait cette fonction?
\footnotesize
```C
void *foo(void *tab, int n_items, int s_items,
bool (*bar)(void *, void *)) {
if (n_items <= 0 || s_items <= 0 || NULL == tab) {
return NULL;
}
void *elem = tab;
for (int i = 1; i < n_items; ++i) {
// void pointer arithmetics is illegal in C
// (gcc is ok though)
void *tmp_elem = (void *)((char *)tab + i*s_items);
if (bar(elem, tmp_elem)) {
elem = tmp_elem;
}
}
return elem;
}
```
# Cas d'utilisation (3/4)
## Avec un tableau de `int`{.C}
```C
bool cmp_int(void *a, void *b) {
return (*(int *)a < *(int *)b);
}
int main() {
int tab[] = {-1, 2, 10, 3, 8};
int *a = foo(tab, 5, sizeof(int), cmp_int);
printf("a = %d\n", *a);
}
```
# Cas d'utilisation (4/4)
## Avec un tableau de `double`{.C}
```C
bool cmp_dbl(void *a, void *b) {
return (*(double *)a < *(double *)b);
}
int main() {
double tab[] = {-1.2, 2.1, 10.5, 3.6, 18.1};
double *a = foo(tab, 5, sizeof(double), cmp_dbl);
printf("a = %f\n", *a);
}
```
...@@ -15,3 +15,4 @@ ...@@ -15,3 +15,4 @@
frame=trbl, frame=trbl,
framesep=4pt, framesep=4pt,
} }
\usepackage{dsfont}
--- ---
title: "Introduction générale" title: "Introduction générale"
date: "2022-09-20" date: "2024-09-17"
--- ---
# La hotline # La hotline
...@@ -8,41 +8,36 @@ date: "2022-09-20" ...@@ -8,41 +8,36 @@ date: "2022-09-20"
Nom Mél Bureau Nom Mél Bureau
-------------------- ------------------------------ -------------------- -------------------- ------------------------------ --------------------
Kevin Heirich kevin.heirich@hesge.ch A403 Kevin Heirich kevin.heirich@hesge.ch A403
Quentin Leblanc quentin.leblanc@hesge.ch A403
Damian Boquete damian.boquete@hesge.ch B403
Michaël El Kharroubi michael.el-kharroubi@hesge.ch A403 Michaël El Kharroubi michael.el-kharroubi@hesge.ch A403
Pierre Kunzli pierre.kunzli@hesge.ch
Paul Albuquerque paul.albuquerque@hesge.ch B410 Paul Albuquerque paul.albuquerque@hesge.ch B410
Orestis Malaspinas orestis.malaspinas@hesge.ch A401 Orestis Malaspinas orestis.malaspinas@hesge.ch A401
-------------------- ------------------------------ -------------------- -------------------- ------------------------------ --------------------
Utilisez le libre service (pas encore commencé): Utilisez le libre service (pas encore d'horaire):
* lundi: 12h-13h, mecredi: 12h-13h;
* jeudi: 12h-13h, vendredi: 17h-18h.
# Communication # Communication
Tout le contenu de ce qu'on raconte se trouve sur cyberlearn: Tout le contenu de ce qu'on raconte se trouve sur cyberlearn:
- Algorithmes et structures de données - Algorithmes et structures de données
- <https://cyberlearn.hes-so.ch/course/view.php?id=13941> - <https://cyberlearn.hes-so.ch/course/view.php?id=7276>
- Clé d'inscription: algo_2021_22 - Clé d'inscription: algo_2024_25
- Programmation Sequentielle en C - Programmation Sequentielle en C
- <https://cyberlearn.hes-so.ch/course/view.php?id=12399> - <https://cyberlearn.hes-so.ch/course/view.php?id=7282>
- Clé d'inscription: prog_seq_2021_22 - Clé d'inscription: prog_seq_2024_25
* Espace de discussion * Espace de discussion
[Matrix](https://matrix.to/#/!aKYVlcclmPGYXQFxAK:matrix.org?via=matrix.org), [Matrix](https://matrix.to/#/!aKYVlcclmPGYXQFxAK:matrix.org?via=matrix.org),
installez [element.io](https://element.io). installez [element.io](https://element.io).
![](figs/matrix_qr.png){width=20%}
# Organisation du cours (1/3) # Organisation du cours (1/3)
## But: Illustration des concepts vus au cours d'algorithmique ## But: Illustration des concepts vus au cours d'algorithmique
- Salle A502 pour la "théorie" (présentation langage et TPs). - Salle B119 pour la "théorie" (présentation langage et TPs).
- Salles A406-A432-A433 pour la "pratique". - Salles A404-A406-A432-A433 pour la "pratique".
## Le bâton ## Le bâton
...@@ -67,41 +62,46 @@ Tout le contenu de ce qu'on raconte se trouve sur cyberlearn: ...@@ -67,41 +62,46 @@ Tout le contenu de ce qu'on raconte se trouve sur cyberlearn:
# Organisation du cours (3/3) # Organisation du cours (3/3)
- Les cours "théoriques" seront streamés sur <https://bbb.hesge.ch/b/ore-xff-hkz-poh>. - Les cours "théoriques" seront disponible en replay sur <https://bbb.hesge.ch/rooms/wkm-a1q-7d1-rjb/join>.
- Vous y trouverez également les replay sponsorisés par HEPIA-VPN[^2]!
- Il y a un certain nombre de ressources se trouvant sur <https://malaspinas.academy>. - Il y a un certain nombre de ressources se trouvant sur <https://malaspinas.academy>.
- Mon bureau est toujours ouvert (tapez *assez fort* sur la porte). - Mon bureau est toujours ouvert (tapez *assez fort* sur la porte).
- N'hésitez pas à utiliser le salon *Element*. - N'hésitez pas à utiliser le salon *Element*...
[^2]: Likez, followez, et abonnez vous à la chaîne pour la faire vivre!
# Évaluations # Évaluations
## 1er semestre deux examens sur machine ## 1er semestre deux examens sur machine
- Seul·e devant votre ordinateur. - Seul·e devant votre ordinateur.
- Avec à disposition le manuel du C. - Avec à disposition une page rect-verso de notes manuscrites.
## 2e semestre ## 2e semestre deux examens sur machine
- on verra au deuxième semestre - Seul·e devant votre ordinateur.
- Avec à disposition une page rect-verso de notes manuscrites.
# Sondage: expérience de programmation # Sondage: expérience de programmation
## [Sondage: expérience de linux](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1291283) ## [Sondage: expérience de linux](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=501943)
## [Sondage: expérience de programmation](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1035242) ## [Sondage: expérience de programmation](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=501940)
**Installez un lecteur de QR code s'il-vous-plaît.** **Installez un lecteur de QR code s'il-vous-plaît.**
# Install Party
* Ubuntu 24 LTS
* `gcc`, `clang`, `make`, `docker` en mode rootless, `codium` (ou `neovim`)
* Quand tout est installé: TP du nombre secret sur <https://malaspinas.academy>
# Questions? # Questions?
- N'hésitez pas à poser des *questions*, nous sommes là pour ça! [^3] - N'hésitez pas à poser des *questions*, nous sommes là pour ça! [^3] [^4]
- Ne restez pas coincés pendant des jours sur un problème. - Ne restez pas coincés pendant des jours sur un problème.
- Utilisez le *libre-service*! - Utilisez le *libre-service*!
- N'hésitez pas à faire des *retours*: *négatifs* ou *positifs* (évaluations des cours, ou au cours de discussions). - N'hésitez pas à faire des *retours*: *négatifs* ou *positifs* (évaluations des cours, ou au cours de discussions).
- Il est très tentant de faire les TPs en groupe, mais il est **primordial** de programmer vous-mêmes (c'est comme apprendre une langue)! - Il est très tentant de faire les TPs en groupe, mais il est **primordial** de programmer vous-mêmes (c'est comme apprendre une langue)!
[^3]: Chaque étudiant·e·s a un quota de 1 question par semestre. [^3]: Surtout les assistants.
[^4]: Chaque étudiant·e·s a un quota de 1 question par semestre pour les professeurs.