Partage
  • Partager sur Facebook
  • Partager sur Twitter

Suggestion pour "Envoyer des pointeurs"

Amélioration de l'exemple decoupeMinutes

    29 août 2024 à 15:57:24

    Bonjour,

    En faisant l'exercice, je me suis rendu compte d'une différence avec le corrigé, qui ne fonctionne qu'avec une valeur d'"heures" égale à 0 (et non différent de 0).

    https://openclassrooms.com/fr/courses/19980-apprenez-a-programmer-en-c/7672401-envoyez-des-pointeurs#/id/r-7672465

    Donc dans la fonction decoupeMinutes :

    void decoupeMinutes(int *heures, int *minutes)
    {
        *heures += *minutes/60;
        *minutes %= 60;
    }

    Il faut incrémenter les heures.

    Un détail, peut-être déjà remarqué d'ailleurs.

    Merci pour le cours, bien rédigé en tout cas !

    • Partager sur Facebook
    • Partager sur Twitter
      29 août 2024 à 16:15:29

      Vous avez raison, mais peut-être ce n'était pas le but de la fonction car elle se nomme decoupeminutes.
      • Partager sur Facebook
      • Partager sur Twitter
      ...
        29 août 2024 à 17:31:51

        Euh, pourtant les heures sont bien incrémenté ?
        Via le "+=" ?

        #include <stdio.h>
        
        void decoupeMinutes(int *heures, int *minutes)
        {
            *heures += *minutes/60;
            *minutes %= 60;
        }
        
        int main(void)
        {
            int heure = 0;
            int minute = 0;  
            
            decoupeMinutes(&heure, &minute);
            printf("%02d:%02d\n\n", heure, minute);
            
            minute += 93;
            decoupeMinutes(&heure, &minute);
            printf("%02d:%02d\n\n", heure, minute);  
            
            minute += 35;
            decoupeMinutes(&heure, &minute);
            printf("%02d:%02d\n\n", heure, minute);  
        }
        00:00
        
        01:33
        
        02:08



        • Partager sur Facebook
        • Partager sur Twitter
          29 août 2024 à 18:03:17

          RémiTHOMAS4 a écrit:

          Euh, pourtant les heures sont bien incrémenté ?
          Via le "+=" ?

          Ça, c'est le code de MaximeHalin. Dans le tutoriel, le code est
          void decoupeMinutes(int* pointeurHeures, int* pointeurMinutes)
          {   *pointeurHeures = *pointeurMinutes / 60;
              *pointeurMinutes = *pointeurMinutes % 60; 
          }
          En fait, le but de cette fonction est de transformer une quantité quelconque de minutes en son équivalent heures et minutes, avec, en sortie, minutes<60.


          -
          Edité par edgarjacobs 29 août 2024 à 18:09:21

          • Partager sur Facebook
          • Partager sur Twitter

          On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

            29 août 2024 à 18:36:01

            Dans le sous-titre, c'est écrit "amélioration".

            L'important est de comprendre la différence entre les deux versions.

            • Partager sur Facebook
            • Partager sur Twitter

            Le Tout est souvent plus grand que la somme de ses parties.

              29 août 2024 à 19:26:22

              MaximeHalin a écrit:

              Bonjour,

              En faisant l'exercice, je me suis rendu compte d'une différence avec le corrigé, qui ne fonctionne qu'avec une valeur d'"heures" égale à 0 (et non différent de 0).

              https://openclassrooms.com/fr/courses/19980-apprenez-a-programmer-en-c/7672401-envoyez-des-pointeurs#/id/r-7672465

              Merci pour le cours, bien rédigé en tout cas !

              C'est pas nous qu'il faut remercier, pour ce cours qui n'est pas si bien rédigé.

              L'exercice est foireux.   Les explications sont claires comme du jus de boudin.    Si il s'agit de découper une durée (exprimées en minutes) pour obtenir des heures et minutes, a priori 3 (trois) nombres sont concernées.

              La fonction,

              • on lui transmet la valeur du nombre de minutes initial
              • et ça place quelque part les nombres d'heures et de minutes

              ce qui donne une fonction à 3 paramètres

              void decomposer(int duree, int *h, int *m)
              {
                   *h = duree / 60;
                   *m = duree % 60;
              }
              

              les deux derniers sont les adresses ou il faut placer les résultats.

              La rédaction n'est pas bonne du tout. Il est écrit

              > Le gros intérêt des pointeurs (mais ce n'est pas le seul) est qu'on peut les envoyer à des fonctions pour qu'ils modifient directement une variable

              Ben non. Les pointeurs, ça ne modifie rien.   Un pointeur, ça contient une adresse, ça la modifie pas. Ce qui va modifier la variable dont on a l'adresse dans le pointeur, c'est les instructions qui utilisent la dé-référenciation (l'étoile). Et justement, ça ne les modifie pas directement, mais indirectement (elles passent par le contenu des variables h et m qui contiennent les adresses des variables à modifier.


              Exemple

              int main()
              {
                  int duree = 421;
                  int heures, minutes;
              
                  decomposer(duree, & heures, & minutes);
              	
                  printf("%d minutes, ça fait %d heures et %d minutes\n",
              		   duree, heures, minutes);
                  return 0;
              }
              

              Compilation et Exécution

              % make -k a && ./a
              cc     a.c   -o a
              421 minutes, ça fait 7 heures et 1 minutes






              -
              Edité par michelbillaud 29 août 2024 à 19:27:15

              • Partager sur Facebook
              • Partager sur Twitter
                30 août 2024 à 9:33:46

                edgarjacobs a écrit:



                Ça, c'est le code de MaximeHalin. Dans le tutoriel, le code est

                void decoupeMinutes(int* pointeurHeures, int* pointeurMinutes)
                {   *pointeurHeures = *pointeurMinutes / 60;
                    *pointeurMinutes = *pointeurMinutes % 60; 
                }

                En fait, le but de cette fonction est de transformer une quantité quelconque de minutes en son équivalent heures et minutes, avec, en sortie, minutes<60.


                -
                Edité par edgarjacobs il y a environ 14 heures

                ... Ahhh ... zut ...
                Merci de l'éclaircissement.

                Le problème du code du tuto, je pense, c'est comme ce que michelbillaud fait remarquer : il y a peu d'explication clair sur ce que dois faire la fonction.
                Bon, c'est vrai que les structures n'ont pas encore été vu à ce point dans le tuto, donc difficile d'organiser de manière un peu plus "naturel" le code, mais les commentaires devraient être plus utilisé.

                Personnellement, j'aurais fais un code proche de celui de michelbillaud, mais en rajoutant que le nombre d'heure doit rester inférieur à 24 (comme si je voulais manipuler une horloge).

                #include <stdlib.h>
                #include <stdio.h>
                
                // *************************************************************************/
                //  Ajoute un nombre de minute au temps
                // *************************************************************************/
                //  [IN/OUT] hour : Nombre d'heures, compris dans l'interval [0,24[
                //  [IN/OUT] minute : Nombre de minutes, compris dans l'interval [0,60[
                //  [IN] add_minute : Nombre de minutes à ajouter
                //  [RETURN] Nombre de jours en surplus
                // *************************************************************************/
                
                int AddMinute(int *hour, int *minute, int add_minute)
                {
                    int nb_day = 0;
                    
                    // Ajoute les minutes et repercute sur heure et jour
                    *minute += add_minute;
                    *hour += *minute / 60;
                    nb_day += *hour / 24;
                    
                    // Remet dans les bornes
                    *minute %= 60;
                    *hour %= 24;
                    
                    return nb_day;
                }
                
                
                // *************************************************************************/
                //  Affiche le résultat de la fonction AddMinute
                // *************************************************************************/
                //  [IN/OUT] hour : Nombre d'heures, compris dans l'interval [0,24[
                //  [IN/OUT] minute : Nombre de minutes, compris dans l'interval [0,60[
                //  [IN] add_minute : Nombre de minutes à ajouter
                // *************************************************************************/
                
                void ExplainAddMinute(int *hour, int *minute, int add_minute)
                {
                    int nb_day;
                    
                    printf("Ajout de %d minute%s à %02d:%02d  ==>  ", add_minute, add_minute > 1 ? "s" : "", *hour, *minute);
                    nb_day = AddMinute(hour, minute, add_minute);
                    printf("%02d:%02d", *hour, *minute);
                    if (nb_day > 0) {
                        printf(" (+%d jour%s)", nb_day, nb_day > 1 ? "s" : "");
                    }
                    printf("\n");
                }
                
                
                int main(void)
                {
                    int hour = 0;
                    int minute = 0;
                
                    ExplainAddMinute(&hour, &minute, 25);
                    ExplainAddMinute(&hour, &minute, 60);
                    ExplainAddMinute(&hour, &minute, 17);
                    ExplainAddMinute(&hour, &minute, 13);
                    ExplainAddMinute(&hour, &minute, 60*24); // Ajout d'un jour
                    ExplainAddMinute(&hour, &minute, 2*60*24); // Ajout de deux jours
                
                    return 0;
                }


                L'exécution de ce code donne :

                Ajout de 25 minutes à 00:00  ==>  00:25
                Ajout de 60 minutes à 00:25  ==>  01:25
                Ajout de 17 minutes à 01:25  ==>  01:42
                Ajout de 13 minutes à 01:42  ==>  01:55
                Ajout de 1440 minutes à 01:55  ==>  01:55 (+1 jour)
                Ajout de 2880 minutes à 01:55  ==>  01:55 (+2 jours)


                Bon après, c'est sûr qu'il faut savoir que "IN" ca veut dire que la variable doit déjà être initialisé (et avoir une valeur cohérente) avant appel de la fonction, et que "OUT" veut dire que la variable est modifiable depuis la fonction (el famoso but du pointeur).

                C'est une manière de décrire ses fonctions qui permet à un autre développeur (ou nous-même, plus tard) de comprendre comment la fonction doit être utilisé (même si je suis d'accord que ce serait mieux d'avoir une structure, unsigned int au lieu de int, utiliser time.h au lieu de refaire la roue ... mais c'est un exemple pour un débutant donc passons ça sous le tapis).



                -
                Edité par RémiTHOMAS4 30 août 2024 à 9:35:34

                • Partager sur Facebook
                • Partager sur Twitter
                  30 août 2024 à 10:19:51

                  Ou alors, on peut vouloir une fonction qui "normalise" une durée, qui est donnée en heures et minutes. 

                  Par exemple, 2 heures et 123 minutes, ça fait 4 heures et 3 minutes.

                  On retombe sur du code déjà vu

                  void normaliser_duree(int *h, int *m)
                  {
                  	*h += *m / 60;
                  	*m %=      60;
                  }
                  
                  

                  qu'on peut tester comme ça (faut toujours se prévoir un moyen de tester dès le départ)

                  void test_normalisation(int heures, int minutes)
                  {
                  	printf("%d heures et %d minutes, ", heures, minutes);
                  	normaliser_duree(& heures, & minutes);
                  	printf("ça fait %d heures et %d minutes\n", heures, minutes);	
                  }
                  
                  int main()
                  {
                  	test_normalisation(2, 123);
                  	return 0;
                  }
                  


                  Résultat

                  2 heures et 123 minutes, ça fait 4 heures et 3 minutes, 
                  


                  Remarque :  comme l'opérateur % n'est pas le célèbre modulo, alias reste de la division euclidienne , ça ne fait pas ce qu'on attendrait peut être pour les nombres négatifs

                  2 heures et -1 minutes, ça fait 2 heures et -1 minutes


                  Rappel : -5 / 2, ça donne -2 (quotient algébrique avec suppression de la partie fractionnaire, aka "arrondi vers zero")

                  et comme  le quotient et le reste sont liés par

                       a = (a/b)*b + (a%b)

                  ça nous fait -5 % 2 = -1.

                  Avec une division euclidienne, le quotient serait -3, et le reste 1.

                  -
                  Edité par michelbillaud 31 août 2024 à 23:44:33

                  • Partager sur Facebook
                  • Partager sur Twitter
                    31 août 2024 à 23:47:57

                    Le souci dans les cours sur les fonctions et les pointeurs, je trouve, c'est la confusion entre deux niveaux

                    • ce qu'on veut faire (niveau "algo")
                    • comment on va se débrouiller pour le faire en C

                    Un exemple dans le goût de ceux d'en dessus :

                    On veut du code qui

                    // 1. demande un nombre d'heures et de minutes
                    
                    // 2. se débrouille pour normaliser : ajuster le nombre
                    // d'heures pour que les minutes soient entre 0 et 59
                    
                    // 3. affiche les heures et les minutes
                    

                    En C, le premier point peut se faire par du code direct

                    int heures, minutes;
                    
                    // 1
                    
                    printf("Donnez les heures et les minutes : ");
                    scanf("%d%d", &heures, &minutes);

                    mais aussi en appelant une fonction qu'on a définie par ailleurs

                    // 1.
                    
                    demander_heures_minutes(& heures, &minutes);
                    

                    ce qui est intéressant si on le fait à plusieurs endroits et/ou si la fonction intègre des vérifications comme quoi on tape des nombres, etc.


                    Au niveau algorithmique, on peut dire que la fonction code une action qui sert à modifier le contenu des variables.

                    Mais en C, c'est autre chose. La fonction

                    void demander_heures_minute(int *h, int *m) 
                    {
                        printf("Donnez les heures et les minutes : ");
                        scanf("%d%d", h, m);
                    }
                    

                    ne reçoit pas de variables en paramètres. Ca n'existe pas en C, le passage de variables (*).

                    En C ce qui est passé en paramètre d'une fonction, ce sont toujours des valeurs, les valeurs des expressions indiquée en paramètres lors de l'appel.

                    Et quand on fait

                    demander_heures_minutes(& heures, &minutes);

                    ce qui est passé ce sont les valeurs des adresses des variables. Valeurs obtenues par les expressions &heures et &minutes.



                    (*) mais ça existait à l'époque dans d'autres langages (paramètres "var" de Pascal, paramètres passés par adresse en Fortran), ce qui fait que les auteurs de cours C se sont précipités à employer des termes qui prêtent à confusion pour ceux qui ne connaissent pas ces langages.  L'idée était de leur expliquer (à ceux qui connaissaient ces langages) qu'en C il n'y avait que le passage par copie de la valeur, mais que si on voulait faire une  action  qui modifie des variables , on pouvait contourner ça en écrivant une fonction à qui on passe les (valeurs des) adresses des variables.




                    -
                    Edité par michelbillaud 1 septembre 2024 à 12:47:43

                    • Partager sur Facebook
                    • Partager sur Twitter

                    Suggestion pour "Envoyer des pointeurs"

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    • Editeur
                    • Markdown