IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Calendrier Perpetuel : perfectionnement du code


Sujet :

C

  1. #1
    Membre très actif
    Inscrit en
    Décembre 2006
    Messages
    205
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 205
    Par défaut Calendrier Perpetuel : perfectionnement du code
    Bonjour;
    Dans le cadre de mes études, voici l'énoncé d'un exercice que j'ai à faire:
    Donnez le jour de semaine d'une date comprise entre le

    1er janvier de l'an -2000 au 31 décembre de l'an 4000.

    Gérer si possible les différentents calendriers qui

    ont été utilisés dans l'hitoire de France.

    Voici mon code actuel de calendrier perpétuel en C (de l'an -2000 à 4000): permettant l'affichage du jour de la semaine (lundi, mardi,mercredi...) en fonction de la date, mais il reste perfectible.
    En effet, il y a des jours qui n'existent pas comme les 29 févriers des années non bissextiles qui sont affichées. Je voudrais que ces jours ne soient pas affichées (message d'erreur à la place).
    Je suis en train de plancher sur le code, si vous avez des solutions ou des astuces ou même des remarques quant à l'analyse, n'hésitez pas à me les communiquer.
    Merci.

    Voici le code du programme à perfectionner (élimination des jours n'ayant jamais existé comme les 29 févriers des années non bissextiles):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
     
    #include <stdio.h>
    #include <stdlib.h>
     
    int ansup (int an)
    {
    	int an_bis, an_nbis;
    	an_bis = an_nbis = 0;
     
    	while (an >= 2003)
    	 {
    	 	if ( an%4==0 && an%100!=0 || an%400==0 )
    			an_bis+=1;
    		else
    			an_nbis+=1;
    		an--;
    	}
     
      		return(an_bis * 366  + an_nbis * 365);  /* c'est le nombre de jours entre le 01/01/2003 et le 01/01 de l'année rentrée */
    }
     
    int aninf (int an)
    {
    	int an_bis, an_nbis;
    	an_bis = an_nbis = 0;
     
    	while (an < 2003)
    	{
    		if (an%4 == 0 && an%100 !=0 || an%400 == 0)
    			an_bis+=1;
    		else
    			an_nbis+=1;
    		an++;
    	}
     	return(an_bis * 366 + an_nbis * 365); /* c'est le nombre de jours entre le 01/01 de l'année rentrée et le 01/01/2003 */
    }
     
    int nb_jr (int mois, int an) /* calcul du nombre de jours passés en fonction de l'année (bissextile ou non) et du mois rentrés */
    {
    	int bissextile[13] = {0,31,29,31,30,31,30,31,31,30,31,30,31};
    	int n_bissextile[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
    	int som = 0;
     
    	if ( an%4==0 && an%100!=0 || an%400==0 )
    	{
    		while (mois>0)
    		{
    			som = som + bissextile[mois-1];
    			mois--;
    		}
    	}
    	else
    	{
    		while (mois>0)
    		{
    			som = som + n_bissextile[mois-1];
    			mois--;
    		}
    	}
    	return som;
    }
     
    int main ()
    {
    	int ans, ms, jr, jrs;
    	char *jouri[7] = {"mardi", "lundi", "dimanche", "samedi", "vendredi", "jeudi", "mercredi"};
    	char *jours[7] = {"mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche", "lundi"};
     
     	printf("rentrer une annee (entre -2000 et 4000) :");
    	scanf("%d",&ans);
    	printf("\n");
    	printf("rentrer un mois (entre 1 et 12) :");
    	scanf("%d",&ms);
    	printf("\n");
        printf("rentrer un jour (entre 1 et 31) :");
    	scanf("%d",&jr);
    	printf("\n");
     
        if ((ans >= -2000) && (ans <=4000) && (ms >=1) && (ms<=12) && (jr >=1) && (jr <= 31))
        {
    	    if(ans < 2003)   /*si l'année saisie est inférieure à 2003*/
    	    {
      		    printf("\nLe (%d/%d/%d) est un %s.\n\n", jr, ms, ans, jouri[(aninf (ans) - nb_jr (ms, ans) - jr)%7]);
    	    }
    	    else if (ans >= 2003) /*si l'année saisie est sup ou égale à 2003*/
    	    {
    		    if ( ans%4==0 && ans%100!=0 || ans%400==0 )
    			    jrs = 366 - nb_jr (ms, ans);
    		    else
    			    jrs = 365 - nb_jr (ms, ans); /*jrs est le nombre de jours restant de l'année rentrée*/
     
                printf("\nLe (%d/%d/%d) est un %s.\n\n", jr, ms, ans, jours[(ansup (ans) - jrs + jr)%7]);
    	    }
        }
        else 
        {
        printf ("\n");
        printf ("Erreur de saisie.\n");
        printf ("Saisir obligatoirement une date dont: \n");
        printf ("L'annee varie de -2000 a 4000 inclus.\n");
        printf ("Le mois varie de 1 a 12 inlus.\n");
        printf ("Le jour varie de 1 a 31 inclus.");
        }
    	return 0;
    }

  2. #2
    Membre expérimenté
    Inscrit en
    Décembre 2003
    Messages
    272
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 272
    Par défaut
    Citation Envoyé par cirtey
    Gérer si possible les différentents calendriers qui ont été utilisés dans l'hitoire de France.
    Je ne me rappelle plus trop quel calendrier était utilisé avant -45 (12 mois de 30 jours et 5 jours hors de l'année), mais jusqu'en 1582 c'était le calendrier julien : toutes les années multiples de 4 sont bisextiles.
    10 jours ont disparus lors du changement de calendrier, on est passé du jeudi 4 octobre 1582 au vendredi 15 octobre (en France, dans d'autres pays le changement de calendrier s'est fait plus tard).
    Il faut également noter qu'il n'y a pas d'an 0 dans le calendrier.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    if ( an%4==0 && an%100!=0 || an%400==0 )
    Avec des parenthèses ce sera mieux (2 fois dans ton code).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    if(ans < 2003)   /*si l'année saisie est inférieure à 2003*/
        {
        ...
        }
    else if (ans >= 2003) /*si l'année saisie est sup ou égale à 2003*/
        {
        ...
        }
    Le second "if" est superflu puisque c'est la condition contraire du premier.

  3. #3
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    La regle, pour les années bisextiles est:
    une année est bisextile si son nombre est divisible par quatre, sauf s'il est divisible par 100, sauf s'il est divisible par 400 (comprendre: elle l'est de nouveau, bien que divisible par 100 si elle est divisible par 400)...
    Il devient donc facile de créer une petite fonction qui s'occupe de calculer cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    /* @in: année à tester
       @out: 0 si l'annee n'est pas bisextile, 1 si elle l'est
    */
     
    int Bisextile(int annee)
    {
        if(annee%4==0)
        {
    /* si l'année est divisible par 4, il faut tester si elle l'est par 100 */
            if(annee%100==0)
            {
    /* si l'année est divisible par 100, il faut tester si elle l'est par 400*/
                 if(annee%400==0)
                     return 1;
    /* on n'arrive ici que si l'année n'est pas divisible par 400 (mais qu'elle
       l'est par 100) ;) */
                 return 0;
            }
    /* on n'arrive ici que si l'année n'est pas divisible par 100 (mais qu'elle
       l'est par 4) ;)*/
            return 1;
        }
    /* si l'année n'est pas divisible par 4, c'est d'office non */
        return 0;
    }
    Avec cette fonction prete, tu pourrait tres bien envisager de travailler selon le principe de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    /* le nombre de jours des douze mois de l'année (fevrier est à 0, car il
       faut le déterminer avec bisextile ;) */
    int mois[]={31,0,31,30,31,30,31,31,30,31,30,31};
    int annee;
    /* tout ce qu'il faut pour récupérer l'année */
     
    mois[1]=(Bissextile(annee)==1? 29:28;)
    /* ou, si  tu préfère */
    if(Bissextile(annee)==1)
        mois[1]=29;
    else
        mois[1]=28;
    /* la suite du travail ;) */
    /* si tu préfère avoir le nombre de jours de l'année, ca peut, apres avoir
       déterminé le nombre de jours de fevrier, se faire sous la forme de */
    int nb_jours=0;
    int i;
    for(i=0;i<12;i++)
        nb_jours+=mois[i];
    Pour arriver à déterminer le jour de la semaine d'une date bien précise, il ne te reste plus qu'à connaitre une date de référence
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 404
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 404
    Par défaut
    Je crois bien avoir lu dans une revue (Pour la Science, Sciences&Avenir ou Science&Vie Junior) que pour être exact, il faudrait aussi rajouter "sauf s'il est divisible par 4000", mais que:
    • À l'époque de l'écriture du magazine, ce n'était pas encore dans le calendrier officiel
    • On a le temps.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre très actif
    Inscrit en
    Décembre 2006
    Messages
    205
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 205
    Par défaut
    Merci pour vos réponses.
    Effectivement; les jours à éliminer sont:
    1- les 29 févriers des années non bissextiles
    2- l'année 0
    3- le 4, 5, 6, 6, 8, 9, 10, 11, 12, 13, 14, 15 octobre 1582 : le décalage grégorien qui supprima dix jours du calendrier, entre le 4 octobre 1582 et le 15 octobre 1582 pour les pays ayant immédiatement suivi Rome, ce qui permit de fixer de nouveau l’équinoxe de printemps le 21 mars, comme ce fut le cas au début de l’ère chrétienne

    Les cas 2 et 3 semblent relativement faciles à supprimer, il suffit de rajouter des conditions à la ligne 80 du code : if ((ans >= -2000) && (ans <=4000) && (ms >=1) && (ms<=12) && (jr >=1) && (jr <= 31)).
    Par contre les 29 févriers sont plus compliqués à supprimer.
    J'ai pensé à tranformer les 3 conditions en booléens puis les insérer dans le if de la ligne 80 du code. Par ex mettre en place la fonction calcul année non bissextile + jour 29 + mois 2 en true (1), me semble être une solution pour le cas 1. Qu'en pensez-vous? Est-ce faisable?

  6. #6
    Membre émérite Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Par défaut
    Pourquoi ne pas faire simplement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    int estbissextile(int annee)
     {return !(annee%4) && annee%100 || !(annee%400);}
     
     
    int main(void)
     {
     ...
     if (ms==2 && jr==29 && !estbissextile(ans))
      {
      /*Erreur*/
      ...
      }
     ...
     }
    ?

  7. #7
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Médinoc
    Je crois bien avoir lu dans une revue (Pour la Science, Sciences&Avenir ou Science&Vie Junior) que pour être exact, il faudrait aussi rajouter "sauf s'il est divisible par 4000", mais que:
    • À l'époque de l'écriture du magazine, ce n'était pas encore dans le calendrier officiel
    • On a le temps.
    Faux. (Pour une simple raison, on est dans l'ordre de grandeur de variation de l'annee qui est corrigee tous les six mois par l'ajout/le retrait de seconde -- voir difference entre temps UTC et temps TAI).

  8. #8
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    La technique habituelle de gestion de date sur une longue periode avec different calendrier est de prevoir des conversions de chaque calendrier vers le jour julien et inversement.

  9. #9
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    oui voir d'ailleurs thread et solution dans le forum Algo :

    http://www.developpez.net/forums/sho...d.php?t=260778

  10. #10
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145

  11. #11
    Membre très actif
    Inscrit en
    Décembre 2006
    Messages
    205
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 205
    Par défaut Avant dernière version
    Salut à tous;
    J'ai retravaillé le code en prenant en compte les jours inexistants.
    Que pensez-vous qu'il y a encore à améliorer?
    Comment faire alors?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
     
     
    #include <stdio.h>
    #include <stdlib.h>
     
    int ansup (int an)
    {
    	int an_bis, an_nbis;
    	an_bis = an_nbis = 0;
     
    	while (an >= 2003)
    	 {
    	 	if ( an%4==0 && an%100!=0 || an%400==0 )
    			an_bis+=1;
    		else
    			an_nbis+=1;
    		an--;
    	}
     
      		return(an_bis * 366  + an_nbis * 365);  /* c'est le nombre de jours entre le 01/01/2003 et le 01/01 de l'année rentrée */
    }
     
    int aninf (int an)
    {
    	int an_bis, an_nbis;
    	an_bis = an_nbis = 0;
     
    	while (an < 2003)
    	{
    		if (an%4 == 0 && an%100 !=0 || an%400 == 0)
    			an_bis+=1;
    		else
    			an_nbis+=1;
    		an++;
    	}
     	return(an_bis * 366 + an_nbis * 365); /* c'est le nombre de jours entre le 01/01 de l'année rentrée et le 01/01/2003 */
    }
     
    int nb_jr (int mois, int an) /* calcul du nombre de jours passés en fonction de l'année (bissextile ou non) et du mois rentrés */
    {
    	int bissextile[13] = {0,31,29,31,30,31,30,31,31,30,31,30,31};
    	int n_bissextile[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
    	int som = 0;
     
    	if ( an%4==0 && an%100!=0 || an%400==0 )
    	{
    		while (mois>0)
    		{
    			som = som + bissextile[mois-1];
    			mois--;
    		}
    	}
    	else
    	{
    		while (mois>0)
    		{
    			som = som + n_bissextile[mois-1];
    			mois--;
    		}
    	}
    	return som;
    }
     
    int main ()
    {
    	int ans, ms, jr, jrs;
    	char *jouri[7] = {"mardi", "lundi", "dimanche", "samedi", "vendredi", "jeudi", "mercredi"};
    	char *jours[7] = {"mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche", "lundi"};
        printf ("\n");
        printf ("Saisir une date entre l\'an -2000 et l\'an 4000 et vous aurez son jour de semaine.\n");
        printf ("\n");
        printf ("Attention ! Le calendrier de reference est le calendrier Gregorien.\n");
        printf ("Par consequent: \n");
        printf ("\n");
        printf ("1- L\'annee 0 n\'a jamais existe.\n");
        printf ("2- Le mois doit varier de 1 a 12 inclus.\n");
        printf ("3- Les mois de fevrier, avril, juin, septembre et novembre \n");
        printf ("ne peuvent en aucun cas contenir plus de 30 jours.\n"); 
        printf ("4- Il n' y a pas de 29 fevrier dans les annees non bissextiles.\n");
        printf ("5- Il n' y a pas de 30 fevrier.\n");
        printf ("6- Le jour varie de 1 a 31 inclus.\n");
        printf ("7- Le decalage gregorien supprima dix jours du calendrier julien:\n");
        printf ("entre le 4 octobre 1582 et le 15 octobre 1582;\n");
        printf ("ces jours decales par la reforme gregorienne n'\ont donc pas existe.\n");
        printf ("\n");
     	printf("Rentrer une annee (entre -2000 et 4000) :");
    	scanf("%d",&ans);
    	printf("\n");
    	printf("Rentrer un mois (entre 1 et 12) :");
    	scanf("%d",&ms);
    	printf("\n");
        printf("Rentrer un jour (entre 1 et 31) :");
    	scanf("%d",&jr);
    	printf("\n");
     
        if 
        (
            (
                (
                    (ans >= -2000) 
                    &&
                    (ans <= 4000) 
                    && 
                    (ans != 0)
                    &&
                    (ms >= 1) 
                    &&
                    (ms <= 12) 
                    &&
                    (jr >= 1) 
                    &&
                    (jr <= 31)
                )
            ) 
            &&
            (
                ( 
                    ( !( ans%4==0 && ans%100!=0 || ans%400==0 ) ) 
                    &&
                    (ms == 2)
                    &&
                    (jr == 29)
                )
                == 0
            )
            &&
            (  
                (
                    (jr >= 4) 
                    && 
                    (jr <= 15) 
                    &&
                    (ms == 10)
                    &&
                    (ans == 1582)
                )
                == 0    
            )
            &&
            (
                (   
                    (  
                        (ms == 2) || (ms == 4) || (ms == 6) || (ms == 9) || (ms == 11)  
                    ) 
                    && 
                    (  
                        (jr > 30)  
                    )
                )
                == 0
            )
            &&
            (
                (
                    (ms == 2)
                    &&
                    (jr == 30)
                )
                == 0
            )
        )
        {
    	    if(ans < 2003)   /*si l'année saisie est inférieure à 2003*/
    	    {
      		    printf("\nLe (%d/%d/%d) est un %s.\n\n", jr, ms, ans, jouri[(aninf (ans) - nb_jr (ms, ans) - jr)%7]);
    	    }
    	    else if (ans >= 2003) /*si l'année saisie est sup ou égale à 2003*/
    	    {
    		    if ( ans%4==0 && ans%100!=0 || ans%400==0 )
    			    jrs = 366 - nb_jr (ms, ans);
    		    else
    			    jrs = 365 - nb_jr (ms, ans); /*jrs est le nombre de jours restant de l'année rentrée*/
     
                printf("\nLe (%d/%d/%d) est un %s.\n\n", jr, ms, ans, jours[(ansup (ans) - jrs + jr)%7]);
    	    }
        }
     
     
     
        else 
        {
        printf ("\n");
        printf ("Echec!\n");
        printf ("Soit l\'annee saisie est hors champs (annee > 4000 ou < -2000).\n" );
        printf ("Soit une ou plusieurs des 7 conditions du calendrier gregorien\n");
        printf ("n\'ont pas etes respectees.\n");   
        printf ("Recommencez l\'operation.\n");
        }
    	return 0;
    }

  12. #12
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Je te suggère de lire les liens que j'ai donné. Je ne vois pas de raison de réexpliquer ce qui s'y trouvre.

  13. #13
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Allez, pour te permettre d'avancer, je vais te fournir un code qui fonctionne...

    Il est (tres) amplement commenté, et tu devrais arriver à en comprendre le fonctionnement...

    La seule chose que j'ai faite, c'est de fournir un mois et une date "en dur" dans le code (et c'est donc la seule modification que tu devra apporter)

    Il faut juste prendre en compte, pour les mois, le fait que janvier est le mois 0 (février le mois 1, mars le mois 2...), et, pour les jours, celui que lundi est le jour 0 (mardi, le jour 1...)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
     
    /* quelques valeurs pour éviter les "nombres magiques" 
       Toutes ces valeurs ne changeront normalement jamais... mais bon,
        Ca a une valeur hautement documentaire ;)*/
    /* nombre de jours d'une année bisextile */
    #define ABISEXTILE 366
    /* nombre de jours d'une année non bisextile */
    #define ANONBISEXTILE 365
    /* numéro du jour du 01/01/2000 (un samedi, mais avec lundi==0) */
    #define REFERENCE 5
    /* L'année de référence */
    #define REFANNEE 2000
    /* les prototypes des fonctions */
    int Bisextile(int annee);
    void Calendar(int ref, int mois, int bisextile);
    /* la fonction principale */
    int main()
    {
        /* notre jour de référence: le 01/01/2000 était un samedi */
    	int ref=REFERENCE;
    	/* l'année qui devrait etre introduite par l'utilisateur */
    	int annee=1968;/* pour l'exemple */
    	/* le mois qui devrait etre introduit par l'utiliateur */
    	int mois=8;/* pour l'exemple... représente septembre */
    	/* il faut travailler différemment selon que l'on cherche
    	   le calendrier d'une année avant ou apres notre année de référence*/
        int isbisextile;
        if(annee>REFANNEE)
        {
            int i;
            /* on passe toutes les années entre 2000 et annee en revue */
            for(i=REFANNEE;i<annee;i++)
            {
                if(Bisextile(i)==1)
                {
                    ref+=ABISEXTILE;
                }
                else
                {
                    ref+=ANONBISEXTILE;
                }
                /* on remet ref dans une fourchette [0,7[ */
                ref=ref%7;
            }
        }
        else
        {
            /* si l'année recherchée date d'avant l'an 2000, il faut soustraire 
               mais comme on se base sur le 01/01/2000, il faut commencer à
               partir de 1999 pour la soustraction des jours, et soustraire 
               également le nombre de jours de l'année recherchée ;) */
            int i;
            for(i=REFANNEE-1;i>=annee;i--)
            {
                if(Bisextile(i)==1)
                    ref-=(ABISEXTILE%7);
                else
                    ref-=(ANONBISEXTILE%7);
                /* probleme: ref peut etre devenu négatif (il se trouve dans une
                   fourchette [-7,7[)... ajouter 7 permet de récupérer une valeur
                    correcte */
                if(ref<0)
                    ref+=7;
            }
        }
        /* arrivé ici, ref correspond au jour de la semaine du 01/01/annee
           Il faut arriver au premier du mois recherché*/
        /* le nombre de jours des mois */
        int nbmois[]={31,0,31,30,31,30,31,31,30,31,30,31};
        /* dont on adapte février en fonction du fait que l'année soit bisextile
           ou non */
        if(Bisextile(annee)==1)
            nbmois[1]=29;
        else
            nbmois[1]=28;
        /* on rajoute les mois précédant celui qu'on recherche */
        int i;
        for(i=0;i<mois;i++)
            ref+=(nbmois[i]%7);
        /* et on remet la valeur dans la fourchette [0,7[ */
        ref=ref%7;
        /* pour, enfin, appeler la fonction d'affichage du calendrier */
        Calendar(ref,mois,annee);
        return 0;
    }
    /* fonction qui calcule si l'année est bisextile ou non
       @in: année recherchée
       @out: 1 si oui, 0 si non
    */
    int Bisextile(int annee)
    {
        if(annee%4==0)
        {
            if(annee%100==0)
            {
                if(annee%400==0)
                    return 1;
                return 0;
            }
            return 1;
        }
        return 0;
    }
    /* fonction qui affiche le calendrier...
       @ in: ref: numéro du jour du premier du mois
             mois: numéro du mois à afficher(avec janvier==0)
             annee: année affichée 
    */
    void Calendar(int ref, int mois, int annee)
    {
        /* il nous faut quelques tableaux utiles...
           celui des nombres de jour de l'année */
        int nbmois[]={31,0,31,30,31,30,31,31,30,31,30,31};
        /* que l'on adapte directement */
        if(Bisextile(annee)==1)
            nbmois[1]=29;
        else
            nbmois[1]=28;
        /* celui avec les noms en toutes lettres des mois */
        char nommois[12][10]={"janvier","fevrier","mars","avril","mai","juin",
                            "juillet","aout","septembre","octobre","novembre",
                            "decembre"};
     
        /* celui des jours de la semaine (4 caracctères utiles chaque fois, dont
           le dernier est un espace */
        char nomsem[7][5]={"lun ","mar ","mer ","jeu ","ven ","sam ","dim "};
        /* on affiche d'abord le mois impliqué et une "entete" */
        printf("Calendrier du mois de %s %d\n",nommois[mois],annee);
        int i;
        for(i=0;i<7;i++)
            printf("%s",nomsem[i]);
        printf("\n");
        /* ensuite, on affiche autant d'espace que nécessaire pour que le jour du
           premier du mois soit à la bonne position */
        for(i=0;i<ref;i++)
            printf("    ");
        /* et on termine en affichant les jours du mois...
           un petit calcul (ref+jour)%7 permet de savoir quel jour de la semaine
           c'est ;) */
        for(i=1;i<=nbmois[mois];i++)/* nous, on compte à partir de 1 :P */
        {
            printf(" %2d ",i);
            if((ref+i)%7==0)
                printf("\n");
        }
    }
    Il ne te reste plus qu'à gérer une fonction de convertion entre calendriers
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  14. #14
    Membre très actif
    Inscrit en
    Décembre 2006
    Messages
    205
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 205
    Par défaut
    Je vais finalement garder ma dernière version, je n'ai pas le temps de tout refaire à 0, j'ai d'autres projets en cours.
    Merci beaucoup à tous ceux qui ont contribué à ce thread.
    A+

  15. #15
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Heu...

    As tu au moins pris la peine de jeter une oeil au code que j'ai fournis, qui fonctionne parfaitement, et dans lequel il ne manque que l'inclusion des fichiers d'entetes, et peut etre l'une ou l'autre fonction
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Réponses: 58
    Dernier message: 27/04/2015, 15h09
  2. [XL-2002] RP et Feriés dans Calendrier perpetuel
    Par freddy80 dans le forum Excel
    Réponses: 3
    Dernier message: 22/04/2014, 10h35
  3. Calendrier - Extraire un code
    Par NooD dans le forum Access
    Réponses: 4
    Dernier message: 13/07/2006, 15h56
  4. Réaliser calendrier perpetuel avec EXEL
    Par Perdus dans le forum Autres Logiciels
    Réponses: 2
    Dernier message: 20/10/2005, 09h05
  5. [toFAQ]calendrier perpetuel
    Par philippe_jasmin dans le forum C
    Réponses: 17
    Dernier message: 22/04/2003, 20h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo