Exercice 1 : Analyser six programmes, affichages et calculs
Que produit chacun des six programmes suivants ? Pour ceux qui lisent des nombres, donner le comportement selon les entrées. Voici les programmes du support, avec leur logique et leurs formats conservés :
Programme a du sujet
#include <stdio.h>
int main() {
printf("*****\n");
printf("****\n");
printf("***\n");
printf("**\n");
printf("*\n");
return 0;
}Programme b du sujet
#include <stdio.h>
int main() {
printf("*****\n");
printf("* *\n");
printf("* *\n");
printf("* *\n");
printf("*****\n");
return 0;
}Programme c du sujet
#include <stdio.h>
int main() {
float a, b, max;
printf("Enter two numbers");
scanf("%f", &a);
scanf("%f", &b);
if (a < b) { max = b; }
else { max = a; }
printf("maximum =%d", max);
return 0;
}Programme d du sujet
#include <stdio.h>
int main() {
float a, b, c, sum;
printf("Enter thre numbers");
scanf("%f", &a);
scanf("%f", &b);
scanf("%f", &c);
sum = a + b + c;
printf("sum=%f", sum);
return 0;
}Programme e du sujet
#include <stdio.h>
#define TEN 10
int main() {
float moyenne;
printf("Enter the average");
scanf("%f", &moyenne);
if (moyenne < TEN) { printf("Echec"); }
else { printf("Succès"); }
return 0;
}Programme f du sujet
#include <stdio.h>
#define PI 3.14
int main() {
float r, s;
printf("Enter the radius");
scanf("%f", &r);
s = r * r * PI;
printf("result=%f\n", s);
return 0;
}Voir le corrigé détailléMasquer le corrigé
Rappel des notions utiles
Une chaîne entre guillemets est affichée littéralement, sauf les séquences comme \n. Une entrée au clavier n’est pas connue avant l’exécution : les programmes c à f n’ont donc pas une sortie numérique unique. Un if choisit un seul de ses deux blocs.
À revoir dans les cours : Structure d’un programme C · Entrées et sorties : printf et scanf · Types de données · Structures de contrôle : if et else · Constantes et littéraux.
Erreur importante du programme c original : printf("maximum =%d", max) attend un int alors que l’argument est un double après promotion du float. Le comportement est indéfini : on ne peut pas prédire une valeur correcte, ni conclure à une simple troncature. La correction utilise %f. Les autres programmes sont analysés pour des saisies valides ; les versions complètes ci-dessous ajoutent des contrôles de lecture et des retours à la ligne.
Pour a et b, l’affichage est entièrement déterminé. Pour d, la sortie originale commence par Enter thre numbers puis sum=... sans nouvelle ligne imposée entre les deux. Pour e, elle commence par Enter the average puis Echec ou Succès. Pour f, elle commence par Enter the radius puis result=.... Les versions corrigées séparent proprement les invites et les résultats.
Ce programme ne lit aucune valeur et ne calcule aucun choix : la version simple et la version générale sont identiques. Les deux affichages restent exactement ceux expliqués ci-dessous.
Version plus générale : 1a, Triangle d’étoiles
1a : Triangle d’étoiles : programme complet
#include <stdio.h>
int main(void) {
printf("*****\n");
printf("****\n");
printf("***\n");
printf("**\n");
printf("*\n");
return 0;
}| Instruction ou étape | Explication et état du programme |
|---|---|
| #include et main | stdio.h déclare printf ; main est exécutée au lancement. Ici aucune saisie n’est nécessaire. |
| printf("*****\n"); | Écrit cinq étoiles puis passe à la ligne. Le est un caractère de contrôle ; les deux signes barre oblique et n ne s’impriment pas. |
| Les quatre printf suivants | Impriment successivement 4, 3, 2 et 1 étoile. Après chaque appel, le curseur commence une nouvelle ligne. |
| return 0 | Le dessin est terminé ; le programme se termine normalement. |
| Saisie | Résultat après l’invite | Pourquoi ce résultat ? |
|---|---|---|
| (aucune) | ***** **** *** ** * | L’affichage a cinq lignes de longueurs décroissantes ; aucune variable ne change. |
Sorties écran : 1a, Triangle d’étoiles
Exécution 1. L’affichage a cinq lignes de longueurs décroissantes ; aucune variable ne change.
*****
****
***
**
*Ce programme ne lit aucune valeur et ne calcule aucun choix : la version simple et la version générale sont identiques. Les deux affichages restent exactement ceux expliqués ci-dessous.
Version plus générale : 1b, Cadre tel qu’écrit
1b : Cadre tel qu’écrit : programme complet
#include <stdio.h>
int main(void) {
printf("*****\n");
printf("* *\n");
printf("* *\n");
printf("* *\n");
printf("*****\n");
return 0;
}| Instruction ou étape | Explication et état du programme |
|---|---|
| printf("*****\n") | La première et la dernière ligne contiennent cinq étoiles. |
| printf("* *\n") | Chaque ligne intérieure contient une étoile, six espaces, puis une étoile : elle mesure huit colonnes. |
| Les trois appels identiques | La même ligne intérieure est répétée trois fois, sans boucle. Les espaces d’une chaîne sont conservés. |
| Différence entre intention et code | Le sujet semble vouloir un cadre, mais les largeurs 5 et 8 ne coïncident pas. On décrit le code réellement écrit. |
| Saisie | Résultat après l’invite | Pourquoi ce résultat ? |
|---|---|---|
| (aucune) | ***** * * * * * * ***** | Les deux bordures ne couvrent pas la largeur intérieure. Pour un carré de largeur 5, il faudrait trois espaces entre les étoiles. |
Sorties écran : 1b, Cadre tel qu’écrit
Exécution 1. Les deux bordures ne couvrent pas la largeur intérieure. Pour un carré de largeur 5, il faudrait trois espaces entre les étoiles.
*****
* *
* *
* *
*****Version simple (naïve) : 1c, Maximum, version corrigée
On suppose les saisies numériques correctes, représentables dans leurs types et dans le domaine de la formule. Cette version ne vérifie pas le retour de scanf ni les bornes de saisie. Le coeur du calcul reste le meme.
#include <stdio.h>
#include <math.h>
int main(void) {
float a, b, max;
puts("Entrer a b :");
scanf("%f %f", &a, &b);
if (a < b) {
max = b;
} else {
max = a;
}
printf("maximum =%f\n", max);
return 0;
}Lecture du code simple : les déclarations donnent les variables nécessaires ; scanf remplit ces variables sans vérifier son résultat ; les instructions suivantes effectuent le calcul ou choisissent la branche. Les tableaux de la version générale, plus bas, détaillent le même coeur de calcul et les évolutions des valeurs. Les cas exclus par les hypothèses ne doivent pas etre testes avec cette version.
Sorties écran : 1c, Maximum, version corrigée - version simple
Exécution 1. Le deuxième nombre est le plus grand.
Entrer a b :
2.5 7.25
maximum =7.250000Exécution 2. Le bloc else affecte a à max.
Entrer a b :
8 3
maximum =8.000000Exécution 3. L’égalité suit else sans changer la réponse.
Entrer a b :
4 4
maximum =4.000000Version plus générale : 1c, Maximum, version corrigée
1c : Maximum, version corrigée : programme complet
#include <stdio.h>
#include <math.h>
int main(void) {
float a, b, max;
puts("Entrer a b :");
if (scanf("%f %f", &a, &b) != 2) {
puts("Saisie invalide.");
return 1;
}
if (!isfinite(a) || fabs(a) > 1000000.0 || !isfinite(b) || fabs(b) > 1000000.0) {
puts("Valeur hors domaine.");
return 1;
}
if (a < b) {
max = b;
} else {
max = a;
}
printf("maximum =%f\n", max);
return 0;
}| Instruction ou étape | Explication et état du programme |
|---|---|
| float a, b, max | a et b reçoivent les deux réels. max n’est affecté qu’après la comparaison. |
| scanf et contrôle | Deux conversions %f sont attendues. Si une lecture échoue, le calcul est abandonné avant d’utiliser une valeur non initialisée. |
| if (a < b) | Avec a = 2.5 et b = 7.25, le test est vrai : max devient b. Le bloc else est ignoré. |
| else | Avec a = 8 et b = 3, le test est faux : max devient a. Si a et b sont égaux, prendre a donne aussi le maximum. |
| printf("maximum =%f\n", max) | Le format attend un double ; max, de type float, est automatiquement promu en double à cet appel. Les six décimales sont le format par défaut. |
| Saisie | Résultat après l’invite | Pourquoi ce résultat ? |
|---|---|---|
| 2.5 7.25 | maximum =7.250000 | Le deuxième nombre est le plus grand. |
| 8 3 | maximum =8.000000 | Le bloc else affecte a à max. |
| 4 4 | maximum =4.000000 | L’égalité suit else sans changer la réponse. |
| abc | Saisie invalide. | Aucune conversion numérique n’a réussi. |
Sorties écran : 1c, Maximum, version corrigée
Exécution 1. Le deuxième nombre est le plus grand.
Entrer a b :
2.5 7.25
maximum =7.250000Exécution 2. Le bloc else affecte a à max.
Entrer a b :
8 3
maximum =8.000000Exécution 3. L’égalité suit else sans changer la réponse.
Entrer a b :
4 4
maximum =4.000000Exécution 4. Aucune conversion numérique n’a réussi.
Entrer a b :
abc
Saisie invalide.Version simple (naïve) : 1d, Somme de trois réels
On suppose les saisies numériques correctes, représentables dans leurs types et dans le domaine de la formule. Cette version ne vérifie pas le retour de scanf ni les bornes de saisie. Le coeur du calcul reste le meme.
#include <stdio.h>
#include <math.h>
int main(void) {
float a, b, c, sum;
puts("Entrer a b c :");
scanf("%f %f %f", &a, &b, &c);
sum = a + b + c;
printf("sum=%f\n", sum);
return 0;
}Lecture du code simple : les déclarations donnent les variables nécessaires ; scanf remplit ces variables sans vérifier son résultat ; les instructions suivantes effectuent le calcul ou choisissent la branche. Les tableaux de la version générale, plus bas, détaillent le même coeur de calcul et les évolutions des valeurs. Les cas exclus par les hypothèses ne doivent pas etre testes avec cette version.
Sorties écran : 1d, Somme de trois réels - version simple
Exécution 1. 1.5 + 2.25 + 3 = 6.75.
Entrer a b c :
1.5 2.25 3
sum=6.750000Exécution 2. Les termes se compensent.
Entrer a b c :
-2 1 1
sum=0.000000Version plus générale : 1d, Somme de trois réels
1d : Somme de trois réels : programme complet
#include <stdio.h>
#include <math.h>
int main(void) {
float a, b, c, sum;
puts("Entrer a b c :");
if (scanf("%f %f %f", &a, &b, &c) != 3) {
puts("Saisie invalide.");
return 1;
}
if (!isfinite(a) || fabs(a) > 1000000.0 || !isfinite(b) || fabs(b) > 1000000.0 || !isfinite(c) || fabs(c) > 1000000.0) {
puts("Valeur hors domaine.");
return 1;
}
sum = a + b + c;
printf("sum=%f\n", sum);
return 0;
}| Instruction ou étape | Explication et état du programme |
|---|---|
| Les quatre variables float | Les trois entrées et la somme sont des flottants, donc certains décimaux ne sont représentés qu’approximativement. |
| sum = a + b + c | Avec 1.5, 2.25 et 3.0, la somme vaut 6.75 ; l’affectation écrit ce résultat dans sum. |
| printf("sum=%f\n", sum) | Affiche six décimales. Dans le code original il n’y a pas de retour à la ligne après le résultat ; la version proposée en ajoute un. |
| Saisie | Résultat après l’invite | Pourquoi ce résultat ? |
|---|---|---|
| 1.5 2.25 3 | sum=6.750000 | 1.5 + 2.25 + 3 = 6.75. |
| -2 1 1 | sum=0.000000 | Les termes se compensent. |
Sorties écran : 1d, Somme de trois réels
Exécution 1. 1.5 + 2.25 + 3 = 6.75.
Entrer a b c :
1.5 2.25 3
sum=6.750000Exécution 2. Les termes se compensent.
Entrer a b c :
-2 1 1
sum=0.000000Version simple (naïve) : 1e, Réussite et seuil
On suppose les saisies numériques correctes, représentables dans leurs types et dans le domaine de la formule. Cette version ne vérifie pas le retour de scanf ni les bornes de saisie. Le coeur du calcul reste le meme.
#include <stdio.h>
#include <math.h>
#define TEN 10
int main(void) {
float moyenne;
puts("Entrer moyenne :");
scanf("%f", &moyenne);
if (moyenne < TEN) {
puts("Echec");
} else {
puts("Succes");
}
return 0;
}Lecture du code simple : les déclarations donnent les variables nécessaires ; scanf remplit ces variables sans vérifier son résultat ; les instructions suivantes effectuent le calcul ou choisissent la branche. Les tableaux de la version générale, plus bas, détaillent le même coeur de calcul et les évolutions des valeurs. Les cas exclus par les hypothèses ne doivent pas etre testes avec cette version.
Sorties écran : 1e, Réussite et seuil - version simple
Exécution 1. 9.5 < 10 est vrai.
Entrer moyenne :
9.5
EchecExécution 2. 10 < 10 est faux : le seuil est inclus dans le succès.
Entrer moyenne :
10
SuccesExécution 3. Le bloc else est exécuté.
Entrer moyenne :
15
SuccesVersion plus générale : 1e, Réussite et seuil
1e : Réussite et seuil : programme complet
#include <stdio.h>
#include <math.h>
#define TEN 10
int main(void) {
float moyenne;
puts("Entrer moyenne :");
if (scanf("%f", &moyenne) != 1) {
puts("Saisie invalide.");
return 1;
}
if (!isfinite(moyenne) || fabs(moyenne) > 1000000.0) {
puts("Valeur hors domaine.");
return 1;
}
if (moyenne < TEN) {
puts("Echec");
} else {
puts("Succes");
}
return 0;
}| Instruction ou étape | Explication et état du programme |
|---|---|
| #define TEN 10 | Le préprocesseur remplace TEN par 10. Une macro ne réserve pas une variable et ne se termine pas par un point-virgule. |
| moyenne < TEN | Une moyenne strictement inférieure à 10 suit le premier bloc. Le sujet n’impose ici aucun intervalle de notes supplémentaire. |
| else | Contient tous les autres réels du domaine de l’exemple : 10 est donc un succès. À la différence de <, <= aurait classé 10 en échec. |
| puts | Affiche sa chaîne et ajoute un saut de ligne. Le sujet affiche Succès ; la solution emploie Succes pour la portabilité de l’encodage. |
| Saisie | Résultat après l’invite | Pourquoi ce résultat ? |
|---|---|---|
| 9.5 | Echec | 9.5 < 10 est vrai. |
| 10 | Succes | 10 < 10 est faux : le seuil est inclus dans le succès. |
| 15 | Succes | Le bloc else est exécuté. |
Sorties écran : 1e, Réussite et seuil
Exécution 1. 9.5 < 10 est vrai.
Entrer moyenne :
9.5
EchecExécution 2. 10 < 10 est faux : le seuil est inclus dans le succès.
Entrer moyenne :
10
SuccesExécution 3. Le bloc else est exécuté.
Entrer moyenne :
15
SuccesVersion simple (naïve) : 1f, Aire d’un disque
On suppose les saisies numériques correctes, représentables dans leurs types et dans le domaine de la formule. Cette version ne vérifie pas le retour de scanf ni les bornes de saisie. Le coeur du calcul reste le meme. Le rayon est supposé positif ou nul.
#include <stdio.h>
#include <math.h>
#define PI 3.14
int main(void) {
float r, s;
puts("Entrer r :");
scanf("%f", &r);
s = r * r * PI;
printf("result=%f\n", s);
return 0;
}Lecture du code simple : les déclarations donnent les variables nécessaires ; scanf remplit ces variables sans vérifier son résultat ; les instructions suivantes effectuent le calcul ou choisissent la branche. Les tableaux de la version générale, plus bas, détaillent le même coeur de calcul et les évolutions des valeurs. Les cas exclus par les hypothèses ne doivent pas etre testes avec cette version.
Sorties écran : 1f, Aire d’un disque - version simple
Exécution 1. Aire = 3.14 × 2 × 2, arrondie à six décimales.
Entrer r :
2
result=12.560000Exécution 2. Un rayon nul donne une aire nulle.
Entrer r :
0
result=0.000000Version plus générale : 1f, Aire d’un disque
1f : Aire d’un disque : programme complet
#include <stdio.h>
#include <math.h>
#define PI 3.14
int main(void) {
float r, s;
puts("Entrer r :");
if (scanf("%f", &r) != 1) {
puts("Saisie invalide.");
return 1;
}
if (!isfinite(r) || fabs(r) > 1000000.0) {
puts("Valeur hors domaine.");
return 1;
}
if (r < 0.0f) {
puts("Rayon invalide.");
return 1;
}
s = r * r * PI;
printf("result=%f\n", s);
return 0;
}| Instruction ou étape | Explication et état du programme |
|---|---|
| PI = 3.14 | On conserve l’approximation imposée par le sujet. La constante 3.14 est un double ; le résultat de l’expression est ensuite converti en float lors de l’affectation à s. |
| r < 0 | Un rayon géométrique ne peut pas être négatif. Le code original ne le contrôlait pas ; la solution refuse cette saisie. |
| s = r * r * PI | Pour r = 2 : r*r = 4 ; 4*3.14 ≈ 12.56. La formule calcule une aire, pas le volume d’une sphère. |
| Affichage %f | Un arrondi binaire peut être visible au sixième chiffre. Sur l’environnement de test, r = 2 affiche 12.560000. |
| Saisie | Résultat après l’invite | Pourquoi ce résultat ? |
|---|---|---|
| 2 | result=12.560000 | Aire = 3.14 × 2 × 2, arrondie à six décimales. |
| 0 | result=0.000000 | Un rayon nul donne une aire nulle. |
| -1 | Rayon invalide. | La garde arrête le programme. |
Sorties écran : 1f, Aire d’un disque
Exécution 1. Aire = 3.14 × 2 × 2, arrondie à six décimales.
Entrer r :
2
result=12.560000Exécution 2. Un rayon nul donne une aire nulle.
Entrer r :
0
result=0.000000Exécution 3. La garde arrête le programme.
Entrer r :
-1
Rayon invalide.