ALGORITHME DE MAURICE KRAITCHIK (1882�1957)

cs_ghuysmans99 Messages postés 3982 Date d'inscription jeudi 14 juillet 2005 Statut Membre Dernière intervention 30 juin 2013 - 30 avril 2010 à 18:23
alkandor Messages postés 4 Date d'inscription mercredi 21 octobre 2009 Statut Membre Dernière intervention 3 septembre 2012 - 8 nov. 2010 à 01:08
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/51707-algorithme-de-maurice-kraitchik-1882-65533-1957

alkandor Messages postés 4 Date d'inscription mercredi 21 octobre 2009 Statut Membre Dernière intervention 3 septembre 2012
8 nov. 2010 à 01:08
je v modifié le code dans un petit temp
cs_ghuysmans99 Messages postés 3982 Date d'inscription jeudi 14 juillet 2005 Statut Membre Dernière intervention 30 juin 2013 16
11 juin 2010 à 21:01
@thebroyeur : si tu pouvais regarder ...

J'ai fait de nouvelles modifs. Au programme : ajout du support de l'Unicode et purification du code. Pour ce petit nettoyage de code, j'ai viré les commentaires différentiels qui ne facilitaient pas la lecture (et pis pour les modifs c'est décrit ici).

Le code est disponible à cette adresse : http://pastebin.com/Zh0WpWmp
cs_ghuysmans99 Messages postés 3982 Date d'inscription jeudi 14 juillet 2005 Statut Membre Dernière intervention 30 juin 2013 16
3 juin 2010 à 21:05
Oui, pas faux. Mais quand on modifie un programme en C, il n'est pas interdit de réfléchir à ce qu'on fait. Un oubli pareil ne peut passer inaperçu si l'on teste ses fonctions une fois qu'on les a modifiées. Perso je fais ça à chaque fois et je n'ai pas de problèmes (en même temps je n'ai jamais travaillé sur de gros projets en C). Cela doit néanmoins devenir un réflexe de procéder comme ça (énorme gain de temps au debugging).
Menuki Messages postés 13 Date d'inscription lundi 10 octobre 2005 Statut Membre Dernière intervention 11 août 2008
3 juin 2010 à 09:34
Tout à fait, je comprends très bien que ça ne sert à rien dans ce cas-ci (et dans beaucoup d'autres).

Le problème est que, si tu tolères des exceptions, tu trouveras toujours quelques "tout-fous" pour réclamer d'autres passe-droits.
Au final, tes règles de bonne conduite, censées être établies pour permettre un meilleur échange dans le groupe, ne seront qu'un ramassis de bonnes paroles.

Non, chez nous, cela fait partie de la discipline à laquelle tout le monde s'astreint (volontairement, je précise). Il est vrai que c'est un peu déroutant au début. Un oeil non habitué peut trouver cela moins lisible. Mais après peu de temps, c'est l'inverse qui se produit. Si on ne voit pas les accolades après le if, on est choqué.

Et puis, laisse-moi te raconter une histoire. Un gars de chez nous faisait la forte tête. "Je n'ai qu'une instruction, je ne mets pas d'accolade!". Un jour, il a dû rajouter une deuxième instruction à son if et... il a oublié de rajouter les accolades!
C'est moi qui ait trouvé le bug, pas lui. Comme j'étais choqué à chaque if, ça m'a sauté aux yeux.

Je pense que chez certains, c'est l'orgueil qui parle plus qu'autres choses. Ils pensent prouver leur maîtrise en utilisant toutes les subtilités du langage.
Je ne parle pas de toi. Je ne te connais pas, je ne me permettrais donc pas de te juger.
Certes, c'est bien de savoir ces choses mais si tu les appliques pour qu'au final, ça te complique la vie...

Pour ma part, je suis capable d'écrire du code ultra-condensé mais l'expérience m'a montré que 6 mois plus tard, ce qui était si clair et évident le devient beaucoup moins...
cs_ghuysmans99 Messages postés 3982 Date d'inscription jeudi 14 juillet 2005 Statut Membre Dernière intervention 30 juin 2013 16
2 juin 2010 à 19:14
Sorry j'avais pas présenté la 2ème alternative :
# if (*mois > 12 || *mois < 1)
# break;
Beaucoup plus lisible du coup. Mais quand c'est comme ici une série de if avec toujours la même chose dedans, tu peux bien comprendre que ça ne serve à rien dans ce cas-ci.
Menuki Messages postés 13 Date d'inscription lundi 10 octobre 2005 Statut Membre Dernière intervention 11 août 2008
2 juin 2010 à 09:32
Mais pourquoi diable, cher ami Ghuysmans99, aurais-je l'intention de te taper?
Nous sommes entre programmeurs de bonne compagnie et nous savons nous tenir. :-p

Par contre, j'avoue avoir un peu mal pris le "ça tourne au ridicule".
Quand je suis arrivé dans ma boîte, un gars avait pris cette habitude (dans sa boîte précédente).
J'ai trouvé ça un peu lourd mais je m'y suis plié.
Et je me suis rendu compte que c'était beaucoup plus lisible et qu'il y avait moins de risque d'erreur.
Essaie de relire du code ancien ou lire un code d'un autre : quand la partie action de ton "if" se trouve un coup à la fin de la ligne, un coup sur la ligne en dessous, un coup entre accolades, ça devient vite prise de tête...
Quand tu fais ça au fond d'une usine, avec le client stressé derrière toi parce qu'il perd 10.000€ par minute perdue, tu as envie de tuer le type qui n'a pas suivi la charte pour faire son expert!

Ca fait partie des règles de bonne conduite de notre société et ce n'est pas négociable (notamment avec les stagiaires ;-) ).
Après, en dehors, chacun fait ce qui lui plait mais faut pas se moquer des habitudes des autres. Ils ont peut-être des bonnes raisons de faire ainsi...
cs_ghuysmans99 Messages postés 3982 Date d'inscription jeudi 14 juillet 2005 Statut Membre Dernière intervention 30 juin 2013 16
1 juin 2010 à 19:03
Nouvelle proposition de code : http://pastebin.com/AP1AADHU
Menuki aura probablement moins envie de me taper dessus en le voyant (enfin j'espère).
cs_ghuysmans99 Messages postés 3982 Date d'inscription jeudi 14 juillet 2005 Statut Membre Dernière intervention 30 juin 2013 16
1 juin 2010 à 18:51
Mouais mais alors sans accolades décoratives ...

Là ça tourne au ridicule :
# if (*mois > 12 || *mois < 1)
# {
# break;
# }

Peut devenir :
# if (*mois > 12 || *mois < 1) break;
Menuki Messages postés 13 Date d'inscription lundi 10 octobre 2005 Statut Membre Dernière intervention 11 août 2008
1 juin 2010 à 14:48
Le break fait pareil (juste un jmp).
C'est pas pour une question de performance, c'est pour une question d'hygiène de vie!
C'est écrit partout sur les paquets de biscuit :
"Pour votre santé, éviter de manger sucré, salé et les goto" ;-)

Trève de plaisanterie, comme je l'ai précisé, je n'ai pas envie de rentrer dans la sempiternel gueguerre pro/anti goto. Sans les absoudre totalement, j'estime que, quand je peux faire autrement, je les évite. Et voici un moyen de les éviter (sans perte de performance en plus)...
cs_ghuysmans99 Messages postés 3982 Date d'inscription jeudi 14 juillet 2005 Statut Membre Dernière intervention 30 juin 2013 16
31 mai 2010 à 18:45
Ca donne en assembleur jmp short leLabel (deux octets).
Je vois pas pourquoi on pourrait être contre un goto dans le cas présent.
Menuki Messages postés 13 Date d'inscription lundi 10 octobre 2005 Statut Membre Dernière intervention 11 août 2008
31 mai 2010 à 10:00
Bien! Mais je n'aime pas trop les goto.

Même si dans certains cas, c'est bien pratique, quand j'ai une autre solution, je préfère les éviter (ne transformons pas ce sujet en guerre pro-contre goto ;-) ).
Dans mes pérégrinations, j'ai découvert une pratique dans des exemples de Microsoft : la "dummy loop".

Donc voici ce que je propose pour la vérification :

void entreDate(int* jour, int* mois, int* annee)
{
for (;;)
{
printf("Date (JJ MM AAAA) : ");
scanf("%d %d %d",jour,mois,annee);

// dummy loop
do
{
if (*jour > 31 || *jour < 1)
{
break;
}
//pas de jours négatifs ou > 31
if (*mois > 12 || *mois < 1)
{
break;
}
//pas de mois négatifs ou > 12
if (*jour > 29 && *mois == 2)
{
break;
}
//pas plus de 29 jours en févrierif (!((*annee % 4 0 && *annee % 100 > 0) || (*annee % 400 0)) && (*jour > 28))
{
break;
}
//pas plus de 28 jours en février pour les années bisextilesif ((*annee < 1582) || ((*annee 1582) && (*mois < 10)) || ((*annee 1582) && (*mois == 10) && (*jour < 15)))
{
break;
}
//jours en dessous du 15/10/1582 (date de la réforme grégorienne) invalides car calendrier différent avant cette date

// si on arrive ici, c'est qu'on a réussi tous les tests, donc la date est OK
return;
}while (false); // fin de la dummy loop

printf("Date invalide.\n");
}
}

Voilà, juste une proposition...
cs_ghuysmans99 Messages postés 3982 Date d'inscription jeudi 14 juillet 2005 Statut Membre Dernière intervention 30 juin 2013 16
30 mai 2010 à 18:58
Bon, mieux vaut prendre le code via Pastebin (là l'indentation n'est pas massacrée) :
http://pastebin.com/bc2PTzCE
cs_ghuysmans99 Messages postés 3982 Date d'inscription jeudi 14 juillet 2005 Statut Membre Dernière intervention 30 juin 2013 16
30 mai 2010 à 18:57
Update majeure du code comprenant la validation de la date :
---

/*
# Programme permettant la détermination du jour de la semaine
# d'aprés l'Algorithme de Maurice Kraitchik.

Code original de TheBroyeur - 30/04/2010.
Modifications apportées par :
- Menuki
- LeFauve42
- ghuysmans99

*/

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

// @ghuysmans99 : ajout
void entreDate(int* jour, int* mois, int* annee)
{
int dateOk;
do
{
printf("Date (JJ MM AAAA) : ");
scanf("%d %d %d",jour,mois,annee);

dateOk = 1;
if (*jour > 31 || *jour < 1) goto nok;
//pas de jours négatifs ou > 31
if (*mois > 12 || *mois < 1) goto nok;
//pas de mois négatifs ou > 12
if (*jour > 29 && *mois == 2) goto nok;
//pas plus de 29 jours en févrierif (!((*annee % 4 0 && *annee % 100 > 0) || (*annee % 400 0)) && (*jour > 28)) goto nok;
//pas plus de 28 jours en février pour les années bisextilesif ((*annee < 1582) || ((*annee 1582) && (*mois < 10)) || ((*annee 1582) && (*mois == 10) && (*jour < 15))) goto nok;
//jours en dessous du 15/10/1582 (date de la réforme grégorienne) invalides car calendrier différent avant cette date
goto ok;

nok:
dateOk = 0;
printf("Date invalide.\n");
ok:
;
} while (dateOk == 0);
}

int main()
{
int a; // l'année
int m; // le mois (mais janvier et février sont 13ème et 14ème mois de l'année suivante)
int q ; // le quantième du mois
int j; // le rang du jour de la semaine où 0=samedi, 1=dimanche, etc., 6=vendredi
// @Menuki : ajout
static const char* s_jours[] = {"samedi","dimanche","lundi","mardi","mercredi","jeudi","vendredi"};

// @ghuysmans99 : modif
entreDate(&q,&m,&a);

// @LeFauve42 : modif
if (m <= 2)
{
a--;
m+=12;
}

j = (q+2*m+((3*(m + 1))/5)+a+(a/4)-(a/100)+(a/400)+2)%7;

// @ghuysmans99 : modif
printf("Ce jour etait un %s.\n", s_jours[j]);

/*printf("\n");
system("pause");*/
return 0;
}
ADELSTYLE Messages postés 3 Date d'inscription mercredi 10 mars 2010 Statut Membre Dernière intervention 30 mai 2010
30 mai 2010 à 15:36
ahh! il reste les dates en dessous du 15/10/1582. ça marche normalement...
ADELSTYLE Messages postés 3 Date d'inscription mercredi 10 mars 2010 Statut Membre Dernière intervention 30 mai 2010
29 mai 2010 à 11:44
Oui mais c logique.
Merci à tous ceux qui ont fourni des idées

=============== Exemple :) ====================

#include <stdio.h>
#include <stdlib.h>

int main()
{
int j,m,M,a,jour;

static const char * s_jours[]={"Samedi","Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi"};
static const char * s_Mois[]={"Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Aout","Septembre","Octobre","Novembre","Décembre"};

printf("La date sous la forme JJ / MM / AAAA :\n\n");
printf("Entrez le jour (JJ): ");
scanf("%d",&j);
printf("Entrez le mois (MM): ");
scanf("%d",&m);
printf("Entrez l'année (AAAA): ");
scanf("%d",&a);
M=m;

if((M==2 && j>28) && !(a % 4 == 0 && a % 100 != 0 || a %400 == 0)){
printf("\n\nle mois de février [1-28] jour\n\n");}
else{
if(m == 2){a--;m=14;
jour=(j + 2*m + ((3*(m + 1))/5) + a + (a/4) - (a/100) + (a/400) + 2) % 7; a++;}
else if(m == 1) {a--;m=13;
jour=(j + 2*m + ((3*(m + 1))/5) + a + (a/4) - (a/100) + (a/400) + 2) % 7; a++;}
else jour=(j + 2*m + ((3*(m + 1))/5) + a + (a/4) - (a/100) + (a/400) + 2) % 7;

if(j 0 || m 0 || a == 0){
printf("\nErreur JJ/MM/AAA <> 0\n\n");}
else if(j > 31){
printf("\nErreur -> Jour [1-31]\n\n");}
else if(M > 12){
printf("\nErreur -> Mois [1-12]\n\n");}
else if(M == 4 & j >30){
printf("\nErreur -> Mois = 30 jour\n\n");}
else if(M == 6 & j >30){
printf("\nErreur -> Mois = 30 jour\n\n");}
else if(M == 9 & j >30){
printf("\nErreur -> Mois = 30 jour\n\n");}
else if(M == 11 & j >30){
printf("\nErreur -> Mois = 30 jour\n\n");}
else if(M == 2 & j > 29){
printf("\nErreur -> Mois = 29 jour\n\n");}
else {printf("\n%s %02d %s %04d\n\n",s_jours[jour],j,s_Mois[M-1],a);}
}
system("pause");
return 0;

}
cs_ghuysmans99 Messages postés 3982 Date d'inscription jeudi 14 juillet 2005 Statut Membre Dernière intervention 30 juin 2013 16
26 mai 2010 à 20:25
@adelstyle : Ton 1er code ne ressemble à rien. Et on se fiche complètement d'afficher le mois, l'utilisateur l'a déjà entré par lui-même.

Pour la validation de dates tu dois :
- Vérifier que le jour ne dépasse pas 31.
- Vérifier que le mois ne dépasse pas 12.
Si ces conditions sont remplies, tu peux maintenant vérifier la validité du jour (pas de 31/01 ni de 29/02/2001, par exemple). Tu dois aussi interdire les dates en dessous du 15/10/1582.

Voilà je pense que c'est tout.
Menuki Messages postés 13 Date d'inscription lundi 10 octobre 2005 Statut Membre Dernière intervention 11 août 2008
26 mai 2010 à 16:12
Je préfère la deuze mais avec la modif' de M. LeFauve42 :

if (m <= 2) {a--;m+=12;}

Par contre, il n'y a toujours pas de vérification des entrées...
ADELSTYLE Messages postés 3 Date d'inscription mercredi 10 mars 2010 Statut Membre Dernière intervention 30 mai 2010
26 mai 2010 à 16:02
pour afficher la date correctement

int j,m,M,a,jour;

static const char * s_jours[]={"samedi","dimanche","lundi","mardi","mercredi","jeudi","vendredi"};

printf("Entrez une date sous la forme JJ MM AAAA : ");
scanf("%d %d %d",&j,&m,&a);

M=m;

if(m == 2){a--;m=14;
jour=(j + 2*m + ((3*(m + 1))/5) + a + (a/4) - (a/100) + (a/400) + 2) % 7; a=a+1;}

else if(m == 1) {a--;m=13;
jour=(j + 2*m + ((3*(m + 1))/5) + a + (a/4) - (a/100) + (a/400) + 2) % 7; a=a+1;}

else jour=(j + 2*m + ((3*(m + 1))/5) + a + (a/4) - (a/100) + (a/400) + 2) % 7;

printf("\nLe jour de la semaine correspondant au %02d/%02d/%02d est %s\n.",j,M,a,s_jours[jour]);

====== autre solution: =========

int j,m,M,a,A,jour;

static const char * s_jours[]={"samedi","dimanche","lundi","mardi","mercredi","jeudi","vendredi"};

static const char * s_Mois[]={"Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Aout","Septembre","Octobre","Novembre","Décembre"};
printf("Entrez une date sous la forme JJ MM AAAA : ");
scanf("%d %d %d",&j,&m,&a);

M=m; A=a;

if(m == 2) {a--;m=14;}
if(m == 1) {a--;m=13;}

jour=(j + 2*m + ((3*(m + 1))/5) + a + (a/4) - (a/100) + (a/400) + 2) % 7;

printf("\n %s %02d %s %02d\n.",s_jours[jour],j,s_Mois[M-1],A);
thebroyeur Messages postés 7 Date d'inscription dimanche 10 décembre 2006 Statut Membre Dernière intervention 8 mai 2010 12
8 mai 2010 à 11:30
Oui c'est vrai. Je modifie le code tout de suite
cs_ghuysmans99 Messages postés 3982 Date d'inscription jeudi 14 juillet 2005 Statut Membre Dernière intervention 30 juin 2013 16
5 mai 2010 à 22:34
Non, ça ira très vite si c'est déclaré en static (ce que j'avais oublié de faire). En ASM c'est simplement de l'adressage basé-indexé. Exemple (si eax=jour) : mov edx,[jours+eax*4]
thebroyeur Messages postés 7 Date d'inscription dimanche 10 décembre 2006 Statut Membre Dernière intervention 8 mai 2010 12
5 mai 2010 à 19:22
dsl je continu ma phrase : .... de fonction comme celle-ci et qu'elle sont appelé un grand nombre de fois cela risque de ralentir ton programme.Bien sur dans ce cas, la différence est casi inexistante.
thebroyeur Messages postés 7 Date d'inscription dimanche 10 décembre 2006 Statut Membre Dernière intervention 8 mai 2010 12
5 mai 2010 à 19:16
Ouai c'est vrai que je n'ai pas fait de test sur la date entrée du fait que cette source est une réponse d'une demande que l'on m'a faite. Il est vrai qu'il est indispensable de tester la validité de la date.
Désolé ghuysmans99 si je me suis mal exprimé, ton code est aussi bon que le mien mais seulement si tu a beaucoup de fonction comme celle-ci et qu'elle sont appelé un grand nombre de fois.
Bien vu pour le static et surtout pour le if (m <= 2) {a--;m+=12;} ;) je vais le modifié.
cs_ghuysmans99 Messages postés 3982 Date d'inscription jeudi 14 juillet 2005 Statut Membre Dernière intervention 30 juin 2013 16
4 mai 2010 à 18:54
Mouais, pas faux pour le static const char* jours[];
Je n'y avais même pas pensé.

Il faudrait aussi penser à valider la date. Là l'utilisateur peut enter 17/343/2010 et le programme ne dira rien :D
LeFauve42 Messages postés 239 Date d'inscription vendredi 20 octobre 2006 Statut Membre Dernière intervention 20 avril 2009
4 mai 2010 à 15:57
> mais si certains comportements sont documentes dans les specificites du language

Il fallait bien sur lire :
"mais si certains comportements sont documentes dans les specifications du language"
LeFauve42 Messages postés 239 Date d'inscription vendredi 20 octobre 2006 Statut Membre Dernière intervention 20 avril 2009
4 mai 2010 à 15:55
>Mais je pense que dans la majorité des cas, il ne faut pas trop s'appuyer sur les
>fonctionnalités spécifiques d'un compilateur en particulier. Rien que pour l'aspect
>portabilité par exemple.

Vaste debat :o)

Je me souviens de mots cles tombes en desuetude, comme "register"(1) par exemple.
L'idee generale est "Le compilateur sait mieux que toi si cette variable doit etre mise dans un registre ou pas".

Apres ca depend ce qu'on entends par "compilateur" :
N'importe qui peut ecrire un compilateur C(2), ca se fait en quelques heures de TP et ca fonctionne pas trop mal pour des programmes simples.
Mais dans la vraie vie, il doit exister environ une demi-douzaine de compilateurs "serieux" et on peut sans problemes esperer qu'ils font bien leur boulot (gcc, visual studio, ...).

Et puis ce genre de comportements (allocation memoire des "variables constantes"(3)) est probablement documente precisement, et pas sujet a interpretation.
Pour dire ca autrement, je suis en faveur de la portabilite mais pas au point de mettre des parentheses partout au cas ou un compilateur exotique ne respecterait pas la precedence des operateurs generalement admise en C.

Bref, c'est bien de ne pas utiliser les specificites non standard d'un compilateur particulier, mais si certains comportements sont documentes dans les specificites du language, pourquoi s'en priver.

J'ai du mal a croire que j'ai ecrit autant sur un bout de code aussi simple (ok, on est un peu parti en "hors topic" vers la fin).

Toutes mes excuses aux lecteurs qui se sont perdu ici et qui ne demandaient qu'un bout de code pour connaitre le jour de la semaine :o)

Je dois commencer a radotter un peu (ca me fait ca quand on parle du bon vieux temps ;o) ).

En tous cas, merci a LeBroyeur pour nous avoir fait partager cet algo tres instructif.

Eric

(1) Et puisque le compilateur se charge d'optimiser tout seul comme un grand, on a ajoute de nouveaux qualifiers comme "volatile"... mais c'est un autre probleme
(2) J'ai bien dit "C", pas "C++". Prevoir un peu plus de temps pour ce dernier language :o)
(3) Oui, je sais, ca n'a pas de sens...
Menuki Messages postés 13 Date d'inscription lundi 10 octobre 2005 Statut Membre Dernière intervention 11 août 2008
4 mai 2010 à 14:42
A moi de te retourner le compliment, cher ami LeFauve42.

Je te dirais qu'en écrivant mon message, j'y pensais. Mais je dois avouer que la syntaxe des tableaux constants m'a toujours un peu échappé.
Grâce à toi, c'est peut-être rentré dans ma caboche. Je vais en mettre partout à présent!!! ^_^

Pour répondre à ta question, je dirais qu'il n'y a pas de réponse universelle car il n'y a pas qu'un compilateur.
Alors peut-être que certains compilateurs "intelligents" font cette optimisation car, comme tu le précises, il n'y a aucun avantage à faire une copie locale d'une variable constante (en tout cas, je n'en vois pas non plus).

Mais je pense que dans la majorité des cas, il ne faut pas trop s'appuyer sur les fonctionnalités spécifiques d'un compilateur en particulier. Rien que pour l'aspect portabilité par exemple.

Philosophiquement, même si ces fonctionnalités apportent un plus indéniable, je ne suis pas forcément convaincu que ce soit une bonne chose qu'on permette au programmeur d'écrire n'importe quoi en laissant le compilateur corrigé.
Cela me pose toujours un problème de conscience.
Car quoi? Ce n'est qu'une machine après tout! et c'est censé être nous les êtres supérieurs? Non?
LeFauve42 Messages postés 239 Date d'inscription vendredi 20 octobre 2006 Statut Membre Dernière intervention 20 avril 2009
4 mai 2010 à 13:56
Argh... J'ai completement pas pense a "static"... Bien vu Menuki

Mais ta declaration est celle d'un tableau sur objets constants, pas sur un tableau constant :o) (1)
Vu qu'on a un tableau constant d'objets constants, on pourrait avoir:
static const char *const s_jours[]...

Mais ma question premiere se pose toujours (un peu changee) :
Est-ce que le static est necessaire, puisque le tableau et son contenu sont constants, il est probable que le compilateur le traitera comme un "local static" (il n'a aucun interet a ne pas le faire (sauf si j'ai loupe un truc)).

Eric

(1) Vu que je suis completement dyslexique(2), c'est peut-etre le contraire (desole)
(2) Oui, j'ai du googler pour retrouver la bonne orthographe de ce mot :o)
Menuki Messages postés 13 Date d'inscription lundi 10 octobre 2005 Statut Membre Dernière intervention 11 août 2008
4 mai 2010 à 11:12
J'attendais que Ghuysmans99 réponde pour faire part de mon analyse mais puisqu'on en parle...

Le contenu des chaînes n'a pas à être modifié, donc on peut les passer en const.
Ensuite, il est inutile de recopier le tableau de pointeur sur la pile à chaque appel.
Comme on n'accède au tableau qu'en lecture, on peut le partager entre tous les appels (local static).

Je proposerais donc de déclarer la variable jours en tant que static const char * s_jours[] pour gagner la dizaine d'instruction nécessaire à l'initialisation du tableau.

PS: Bien vu l'histoire du m<=2!
LeFauve42 Messages postés 239 Date d'inscription vendredi 20 octobre 2006 Statut Membre Dernière intervention 20 avril 2009
4 mai 2010 à 10:42
Ca peut etre pratique comme algo.
Mais pour quelles dates est-il valide ?
Je pencherai pour 15/10/1582 => pas de limites mais j'ai du mal a trouver confirmation.

Puisqu'on est dans les optimisations, on peut aussi gagner quelques octets en remplacant
if (m == 1) {a--;m=13;}
if (m == 2) {a--;m=14;}
par :
if (m <= 2) {a--;m+=12;}

La seule difference de taille memoire entre la version originale et celle de ghuysmans99 est le tableau de pointeurs alloue sur la pile (les constantes chaine de caracteres vont etre alouees dans le segment TEXT du code (ou la partie DATA associee selon l'OS) dans les 2 cas).

Ca peut donc avoir quelques repercussions dans quelques cas tres particuliers (code tres recursif), mais honetement j'aurai aussi utilise un tableau (a moins d'etre dans un de ces cas tres particulier).

Le plus efficace serait sans doute de declarer le tableau comme global, afin de ne pas avoir a le recreer sur la pile a chaque appel de la fonction, mais les variables globales, c'est pas trop top pour la maintenance non plus...

A moins qu'en declarant le tableau comme "const" le compilateur se charge d'optimiser ?
Mes cours de compilation commencent un peu a dater :o) mais si quelqu'un a la reponse, je serais curieux de la connaitre.
cs_ghuysmans99 Messages postés 3982 Date d'inscription jeudi 14 juillet 2005 Statut Membre Dernière intervention 30 juin 2013 16
3 mai 2010 à 19:22
Idem que Menuki : argumente un peu parce que là ça parait un peu léger. 28 octets de pointeurs ce n'est pas beaucoup. Et ce n'est pas parce que le programme grandit que ça prendra plus de place. Je te rappelle quand même que tu prends beaucoup plus de place avec ton switch() car tu appelles printf() à chaque fois. Moi, seulement une fois.
Menuki Messages postés 13 Date d'inscription lundi 10 octobre 2005 Statut Membre Dernière intervention 11 août 2008
3 mai 2010 à 09:19
Tu pourrais expliquer en quoi l'utilisation d'un tableau augmente l'espace mémoire occupé?
Parce que tes chaînes dans les différents printf, on doit bien les trouver également dans les données du programme, non?
thebroyeur Messages postés 7 Date d'inscription dimanche 10 décembre 2006 Statut Membre Dernière intervention 8 mai 2010 12
2 mai 2010 à 22:48
oui c'est vrai cependant je pense que si tu part dans cette optique lorsque tu va réaliser des programmes assez important tu risque d'avoir des problemes avec ta mémoire. Ton programme est certe plus court en ce qui concerne le code mais il utilise plus d'espace mémoire puisque du introduit un tableau. La qualité d'un programme réside dans sa vitesse d'execution et dans l'espace memoire qu'il occupe ( ne pas oublier un code clair et bien commenté :) )
@++ T=
cs_ghuysmans99 Messages postés 3982 Date d'inscription jeudi 14 juillet 2005 Statut Membre Dernière intervention 30 juin 2013 16
30 avril 2010 à 18:23
Fonctionne nickel mais on peut faire plus court (21 lignes contre 45 dans ta version) :

#include <stdio.h>

int main()
{
int q; // quantième du mois
int m; // mois où janvier=13 et février=14
int a; // année
int j; // jour de la semaine en partant de samedi
char* jours[] = {"samedi","dimanche","lundi","mardi","mercredi","jeudi","vendredi"};

printf("Entrez une date sous la forme JJ MM AAAA : ");
scanf("%d %d %d",&q,&m,&a);

if (m == 1) {a--;m=13;}
if (m == 2) {a--;m=14;}
j = (q + 2*m + ((3*(m + 1))/5) + a + (a/4) - (a/100) + (a/400) + 2) % 7;

printf("\nLe jour de la semaine correspondant au %02d/%02d/%02d est %s.",q,m,a,jours[j]);

return 0;
}
Rejoignez-nous