Licence CC BY-SA

TP : déterminer le jour de la semaine

Avant de poursuivre notre périple, il est à présent temps de nous poser un instant afin de réaliser un petit exercice reprenant tout ce qui vient d’être vu.

Objectif

Votre objectif est de parvenir à réaliser un programme qui, suivant une date fournie par l’utilisateur sous la forme « jj/mm/aaaa », donne le jour de la semaine correspondant. Autrement dit, voici ce que devrait donner l’exécution de ce programme.

Entrez une date : 11/2/2015
C'est un mercredi

Entrez une date : 13/7/1970
C'est un lundi

Première étape

Pour cette première étape, vous allez devoir réaliser un programme qui demande à l’utilisateur un jour du mois de janvier de l’an un et qui lui précise de quel jour de la semaine il s’agit, le tout à l’aide de la méthode présentée ci-dessous.

Entrez un jour : 27
C’est un jeudi
Déterminer le jour de la semaine

Pour déterminer le jour de la semaine correspondant à une date, vous allez devoir partir du premier janvier de l’an un (c’était un samedi) et calculer le nombre de jours qui sépare cette date de celle fournie par l’utilisateur. Une fois ce nombre obtenu, il nous est possible d’obtenir le jour de la semaine correspondant à l’aide de l’opérateur modulo.

En effet, comme vous le savez, les jours de la semaine suivent un cycle et se répètent tous les sept jours. Or, le reste de la division entière est justement un nombre cyclique allant de zéro jusqu’au diviseur diminué de un. Voici ce que donne le reste de la division entière des chiffres 1 à 9 par 3.

1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1
5 % 3 = 2
6 % 3 = 0
7 % 3 = 1
8 % 3 = 2
9 % 3 = 0

Comme vous le voyez, le reste de la division oscille toujours entre zéro et deux. Ainsi, si nous attribuons un chiffre de zéro à six à chaque jour de la semaine (par exemple zéro pour samedi et ainsi de suite pour les autres) nous pouvons déduire le jour de la semaine correspondant à un nombre de jours depuis le premier janvier de l’an un.

Prenons un exemple : l’utilisateur entre la date du vingt-sept janvier de l’an un. Il y a vingt-six jours qui le sépare du premier janvier. Le reste de la division entière de vingt-six par 7 est 5, il s’agit donc d’un jeudi.

Si vous le souhaitez, vous pouvez vous aider du calendrier suivant.

     Janvier 1        
di lu ma me je ve sa  
                   1  
 2  3  4  5  6  7  8  
 9 10 11 12 13 14 15  
16 17 18 19 20 21 22  
23 24 25 26 27 28 29  
30 31

À présent, à vous de jouer. ;)

Correction

Alors, cela s’est bien passé ? Si oui, félicitations, si non, la correction devrait vous aider à y voir plus clair. ;)

#include <stdio.h>


int
main(void)
{
    unsigned jour;

    printf("Entrez un jour : ");
    scanf("%u", &jour);

    switch ((jour - 1) % 7)
    {
    case 0:
        printf("C'est un samedi\n");
        break;

    case 1:
        printf("C'est un dimanche\n");
        break;

    case 2:
        printf("C'est un lundi\n");
        break;

    case 3:
        printf("C'est un mardi\n");
        break;

    case 4:
        printf("C'est un mercredi\n");
        break;

    case 5:
        printf("C'est un jeudi\n");
        break;

    case 6:
        printf("C'est un vendredi\n");
        break;
    }
    
    return 0;
}

Tout d’abord, nous demandons à l’utilisateur d’entrer un jour du mois de janvier que nous affectons à la variable jour. Ensuite, nous calculons la différence de jours séparant le premier janvier de celui entré par l’utilisateur. Enfin, nous appliquons le modulo à ce résultat afin d’obtenir le jour de la semaine correspondant.

Deuxième étape

Bien, complexifions à présent un peu notre programme et demandons à l’utilisateur de nous fournir un jour et un mois de l’an un.

Entrez une date (jj/mm) : 20/4
C'est un mercredi

Pour ce faire, vous allez devoir convertir chaque mois en son nombre de jours et ajouter ensuite celui-ci au nombre de jours séparant la date entrée du premier du mois. À cette fin, vous pouvez considérer dans un premier temps que chaque mois compte trente et un jours et ensuite retrancher les jours que vous avez compté en trop suivant le mois fourni.

Par exemple, si l’utilisateur vous demande quel jour de la semaine était le vingt avril de l’an un :

  • vous multipliez trente et un par trois puisque trois mois séparent le mois d’avril du mois de janvier (janvier, février et mars) ;
  • vous retranchez trois jours (puisque le mois de février ne comporte que vingt-huit jours les années non bissextiles) ;
  • enfin, vous ajoutez les dix-neuf jours qui séparent la date fournie du premier du mois.

Au total, vous obtenez alors cent et neuf jours, ce qui nous donne, modulo sept, le nombre quatre, c’est donc un mercredi.

À toutes fins utiles, voici le calendrier complet de l’an un.

      Janvier               Février                 Mars          
di lu ma me je ve sa  di lu ma me je ve sa  di lu ma me je ve sa  
                   1         1  2  3  4  5         1  2  3  4  5  
 2  3  4  5  6  7  8   6  7  8  9 10 11 12   6  7  8  9 10 11 12  
 9 10 11 12 13 14 15  13 14 15 16 17 18 19  13 14 15 16 17 18 19  
16 17 18 19 20 21 22  20 21 22 23 24 25 26  20 21 22 23 24 25 26  
23 24 25 26 27 28 29  27 28                 27 28 29 30 31        
30 31                                                             

       Avril                  Mai                   Juin          
di lu ma me je ve sa  di lu ma me je ve sa  di lu ma me je ve sa  
                1  2   1  2  3  4  5  6  7            1  2  3  4  
 3  4  5  6  7  8  9   8  9 10 11 12 13 14   5  6  7  8  9 10 11  
10 11 12 13 14 15 16  15 16 17 18 19 20 21  12 13 14 15 16 17 18  
17 18 19 20 21 22 23  22 23 24 25 26 27 28  19 20 21 22 23 24 25  
24 25 26 27 28 29 30  29 30 31              26 27 28 29 30        
                                                                  

      Juillet                 Août               Septembre        
di lu ma me je ve sa  di lu ma me je ve sa  di lu ma me je ve sa  
                1  2      1  2  3  4  5  6               1  2  3  
 3  4  5  6  7  8  9   7  8  9 10 11 12 13   4  5  6  7  8  9 10  
10 11 12 13 14 15 16  14 15 16 17 18 19 20  11 12 13 14 15 16 17  
17 18 19 20 21 22 23  21 22 23 24 25 26 27  18 19 20 21 22 23 24  
24 25 26 27 28 29 30  28 29 30 31           25 26 27 28 29 30     
31                                                                

      Octobre               Novembre              Décembre        
di lu ma me je ve sa  di lu ma me je ve sa  di lu ma me je ve sa  
                   1         1  2  3  4  5               1  2  3  
 2  3  4  5  6  7  8   6  7  8  9 10 11 12   4  5  6  7  8  9 10  
 9 10 11 12 13 14 15  13 14 15 16 17 18 19  11 12 13 14 15 16 17  
16 17 18 19 20 21 22  20 21 22 23 24 25 26  18 19 20 21 22 23 24  
23 24 25 26 27 28 29  27 28 29 30           25 26 27 28 29 30 31  
30 31                                                             

À vos claviers !

Correction

Bien, passons à la correction. :)

#include <stdio.h>


int
main(void)
{
    unsigned jour;
    unsigned mois;

    printf("Entrez une date (jj/mm) : ");
    scanf("%u/%u", &jour, &mois);

    unsigned njours = (mois - 1) * 31;

    switch (mois)
    {
    case 12:
        --njours;
    case 11:
    case 10:
        --njours;
    case 9:
    case 8:
    case 7:
        --njours;
    case 6:
    case 5:
        --njours;
    case 4:
    case 3:
        njours -= 3;
        break;
    }

    njours += (jour - 1);

    switch (njours % 7)
    {
    case 0:
        printf("C'est un samedi\n");
        break;

    case 1:
        printf("C'est un dimanche\n");
        break;

    case 2:
        printf("C'est un lundi\n");
        break;

    case 3:
        printf("C'est un mardi\n");
        break;

    case 4:
        printf("C'est un mercredi\n");
        break;

    case 5:
        printf("C'est un jeudi\n");
        break;

    case 6:
        printf("C'est un vendredi\n");
        break;
    }

    return 0;
}

Nous commencons par demander deux nombres à l’utilisateur qui sont affectés aux variables jours et mois. Ensuite, nous multiplions le nombre de mois séparant celui entré par l’utilisateur du mois de janvier par trente et un. Après quoi, nous soustrayons les jours comptés en trop suivant le mois fourni. Enfin, nous ajoutons le nombre de jours séparant celui entré du premier du mois, comme pour la première étape.

Notez que nous avons utilisé ici une propriété intéressante de l’instruction switch : si la valeur de contrôle correspond à celle d’une entrée, alors les instructions sont exécutées jusqu’à rencontrer une instruction break (ou jusqu’à la fin du switch). Ainsi, si le mois entré est celui de mai, l’instruction --njours va être exécutée, puis l’instruction njours -= 3 va également être exécutée.

Troisième et dernière étape

À présent, il est temps de réaliser un programme complet qui correspond aux objectifs du TP. Vous allez donc devoir demander à l’utilisateur une date entière et lui donner le jour de la semaine correspondant.

Entrez une date : 11/2/2015
C'est un mercredi

Toutefois, avant de vous lancer dans la réalisation de celui-ci, nous allons parler calendriers et années bissextiles. ;)

Les calendriers Julien et Grégorien

Vous le savez certainement, une année bissextile est une année qui comporte 366 jours au lieu de 365 et qui se voit ainsi ajouter un vingt-neuf février. Ce que vous ne savez en revanche peut-être pas, c’est que la détermination des années bissextile a varié au cours du temps.

Jusqu’en 1582, date d’adoption du calendrier Grégorien (celui qui est en vigueur un peu près partout actuellement), c’est le calendrier Julien qui était en application. Ce dernier considérait une année comme bissextile si celle-ci était multiple de quatre. Cette méthode serait correcte si une année comportait 365,25 jours. Cependant, il s’est avéré plus tard qu’une année comportait en fait 365,2422 jours.

Dès lors, un décalage par rapport au cycle terrestre s’était lentement installé ce qui posa problème à l’Église catholique pour le calcul de la date de Pâques qui glissait doucement vers l’été. Le calendrier Grégorien fût alors instauré en 1582 pour corriger cet écart en modifiant la règle de calcul des années bissextile : il s’agit d’une année multiple de quatre et, s’il s’agit d’une année multiple de 100, également multiple de 400. Par exemple, les années 1000 et 1100 ne sont plus bissextiles à l’inverse de l’année 1200 qui, elle, est divisible par 400.

Toutefois, ce ne sont pas douze années bissextiles qui ont été supprimées lors de l’adoption du calendrier Grégorien (100, 200, 300, 500, 600, 700, 900, 1000, 1100, 1300, 1400, 1500), mais seulement dix afin de rapprocher la date de Pâques de l’équinoxe de printemps.

Mode de calcul

Pour réaliser votre programme, vous devrez donc vérifier si la date demandée est antérieure ou postérieure à l’an 1582. Si elle est inférieure ou égale à l’an 1582, alors vous devrez appliquer le calendrier Julien. Si elle est supérieure, vous devrez utiliser le calendrier Grégorien.

Pour vous aider, voici un schéma que vous pouvez suivre.

Si l'année est supérieure à 1582
    Multiplier la différence d'années par 365
    Ajouter au résultat le nombre d'années multiples de 4
    Soustraire à cette valeur le nombre d'années multiples de 100
    Ajouter au résultat le nombre d'années multiples de 400
    Ajouter deux à ce nombre (du fait que seules dix années ont été supprimées en 1582)
Si l'année est inférieure ou égale à 1582
    Multiplier la différence d'années par 365
    Ajouter au résultat le nombre d'années multiples de 4

Au nombre de jours obtenus, ajouter la différence de jours entre
le mois de janvier et le mois fourni. N'oubliez pas que les mois comportent
trente et un ou trente jours et que le mois de février comporte pour sa
part vingt-huit jours sauf les années bisextiles où il s'en voit ajouter un
vingt-neuvième. Également, faites attention au calendrier en application pour
la détermination des années bissextiles !

Au résultat obtenu ajouter le nombre de jour qui sépare celui entré du premier
du mois.

Appliquer le modulo et déterminer le jour de la semaine.

À vous de jouer ! :)

Correction

Ça va, vous tenez bon ? :D

#include <stdio.h>


int
main(void)
{
    unsigned jour;
    unsigned mois;
    unsigned an;

    printf("Entrez une date (jj/mm/aaaa) : ");
    scanf("%u/%u/%u", &jour, &mois, &an);

    unsigned njours = (an - 1) * 365;

    if (an > 1582) /* Calendrier Grégorien */
    {
        njours += ((an - 1) / 4);
        njours -= ((an - 1) / 100);
        njours += ((an - 1) / 400);
        njours += 2;
    }
    else /* Calendrier Julien */
        njours += ((an - 1) / 4);

    njours += (mois - 1) * 31;

    switch (mois)
    {
    case 12:
        --njours;
    case 11:
    case 10:
        --njours;
    case 9:
    case 8:
    case 7:
        --njours;
    case 6:
    case 5:
        --njours;
    case 4:
    case 3:
        if (an > 1582)
        {
            if (an % 4 == 0 && (an % 100 != 0 || an % 400 == 0))
                njours -= 2;
            else
                njours -= 3;
        }
        else
        {
            if (an % 4 == 0)
                njours -= 2;
            else
                njours -= 3;
        }
        break;
    }


    njours += (jour - 1);

    switch (njours % 7)
    {
    case 0:
        printf("C'est un samedi\n");
        break;

    case 1:
        printf("C'est un dimanche\n");
        break;

    case 2:
        printf("C'est un lundi\n");
        break;

    case 3:
        printf("C'est un mardi\n");
        break;

    case 4:
        printf("C'est un mercredi\n");
        break;

    case 5:
        printf("C'est un jeudi\n");
        break;

    case 6:
        printf("C'est un vendredi\n");
        break;
    }
    
    return 0;
}

Tout d’abord, nous demandons à l’utilisateur d’entrer une date au format jj/mm/aaaa et nous attribuons chaque partie aux variables jour, mois et an. Ensuite, nous multiplions par 365 la différence d’années séparant l’année fournie de l’an un. Toutefois, il nous faut encore prendre en compte les années bissextiles pour que le nombre de jours obtenus soit correct. Nous ajoutons donc un jour par année bissextile en prenant soin d’appliquer les règles du calendrier en vigueur à la date fournie.

Maintenant, il nous faut ajouter le nombre de jours séparant le mois de janvier du mois spécifié par l’utilisateur. Pour ce faire, nous utilisons la même méthode que celle vue lors de la deuxième étape à une différence près : nous vérifions si l’année courante est bissextile afin de retrancher le bon nombre de jours (le mois de février comportant dans ce cas vingt-neuf jours et non vingt-huit).

Enfin, nous utilisons le même code que celui de la première étape.


Ce chapitre nous aura permis de faire une petite pause et de mettre en application ce que nous avons vu dans les chapitres précédents. Reprenons à présent notre route en attaquant la notion de boucle.