Coincé au TP n°1

Le problème exposé dans ce sujet a été résolu.

Bonjour, je suis coincé au TP où le programme se doit de déterminer le jour de la semaine correspondant à une date donnée, exactement à la dernière partie (celle qui correspond aux objectifs du tp).

Mon programme ne fonctionne pas pour les années bissextiles (par exemple l’an mille). Je pense que c’est lié au fait que j’écris année au lieu de année - 1 dans mes sucres syntaxiques, ce qui fait que j’ajoute un jour dans le cas où l’année entrée est bissextile.

Maintenant, si j’écris année - 1, il faudra que je traite les cas où l’année présente et bissextile ou non, ce qui veux dire plusieurs switch (le code sera trop long!).

Ensuite, pour toute les années, ça déconne si j’entre un jour du mois de février, j’ai du mal à voir pourquoi.

Voici mon code :

 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
#include <stdio.h>

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

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

    nb_jours = 365 * (annee - 1);

    if (annee > 1582)
    {
        nb_jours += annee/4;
        nb_jours -= annee/100;
        nb_jours += annee/400;
        nb_jours += 2;
    }
    else
    {
        nb_jours += annee/4;
    }

    nb_jours += 31 * (mois - 1);


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

    nb_jours += (jour - 1);

    switch (nb_jours % 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;
        default:
            printf("Faille cosmique...\n");
            break;
    }

    return 0;
}

Merci d’avance.

+0 -0

Salut,

Mon programme ne fonctionne pas pour les années bissextiles (par exemple l’an mille). Je pense que c’est lié au fait que j’écris année au lieu de année - 1 dans mes sucres syntaxiques, ce qui fait que j’ajoute un jour dans le cas où l’année entrée est bissextile.

Ozmox

C’est exact.

Maintenant, si j’écris année - 1, il faudra que je traite les cas où l’année présente et bissextile ou non, ce qui veux dire plusieurs switch (le code sera trop long!).

Ozmox

Il est parfaitement possible de placer des if dans les case d’un switch si tu préfères. ;)

Sinon, relis bien le schéma proposé avant la réalisation de l’exercice, tu verras que tu ne réalises pas de vérification quant au calendrier en application.

+0 -0

Votre code est complètement faux pour les dates antérieures au changement de calendrier (Application dans les pays catholiques) https://fr.wikipedia.org/wiki/Calendrier_gr%C3%A9gorien

Vous devriez prendre comme base la date de changement de calendrier plutôt que l’année "1".

Faire les sommes des durées des mois, c’est plus simple que de faire des multiplication et des soustraction de chaman sous champignon hallucinogènes.

+0 -4

Votre code est complètement faux pour les dates antérieures au changement de calendrier (Application dans les pays catholiques) https://fr.wikipedia.org/wiki/Calendrier_gr%C3%A9gorien

bacelar

Parles-tu du code d’Ozmox ou bien de celui du cours ?

Vous devriez prendre comme base la date de changement de calendrier plutôt que l’année "1".

bacelar

Mais encore ?

Faire les sommes des durées des mois, c’est plus simple que de faire des multiplication et des soustraction de chaman sous champignon hallucinogènes.

bacelar

Merci, j’y penserai lors de ma prochaîne cuillette de champignons. Sinon, as-tu des remarques plus constructives ?

+2 -0

Parles-tu du code d’Ozmox ou bien de celui du cours ?

Je n’ai pas lu le cours, c’est celui d’Ozmox.

Mais peut-être que celui du cours est aussi pourri.

Faites simple.

Vous avez des paliers, donc avant toute "analyse", vous vérifiez dans quelle zone vous êtes.

Vous utilisez une méthode par zone.

pourquoi ce code ne fonctionne t-il pas?

Je sais pas mais ça manque clairement de parenthèses. Chacune de ces méthodes utilisera des fonctionnalités de base si nécessaire.

Principe de base, diviser pour mieux régner.

+0 -6

@bacelar: si tu n’a rien à apporter à cette discussion à part des critiques gratuites, je t’invite à passer ton chemin, tout le monde s’en portera mieux.

Enlève sa casquette de staff

Je suis en train de bidouiller là, juste une question, pourquoi ce code ne fonctionne t-il pas?

1
(booléen) ? nb_jours -= x : nb_jours -= y;
Ozmox

Sur ce point, la remarque de bacelar est correcte, il faut que tu entoures les deux assignations avec des parenthèses. En effet, l’opérateur conditionnel a une priorité supérieure aux oprateurs d’assignation, ce qui fait que ton expression est lue comme suit.

1
((booléen) ? nb_jours -= x : nb_jours) -= y;

Ce qui ne correspond pas à ce que tu souhaites. ;)

+0 -0

Il me semble qu’on ne peut pas définir une valeur avec une condition ternaire comme ceci.

L’usage standard est :

1
nb_jours -= (bool) ? x : y;
A-312

J’aurais pensé la même chose d’instinct, mais après vérification :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include <stdio.h>
#include <stdlib.h>


int main(int argc, const char* argv[])
{
    int x;
    1 ? x = 1 : 0;
    printf("%d\n", x);
    return EXIT_SUCCESS;
}

1
2
3
ge0@ventari /tmp » gcc -o -ansi -pedantic test test.c
ge0@ventari /tmp » ./test                            
1

C’est rigolo; :) En revanche, j’ai tapé 1 ? x = 1 : x = 0 au début et le compilateur m’a jeté :

1
2
3
4
test.c: In function ‘main’:
test.c:8:16: error: lvalue required as left operand of assignment
  1 ? x = 1 : x = 0;
                ^

En gros tu peux faire une assignation "en plein milieu de l’expression ternaire" mais pas de l’autre côté du :. J’avoue que j’ai du mal à trouver les mots pour expliquer ça.

Parles-tu du code d’Ozmox ou bien de celui du cours ?

Je n’ai pas lu le cours, c’est celui d’Ozmox.

Mais peut-être que celui du cours est aussi pourri. Principe de base, diviser pour mieux régner.

bacelar

Tu sers pas un peu à rien, toi ?

En gros tu peux faire une assignation "en plein milieu de l’expression ternaire" mais pas de l’autre côté du :. J’avoue que j’ai du mal à trouver les mots pour expliquer ça.

Ge0

La réponse est juste au-dessus, dans le post de Taurre. La priorité des opérateurs fait que ça n’est pas évalué comme tu le penses. Mais avec des parenthèses, il est parfaitement possible de faire une assignation dans la partie droite.

Il me semble qu’on ne peut pas définir une valeur avec une condition ternaire comme ceci.

L’usage standard est :

1
nb_jours -= (bool) ? x : y;
A-312

Effectivement c’est l’usage standard, mais il est tous à fait possible de faire n’importe quoi dans une ternaire. Il faut juste faire attention aux priorités opératoires et que le reste de l’expression soit compatible avec chacune des valeurs des ternaires.

+0 -0

Au passage, quelqu’un pourrait-il m’expliquer pourquoi le mois de février déconne avec mon code?

Il me semble avoir un truc du genre trois jours en moins par rapport au vrai.

Ozmox

C’est parce qu’il fait vriller ton code !

->[] Si vous me cherchez je suis dehors.

+3 -0

Assez logique vu ton switch.

Retire le ’case 2:’ de ton switch. Si on est le 2 février, pas besoin de retirer 3jours ;)

@LudoBike: :lol:

+0 -0

Effectivement c’est l’usage standard, mais il est tous à fait possible de faire n’importe quoi dans une ternaire. Il faut juste faire attention aux priorités opératoires et que le reste de l’expression soit compatible avec chacune des valeurs des ternaires.

ache

Juste pour compléter un peu, il y a quand même une limitation (sinon ça serait équivalent à faire du if ... else) : quand on écrit a ? b : c, b et c doivent être "à peu près du même type". Entre autres ça fonctionne si b et c sont des types "arithmétiques" (entiers ou flottants), ou encore si les deux sont de type void (liste non exhaustive). Par contre, théoriquement on doit pas pouvoir écrire des choses comme :

1
2
3
4
// Incorrect
void f(void) {}

cond ? 0 : f();

ou encore :

1
2
3
// Incorrect
char *p;
cond ? p = NULL : 1;

Bon en réalité tous les exemples théoriquement faux de cette forme que j’ai testés avec gcc compilent quand même, parfois avec un warning (tant qu’on n’essaye pas de faire quelque chose avec la valeur de l’expression ternaire). ^^

Il se trouve que l’astuce marche bien dans le cas ci-dessus parce que (x += 3) est de type int.

+0 -0

Je pense avoir trouvé quelque chose. Je teste avec ce site, il semble que ça fonctionne sur certaines dates totalement random alors que sur d’autres, je ne tombe pas sur le même jour. J’ai donc du mal à saisir le problème exact.

Par exemple pour le 28/10/2017 j’ai samedi, ok, pour le 19/05/1000 (année bissextile) j’ai dimanche, ok, pour le 12/1/13 j’ai jeudi, ok mais pour le 14/04/1561, j’ai dimanche alors que le site affiche lundi…

Voici mon code :

  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
#include <stdio.h>
#include <stdbool.h>

int main (void)
{
    unsigned jour, mois, annee;
    int nb_jours;
    bool bis_1, bis_2;
    
    printf("Entrez une date (jj/mm/aaaa) : ");
    scanf("%u/%u/%u", &jour, &mois, &annee);
    
    bis_1 = annee % 4 == 0 && (annee % 100 != 0 || annee % 400 == 0);
    bis_2 = annee % 4 == 0;
    
    nb_jours = 365 * (annee - 1);
    
    if (annee > 1582)
    {
        nb_jours += (annee - 1)/4;
        nb_jours -= (annee - 1)/100;
        nb_jours += (annee - 1)/400;
        nb_jours += 2;
    }
    else
    {
        nb_jours += (annee - 1)/4;
    }
    
    nb_jours += 31 * (mois - 1);
    
    switch (mois)
    {
        case 3:
            if (annee > 1582)
            {
                nb_jours -= (bis_1) ? 2 : 3;
            }
            else
            {
                nb_jours -= (bis_2) ? 2 : 3;
            }
            break;
        case 4:
        case 5:
            if (annee > 1582)
            {
                nb_jours -= (bis_1) ? 3 : 4;
            }
            else
            {
                nb_jours -= (bis_2) ? 3 : 4;
            }
            break;
        case 6:
        case 7:
        case 8:
            if (annee > 1582)
            {
                nb_jours -= (bis_1) ? 4 : 5;
            }
            else
            {
                nb_jours -= (bis_2) ? 4 : 5;
            }
            break;
        case 9:
        case 10:
            if (annee > 1582)
            {
                nb_jours -= (bis_1) ? 5 : 6;
            }
            else
            {
                nb_jours -= (bis_2) ? 5 : 6;
            }
            break;
        case 11:
        case 12:
            if (annee > 1582)
            {
                nb_jours -= (bis_1) ? 7 : 8;
            }
            else
            {
                nb_jours -= (bis_2) ? 7 : 8;
            }
            break; 
    }
    
    nb_jours += (jour - 1);
    
    switch (nb_jours % 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;
        default:
            printf("Faille cosmique...\n");
            break;
    }
    
    return 0;
}
+0 -0

En effet, j’ai étrangement l’impression de confondre le mois présent et le mois passé.

Voici un code fonctionnel :

  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
#include <stdio.h>
#include <stdbool.h>

int main (void)
{
    unsigned jour, mois, annee;
    int nb_jours;
    bool bis_1, bis_2;
    
    printf("Entrez une date (jj/mm/aaaa) : ");
    scanf("%u/%u/%u", &jour, &mois, &annee);
    
    bis_1 = annee % 4 == 0 && (annee % 100 != 0 || annee % 400 == 0);
    bis_2 = annee % 4 == 0;
    
    nb_jours = 365 * (annee - 1);
    
    if (annee > 1582)
    {
        nb_jours += (annee - 1)/4;
        nb_jours -= (annee - 1)/100;
        nb_jours += (annee - 1)/400;
        nb_jours += 2;
    }
    else
    {
        nb_jours += (annee - 1)/4;
    }
    
    nb_jours += 31 * (mois - 1);
    
    switch (mois)
    {
        case 3:
        case 4:
            if (annee > 1582)
            {
                nb_jours -= (bis_1) ? 2 : 3;
            }
            else
            {
                nb_jours -= (bis_2) ? 2 : 3;
            }
            break;
        case 5:
        case 6:
            if (annee > 1582)
            {
                nb_jours -= (bis_1) ? 3 : 4;
            }
            else
            {
                nb_jours -= (bis_2) ? 3 : 4;
            }
            break;
        case 7:
        case 8:
        case 9:
            if (annee > 1582)
            {
                nb_jours -= (bis_1) ? 4 : 5;
            }
            else
            {
                nb_jours -= (bis_2) ? 4 : 5;
            }
            break;
        case 10:
        case 11:
            if (annee > 1582)
            {
                nb_jours -= (bis_1) ? 5 : 6;
            }
            else
            {
                nb_jours -= (bis_2) ? 5 : 6;
            }
            break;
        case 12:
            if (annee > 1582)
            {
                nb_jours -= (bis_1) ? 7 : 8;
            }
            else
            {
                nb_jours -= (bis_2) ? 7 : 8;
            }
            break; 
    }
    
    nb_jours += (jour - 1);
    
    switch (nb_jours % 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;
        default:
            printf("Faille cosmique...\n");
            break;
    }
    
    return 0;
}

EDIT : Ah oui, dans la correction vous utilisez une technique particulière avec le switch, ce qui allège le code.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte