Exercice langage C: Programmes calcule date et jours

Exercice 1

Si (jma) n'est pas le dernier jour d'un mois alors son lendemain est (j+1, ma), sinon c'est (1, m+1, a) sauf si m = 12, auquel cas le lendemain est (1, 1, a+1). Nous devons donc écrire la condition qui caractérise que (j,ma) est le dernier jour d'un mois, ce qui équivaut, puisque la date est garantie correcte, à :

  • j = 31, ou bien
  • j = 30 et le mois est avril, juin, septembre ou novembre, ou bien
  • j = 29 et le mois est février, ou bien
  • j = 28, le mois est février et l'année n'est pas bissextile.

D'autre part, une année est bissextile si elle est divisible par 4 mais pas par 100. Cependant, les années multiples de 400 sont bissextiles. D'où le programme suivant, dans lequel on reconnaît sans peine la traduction des quatre cas ci-dessus.

#include
#include
int j, m, a, i;
main() {
printf("j m a ?\n");
scanf("%d%d%d", &j, &m, &a);
if (j == 31
|| (j == 30 && (m == 4 || m == 6 || m == 9 || m == 11))
|| (j == 29 && m == 2)
|| (j == 28 && m == 2 && ! (a % 4 == 0 && a % 100 != 0 || a % 400 == 0))) {
j = 1;
if (m == 12) {
m = 1;
a = a + 1;
}
else
m = m + 1;
}
else
j = j + 1;
printf("%d %d %d\n", j, m, a);
}

Exercice 2

Tout le travail à faire ici c'est programmer la formule donnée (nous l'acceptons sans explication!) sans y faire le moindre regroupement ou simplification car les barres de fraction indiquent des quotients entiers, donc impliquent des troncations qui sont nécessaires à la formule (par exemple, à cause de ces troncations, -2ns+ns/4 n'est pas toujours égal à -7ns/4).

Voici le programme, pour une fois il n'y a pas tellement de possibilités :

#include
#include
int j, m, a, as, ns, f;
main() {
printf("j m a ? ");
scanf("%d%d%d", &j, &m, &a);
printf("le %d/%02d/%d est un ", j, m, a);
if (m >= 3)
m = m - 2;
else {
m = m + 10;
a = a - 1;
}
ns = a / 100;
as = a % 100;
f = (j + as + as / 4 - 2 * ns + ns / 4 + (26 * m - 2) / 10) % 7;
if (f f = f + 7;
switch (f) {
case 0:
printf("dimanche\n");
break;
case 1:
printf("lundi\n");
break;
case 2:
printf("mardi\n");
break;
case 3:
printf("mercredi\n");
break;
case 4:
printf("jeudi\n");
break;
case 5:
printf("vendredi\n");
break;
default:
printf("samedi\n");
}
}

Après avoir décalé le mois et l'année comme indiqué (puisque ma et m1a1 ne coexistent pas, il n'y a pas besoin de deux paires de variables distinctes), on sépare le numéro de l'année en deux morceaux : a = 2003 donnens = 20 et as = 3 puis on calcule f.

Dans de nombreux cas f est négatif. Par exemple, pour le 1er mars 2002, f = -30. Cela pose un problème car là où un arithméticien dirait que -30 % 7 vaut 5 (en effet, -30 = -5 x 7 + 5) la bibliothèque C dira que -30 % 7 vaut -2 (car -30 = -4 x 7 - 2). Il se trouve que 5 et -2 sont deux réponses justes mais -2 nous gêne pour la suite du programme, d'où l'ajustement opéré [la bibliothèque garantit que xn est compris, quel que soit x, entre - (n - 1) et (n - 1)].

Enfin, il n'y a plus qu'à traduire le résultat obtenu, un nombre compris entre 0 et 6, et un texte "lundi", "mardi", etc. La solution proposée est la plus simple. Une solution au mieux équivalente, au pire un poil moins efficace, consiste à remplacer switch par une cascade de if :

...
if (f == 0)
printf("dimanche\n");
else if (f == 1)
printf("lundi\n");
else if (f == 2)
printf("mardi\n");
else if (f == 3)
printf("mercredi\n");
else if (f == 4)
printf("jeudi\n");
else if (f == 5)
printf("vendredi\n");
else
printf("samedi\n");
}

Si vous connaissez les tableaux de chaînes de caractères (c'est assez pointu, on y reviendra plus tard) voici une solution plus élégante :

#include
#include
int j, m, a, ns, f;
char *jour[] = { "dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi" };
main() {
printf("j m a ? ");
scanf("%d%d%d", &j, &m, &a);
printf("le %d/%02d/%d est un ", j, m, a);
if (m >= 3)
m = m - 2;
else {
m = m + 10;
a -= 1;
}
ns = a / 100;
a = a % 100;
f = (j + a + a / 4 - 2 * ns + ns / 4 + (26 * m - 2) / 10) % 7;
if (f f = f + 7;
printf("%s\n", jour[f]);
}

Article publié le 25 Février 2012 Mise à jour le Lundi, 07 Novembre 2022 13:57 par BENKIRANE Fatima Ezzahra