Programmation C
Structuration du code - Correction des exercices
|
|

|
|

|
Exercice 1 (while)
#include <stdio.h>
#include <stdlib.h>
void main(void) {
srand(0);
int cpt = 1;
while (rand() != 0) {
cpt++;
}
printf("%12d\n", cpt);
}
|
04-Exercice1.c - 04-Exercice1.exe
|
|
|
Exercice 2 (while)
#include <stdio.h>
#include <stdlib.h>
void main(void) {
srand(9);
char c1 = 'a' + rand() % 26;
char c2;
while ((c2 = 'a' + rand() % 26) == c1);
printf("%c %c\n", c1, c2);
char c3;
while (((c3 = 'a' + rand() % 26) == c1) || (c3 == c2));
printf("%c %c %c\n", c1, c2, c3);
}
|
04-Exercice2.c - 04-Exercice2.exe
|
|
- Utilisation du égal d'affectation à une variable en tant qu'opérateur qui retourne la valeur affectée
|
Exercice 3 (do while)
#include <stdio.h>
const double PI = 3.141592653589793;
void main(void) {
long long dividende = 22;
long long diviseur = 7;
double fraction = (double) dividende / diviseur;
double delta = fabs(PI - fraction);
printf("%8lld %8lld\n", dividende, diviseur);
printf("%20.18lf %20.18lf\n", PI, fraction);
printf("%20.18lf\n\n", delta);
int v;
double dInf;
double dSup;
do {
diviseur++;
v = (int) (diviseur * PI);
double vInf = (double) v / diviseur;
double vSup = (double) (v + 1) / diviseur;
dInf = fabs(vInf - PI);
dSup = vSup - PI;
} while ((dInf >= delta) && (dSup >= delta) && (delta != 0));
dividende = dInf < dSup ? v : v + 1;
fraction = (double) dividende / diviseur;
delta = fabs(PI - fraction);
printf("%8lld %8lld\n", dividende, diviseur);
printf("%20.18lf %20.18lf\n", PI, fraction);
printf("%20.18lf\n", delta);
}
|
04-Exercice3.c - 04-Exercice3.exe
|
22 7
3.141592653589793116 3.142857142857142794
0.001264489267349678
179 57
3.141592653589793116 3.140350877192982448
0.001241776396810668 |
|
- Attention, utilisation de l'opérateur conditionnel en fin d'algorithme pour arbitrer entre v et v+1 pour le choix du dividende
|
Exercice 4 (for)
#include <stdio.h>
const double PI = 3.141592653589793;
void main(void) {
for (int n = 1; n <= 9; n++) {
double pi1 = 0.0;
for (int i = 1, signe = 1; i <= 2 * n + 1; i += 2, signe = -signe) {
pi1 += signe * 4.0 / i;
}
double pi2 = 3.0;
for (int i = 2, signe = 1; i <= 2 * n + 1; i += 2, signe = -signe) {
pi2 += signe * 4.0 / (i * (i + 1LL) * (i + 2LL));
}
printf("%5d : %20.16lf %20.16lf : %20.16lf %20.16lf : %12.1lf\n", n
, pi1
, pi1 - PI
, pi2
, pi2 - PI
, fabs(pi1 - PI) / fabs(pi2 - PI));
}
for (int n = 10; n <= 90; n += 10) {
double pi1 = 0.0;
for (int i = 1, signe = 1; i <= 2 * n + 1; i += 2, signe = -signe) {
pi1 += signe * 4.0 / i;
}
double pi2 = 3.0;
for (int i = 2, signe = 1; i <= 2 * n + 1; i += 2, signe = -signe) {
pi2 += signe * 4.0 / (i * (i + 1LL) * (i + 2LL));
}
printf("%5d : %20.16lf %20.16lf : %20.16lf %20.16lf : %12.1lf\n", n
, pi1
, pi1 - PI
, pi2
, pi2 - PI
, fabs(pi1 - PI) / fabs(pi2 - PI));
}
for (int n = 100; n <= 900; n += 100) {
double pi1 = 0.0;
for (int i = 1, signe = 1; i <= 2 * n + 1; i += 2, signe = -signe) {
pi1 += signe * 4.0 / i;
}
double pi2 = 3.0;
for (int i = 2, signe = 1; i <= 2 * n + 1; i += 2, signe = -signe) {
pi2 += signe * 4.0 / (i * (i + 1LL) * (i + 2LL));
}
printf("%5d : %20.16lf %20.16lf : %20.16lf %20.16lf : %12.1lf\n", n
, pi1
, pi1 - PI
, pi2
, pi2 - PI
, fabs(pi1 - PI) / fabs(pi2 - PI));
}
for (int n = 1000; n <= 10000; n += 1000) {
double pi1 = 0.0;
for (int i = 1, signe = 1; i <= 2 * n + 1; i += 2, signe = -signe) {
pi1 += signe * 4.0 / i;
}
double pi2 = 3.0;
for (int i = 2, signe = 1; i <= 2 * n + 1; i += 2, signe = -signe) {
pi2 += signe * 4.0 / (i * (i + 1LL) * (i + 2LL));
}
printf("%5d : %20.16lf %20.16lf : %20.16lf %20.16lf : %12.1lf\n", n
, pi1
, pi1 - PI
, pi2
, pi2 - PI
, fabs(pi1 - PI) / fabs(pi2 - PI));
}
}
|
04-Exercice4.c - 04-Exercice4.exe
|
|
- Quatre for principaux pour itérer sur n sur les quatre intervalles [1,9], [10,90], [100, 900] et [1000,10000]
- Deux for imbriqués dans chacun des quatre for principaux pour implanter les formules de calcul
- Pour chaque n, deux valeurs estimées de PI calculées (une par formule) et comparées par affichage de la différence avec la "vraie" valeur (erreur d'estimation) et affichage du rapport entre les deux
différences (détermination de la meilleure estimation)
- Programmation sans fonction -> beaucoup de code dupliqué et peu d'expressivité à l'arrivée -> pas génial
|
Exercice 5 (if)
#include <stdio.h>
#include <stdlib.h>
int main(void) {
srand(2224);
{
int v1 = rand() % 256;
printf("%3d %2X\n", v1, v1);
int chiffreUnites = v1 & 0b1111; // ou v1 & 0x0F ou v1 % 16
int chiffreDizaines = v1 >> 4;
printf("%2d %2d\n", chiffreDizaines, chiffreUnites);
if (chiffreDizaines < 10) {
printf("%d", chiffreDizaines);
}
else {
printf("%c", 'A' - 10 + chiffreDizaines);
}
if (chiffreUnites < 10) {
printf("%d", chiffreUnites);
}
else {
printf("%c", 'A' - 10 + chiffreUnites);
}
printf("\n\n");
}
{
int v2 = 10000 + rand() % 90000;
printf("%d\n", v2);
int chiffreUnites = v2 % 10;
int chiffreDizainesMilliers = v2 / 10000;
printf("%d %d\n", chiffreUnites, chiffreDizainesMilliers);
int palindrome = 0;
if (chiffreUnites == chiffreDizainesMilliers) {
int chiffreDizaines = (v2 / 10) % 10;
int chiffreMilliers = (v2 / 1000) % 10;
printf("%d %d\n", chiffreDizaines, chiffreMilliers);
if (chiffreDizaines == chiffreMilliers) {
palindrome = 1;
}
}
if(palindrome == 1) {
printf("%d est palindromique\n",v2);
}
else {
printf("%d n'est pas palindromique\n",v2);
}
}
return 0;
}
|
04-Exercice5.c - 04-Exercice5.exe
|
133 85
8 5
85
34303
3 3
0 4
34303 n'est pas palindromique |
|
|
Exercice 6 (switch)
#include <stdio.h>
#include <stdlib.h>
int main(void) {
srand(204);
char operation = 0x00;
switch (rand() % 5) {
case 0: {
operation = '+';
break;
}
case 1: {
operation = '-';
break;
}
case 2: {
operation = '*';
break;
}
case 3: {
operation = '/';
break;
}
case 4: {
operation = '%';
break;
}
}
int v1 = 10 + rand() % 990;
int v2 = 10 + rand() % 90;
int resultat = -1;
switch (operation) {
case '+': {
resultat = v1 + v2;
break;
}
case '-': {
resultat = v1 - v2;
break;
}
case '*': {
resultat = v1 * v2;
break;
}
case '/': {
resultat = v1 / v2;
break;
}
case '%': {
resultat = v1 % v2;
break;
}
}
if (operation != 0x00) {
printf("%d %c %d = %d", v1, operation, v2, resultat);
}
else {
printf("Probl�me !!!");
}
return 0;
}
|
04-Exercice6.c - 04-Exercice6.exe
|
|
|
Exercice 7 (fonctions)
#include <stdio.h>
#include <stdlib.h>
int myRand(void) {
return rand() * (RAND_MAX + 1) + rand();
}
int randDansIntervalle1(int bi, int bf) {
return bi + rand() % (bf - bi + 1);
}
int randDansIntervalle2(int bi, int bf) {
return bi + myRand() % (bf - bi + 1);
}
int randDansIntervalle(int bi, int bf, int (*fonctionRand)(void)) {
return bi + fonctionRand() % (bf - bi + 1);
}
double rand01(void) {
return ((double) myRand() / (RAND_MAX + 1)) / (RAND_MAX + 1);
}
void tester1(int n) {
int n5 = 0;
int n6 = 0;
int n7 = 0;
int n8 = 0;
int n9 = 0;
int n10 = 0;
for (int i = 0; i < n; i++) {
int v = randDansIntervalle1(5, 10);
switch (v) {
case 5: {
n5++;
break;
}
case 6: {
n6++;
break;
}
case 7: {
n7++;
break;
}
case 8: {
n8++;
break;
}
case 9: {
n9++;
break;
}
case 10: {
n10++;
break;
}
}
}
printf("%7d %7d %7d %7d %7d %7d : %7d\n", n5, n6, n7, n8, n9, n10,
n5 + n6 + n7 + n8 + n9 + n10);
printf("%7.3lf %7.3lf %7.3lf %7.3lf %7.3lf %7.3lf\n",
(double) n5 / n * 100.0,
(double) n6 / n * 100.0,
(double) n7 / n * 100.0,
(double) n8 / n * 100.0,
(double) n9 / n * 100.0,
(double) n10 / n * 100.0);
}
void tester2(int n) {
int n0 = 0;
int n1 = 0;
int n2 = 0;
for (int i = 0; i < n; i++) {
int v = randDansIntervalle1(0, 29999);
if ((v >= 0) && (v <= 9999)) {
n0++;
}
if ((v >= 10000) && (v <= 19999)) {
n1++;
}
if ((v >= 20000) && (v <= 29999)) {
n2++;
}
}
printf("%7d %7d %7d %23s : %7d\n", n0, n1, n2, "", n0 + n1 + n2);
printf("%7.3lf %7.3lf %7.3lf\n",
(double) n0 / n * 100.0,
(double) n1 / n * 100.0,
(double) n2 / n * 100.0);
}
void tester3(int n) {
int n0 = 0;
int n1 = 0;
int n2 = 0;
for (int i = 0; i < n; i++) {
int v = randDansIntervalle2(0, 29999);
if ((v >= 0) && (v <= 9999)) {
n0++;
}
if ((v >= 10000) && (v <= 19999)) {
n1++;
}
if ((v >= 20000) && (v <= 29999)) {
n2++;
}
}
printf("%7d %7d %7d %23s : %7d\n", n0, n1, n2, "", n0 + n1 + n2);
printf("%7.3lf %7.3lf %7.3lf\n",
(double) n0 / n * 100.0,
(double) n1 / n * 100.0,
(double) n2 / n * 100.0);
}
void tester4(int n) {
int n0 = 0;
int n1 = 0;
int n2 = 0;
int n3 = 0;
for (int i = 0; i < n; i++) {
double v = rand01();
if ((v >= 0) && (v < 0.25)) {
n0++;
}
if ((v >= 0.25) && (v < 0.5)) {
n1++;
}
if ((v >= 0.5) && (v < 0.75)) {
n2++;
}
if ((v >= 0.75) && (v < 1.0)) {
n3++;
}
}
printf("%7d %7d %7d %7d %15s : %7d\n", n0, n1, n2, n3, "", n0 + n1 + n2 + n3);
printf("%7.3lf %7.3lf %7.3lf %7.3lf\n",
(double) n0 / n * 100.0,
(double) n1 / n * 100.0,
(double) n2 / n * 100.0,
(double) n3 / n * 100.0);
}
int main(void) {
srand(7);
tester1(6000000);
printf("\n");
tester2(3000000);
printf("\n");
tester3(3000000);
printf("\n");
tester4(4000000);
return 0;
}
|
04-Exercice7.c - 04-Exercice7.exe
|
999746 1000760 1000581 1000044 999677 999192 : 6000000
16.662 16.679 16.676 16.667 16.661 16.653
1169614 914524 915862 : 3000000
38.987 30.484 30.529
999744 1001346 998910 : 3000000
33.325 33.378 33.297
998323 999903 1000850 1000924 : 4000000
24.958 24.998 25.021 25.023
|
|
- Fonction myRand : implantation du calcul proposé dans l'énoncé
- Fonctions randDansIntervalle1 et randDansIntervalle2 : implantation du tirage au sort dans un intervalle en utilisant la fonction rand standard pour randDansIntervalle1 et et la fonction myRand pour
randDansIntervalle2
- Fonction rand01 : implantation du calcul d'une valeur tirée au sort dans l'intervalle [0.0, 1.0[ en divisant un nombre entier tiré au sort dans l'intervalle [0,(RAND_MAX+1)2-1] par (RAND_MAX+1)2.
- Développement de quatre fonctions de test exécutées par la fonction main
Passage en paramètre à chacune de ces fonctions du nombre de nombres aléatoires qu'elle doit générer et analyser
Affichage par chacune des fonctions des effectifs trouvés, du total des effectifs trouvés (qui doit être égal au nombre de nombres aléatoires générés) et des pourcentages de nombres trouvés
- tester1 : test de randDansIntervalle1 (qui utilise la fonction rand standard) sur 6 millions de tirages
La répartition semble ne pas poser de problème avec des pourcentages voisins de 16.667%.
- tester2 : test de randDansIntervalle1 (qui utilise la fonction rand standard) sur 3 millions de tirages
La répartition pose un problème. On s'attend à trouver des valeurs plus proches de 1 million que celles trouvées. Les pourcentages sont très louches. Pourquoi ne sont-ils pas uniformes ?
- tester3 : test de randDansIntervalle2 (qui utilise la fonction myRand) sur 3 millions de tirages
La répartition semble ne pas poser de problème avec des pourcentages voisins de 33.333%.
- tester4 : test de rand01 (qui utilise la fonction myRand) sur 4 millions de tirages
La répartition semble ne pas poser de problème avec des pourcentages voisins de 25.0%.
|
Exercice 8 (fonctions)
#include <stdio.h>
int resoudreEquationSecondDegre(double a, double b, double c, double* x1, double* x2) {
double delta = b * b - 4.0 * a * c;
if (delta < 0.0) {
return 0;
}
else {
if (delta == 0.0) {
*x1 = -b / (2.0 * a);
return 1;
}
else {
*x1 = (-b - sqrt(delta)) / (2.0 * a);
*x2 = (-b + sqrt(delta)) / (2.0 * a);
return 2;
}
}
}
void tester(double a, double b, double c) {
double x1;
double x2;
int nb = resoudreEquationSecondDegre(a, b, c, &x1, &x2);
switch (nb) {
case 0: {
printf("L'equation %.3lfx2%+.3lfx%+.3lf n'a pas de racine reelle\n", a, b, c);
break;
}
case 1: {
printf("L'equation %.3lfx2%+.3lfx%+.3lf a une racine reelle : %lf\n", a, b, c, x1);
break;
}
case 2: {
printf("L'equation %.3lfx2%+.3lfx%+.3lf a deux racines reelles : %lf et %lf\n", a, b, c, x1, x2);
break;
}
}
}
int main(void) {
tester(2.0, -3.1, 2.1);
tester(2.0, 4.0, 2.0);
tester(-2.0, 5.0, -2.0);
return 0;
}
|
04-Exercice8.c - 04-Exercice8.exe
|
L'equation 2.000x2-3.100x+2.100 n'a pas de racine reelle
L'equation 2.000x2+4.000x+2.000 a une racine reelle : -1.000000
L'equation -2.000x2+5.000x-2.000 a deux racines reelles : 2.000000 et 0.500000 |
|
- Développement d'une fonction à retour de type int : le nombre de racines trouvées qui pourra être 0, 1 ou 2
- Développement d'une fonction possédant 5 paramètres
- le coefficient a de type double
- le coefficient b de type double
- le coefficient c de type double
- un premier pointeur sur double permettant de donner l'adresse de la variable à remplir pour donner la valeur de la racine s'il n'y en a qu'une, la valeur de la première racine s'il
y en a deux
- un second pointeur sur double permettant de donner l'adresse de la variable à remplir pour donner la valeur de la seconde racine s'il y en a deux
- Lors de l'appel à la fonction resoudreEquationSecondDegre
- Passage des adresses des deux variables de type double destinées à recevoir les valeurs des racines s'il y en a
- Récupération en retour de fonction du nombre de racines
- Nombre de racines stocké dans une variable utilisée ensuite dans un switch pour faire les affichages
- Placement du test complet dans une fonction ad hoc utilisée trois fois dans le programme principal avec les jeux de paramètres (a,b,c) de l'énoncé
|