From cd45b86ea1e92be54bc784f93a9a5afcf6c268d5 Mon Sep 17 00:00:00 2001 From: leclere Date: Wed, 14 Oct 2026 11:42:40 +0200 Subject: [PATCH] ajout J6 + calcul M python et C --- COMPTE_RENDU.md | 122 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 1 deletion(-) diff --git a/COMPTE_RENDU.md b/COMPTE_RENDU.md index 4d203ed..2c8903f 100644 --- a/COMPTE_RENDU.md +++ b/COMPTE_RENDU.md @@ -2,7 +2,7 @@ ## Partie 1 – Graphes de flot de contrôle -Pour chaque fonction, on construit le graphe de flot de contrôle (un nœud = un bloc sans branchement, une décision = un nœud à deux sorties, un seul nœud de sortie), puis on applique : +Pour chaque fonction demandée dans l'énnoncé, on construit le graphe de flot de contrôle, puis on applique : **M = E − N + 2P** (E = arêtes, N = nœuds, P = 1 pour une fonction) @@ -27,6 +27,21 @@ On vérifie ensuite le résultat avec la règle pratique **M = décisions + 1**. - **M = 9 − 8 + 2 × 1 = 3** - Vérification : 1 `for` + 1 ternaire `?:` + 1 = 3 +### C4 – `nom_jour` (C) + +![Graphe C4](Graphe/C4.jpg) + +| Nœud | Contenu | +|---|---| +| 1 | `switch (jour)` | +| 2 à 8 | `case 1` à `case 7` : `return "lundi"` … `return "dimanche"` | +| 9 | `default` : `return "inconnu"` | +| 10 | sortie | + +- N = 10, E = 16 (8 arêtes du `switch` vers chaque branche + 8 arêtes des branches vers la sortie), P = 1 +- **M = 16 − 10 + 2 × 1 = 8** +- Vérification : 7 `case` + 1 = 8 (le `default` ne compte pas : c'est le « sinon » du `switch`) + ### J2 – `estDisponible` (Java) ![Graphe J2](Graphe/J2.png) @@ -44,6 +59,38 @@ La méthode ne contient aucun `if`, mais les `&&` sont évalués paresseusement - **M = 5 − 4 + 2 × 1 = 3** - Vérification : 2 opérateurs `&&` + 1 = 3 +### J6 – `importer` (Java) + +![Graphe J6](Graphe/J6.png) + +Les nœuds de décision sont en jaune, et la condition de la boucle `for` est en bleu. + +| Nœud | Contenu | +|---|---| +| 1 | `importes = 0` | +| 2 | décision `for` : reste-t-il une ligne ? | +| 3 | décision `ligne.isBlank()` | +| 4 | décision `ligne.startsWith("#")` (le `\|\|`) | +| 5 | `continue` | +| 6 | `champs = ligne.split(";")` | +| 7 | décision `champs.length != 4` | +| 8 | `System.err.println(...)` + `continue` | +| 9 | `try` : `annee = Integer.parseInt(...)` | +| 10 | décision `annee > 0` | +| 11 | décision `annee <= 2026` (le `&&`) | +| 12 | `livres.add(...)` + `importes++` | +| 13 | décision `catch` : `NumberFormatException` levée ? | +| 14 | `System.err.println("Année invalide ...")` | +| 15 | sortie (`return importes`) | + +Arêtes : 1→2, 2→3, 2→15, 3→4, 3→5, 4→5, 4→6, 5→2, 6→7, 7→8, 7→9, 8→2, 9→10, 10→11, 10→13, 11→12, 11→13, 12→13, 13→2, 13→14, 14→2. + +- N = 15, E = 21, P = 1 +- **M = 21 − 15 + 2 × 1 = 8** +- Vérification : 1 `for` + 1 `if` + 1 `||` + 1 `if` + 1 `if` + 1 `&&` + 1 `catch` = 7 décisions, + 1 = 8 + +> Cas particuliers : le `||` et le `&&` comptent chacun comme une décision (évaluation paresseuse), et le `catch` aussi, puisqu'il crée un second chemin de sortie du `try`. Les `continue` ne comptent pas : ils renvoient simplement vers la condition de la boucle. + ### P2 – `signe` (Python) ![Graphe P2](Graphe/P2.jpg) @@ -86,6 +133,79 @@ La compréhension de liste cache une boucle et un filtre : elle se lit comme un | Fonction | N | E | M | Classe | |---|---|---|---|---| | C2 `moyenne` | 8 | 9 | 3 | Simple | +| C4 `nom_jour` | 10 | 16 | 8 | Simple | | J2 `estDisponible` | 4 | 5 | 3 | Simple | +| J6 `importer` | 15 | 21 | 8 | Simple | | P2 `signe` | 6 | 7 | 3 | Simple | | P3 `notes_valides` | 5 | 6 | 3 | Simple | + +## Partie 2 – Comptage des décisions (M = décisions + 1) + +### C (`exercices.c`) + +| Fonction | Décisions | M | Classe | +|---|---|---|---| +| C1 `carre` | aucune | **1** | Simple | +| C2 `moyenne` | 1 `for`, 1 ternaire `?:` | **3** | Simple | +| C3 `est_bissextile` | 1 `&&`, 1 `\|\|` | **3** | Simple | +| C4 `nom_jour` | 7 `case` | **8** | Simple | +| C5 `compter_mots` | 1 `while`, 4 `\|\|`, 1 `if`, 1 `else if` | **8** | Simple | +| C6 `date_valide` | 4 `if`/`else if`, 6 `\|\|` | **11** | Modéré | + +Détail de C3 : il n'y a aucun `if`, mais `&&` et `||` sont évalués paresseusement : chacun crée un branchement (si `annee % 4 == 0` est faux, `annee % 100 != 0` n'est pas évalué). 2 décisions + 1 = **3**, ce qui correspond au graphe vu en cours (N = 4, E = 5). + +Détail de C4 : le `default` ne compte pas (c'est le « sinon » du `switch`) et les `return` non plus. 7 + 1 = **8**, comme avec le graphe (16 − 10 + 2). + +Détail de C5 : + +| Ligne | Décision | +1 | +|---|---|---| +| `while (texte[i] != '\0')` | `while` | 1 | +| `c == ' ' \|\| c == '\t' \|\| c == '\n' \|\| c == ',' \|\| c == '.'` | 4 `\|\|` | 5 | +| `if (separateur)` | `if` | 6 | +| `else if (!dans_mot)` | `else if` | 7 | + +**M = 7 + 1 = 8.** Ici aussi les `||` comptent sans `if` : ils sont dans une affectation (`int separateur = ...`), mais restent des branchements. + +Détail de C6 : + +| Ligne | Décision | +1 | +|---|---|---| +| `if (annee < 1 \|\| mois < 1 \|\| mois > 12 \|\| jour < 1)` | `if` + 3 `\|\|` | 4 | +| `if (mois == 2)` | `if` | 5 | +| `if (est_bissextile(annee))` | `if` | 6 | +| `else if (mois == 4 \|\| mois == 6 \|\| mois == 9 \|\| mois == 11)` | `else if` + 3 `\|\|` | 10 | + +**M = 10 + 1 = 11**, soit juste au-dessus du seuil de 10 (McCabe, PMD) : c'est la fonction C la plus complexe. L'appel à `est_bissextile` ne compte pas : ses décisions appartiennent à `est_bissextile` (M calculé par fonction). + +### Python (`exercices.py`) + +| Fonction | Décisions | M | Classe | +|---|---|---|---| +| P1 `celsius_vers_fahrenheit` | aucune | **1** | Simple | +| P2 `signe` | 1 `if`, 1 `elif` | **3** | Simple | +| P3 `notes_valides` | 1 `for`, 1 `if` (dans la compréhension) | **3** | Simple | +| P4 `mention` | 1 `for`, 1 `if` | **3** | Simple | +| P5 `analyser_mot_de_passe` | 2 `for`, 8 `if`, 2 `elif`, 2 `and`, 1 ternaire | **16** | Modéré | + +Détail de P5 : + +| Ligne | Décision | +1 | +|---|---|---| +| `if len(mdp) < 12` | `if` | 1 | +| `for c in mdp` | `for` | 2 | +| `if c.isupper()` | `if` | 3 | +| `elif c.islower()` | `elif` | 4 | +| `elif c.isdigit()` | `elif` | 5 | +| `if not (majuscule and minuscule)` | `if` + `and` | 7 | +| `if not chiffre` | `if` | 8 | +| `if not special` | `if` | 9 | +| `if login and login.lower() in mdp.lower()` | `if` + `and` | 11 | +| `for i in range(len(mdp) - 2)` | `for` | 12 | +| `if mdp[i] == mdp[i + 1] == mdp[i + 2]` | `if` | 13 | +| `if not problemes` | `if` | 14 | +| `"moyen" if len(problemes) <= 2 else "faible"` | ternaire | 15 | + +**M = 15 + 1 = 16.** Le `else` final de la cascade `if/elif/else` et le `break` ne comptent pas. Comme pour P3, la comparaison chaînée `mdp[i] == mdp[i + 1] == mdp[i + 2]` est comptée comme une seule condition. + +P4 a le même M que la version refactorisée de `mention` vue en cours : le dictionnaire remplace la cascade de `if/elif` (qui aurait donné M = 5).