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).
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
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
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).
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
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).
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.
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
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
Suggestion pour "Envoyer des pointeurs"
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent
Le Tout est souvent plus grand que la somme de ses parties.