TP : premières fonctions#

Exercice 1 : renvoyer versus afficher#

Exécutez les cellules suivantes qui définissent deux fonctions.

#include <iostream>
using namespace std;
/** Une fonction qui calcule la valeur absolue
 * @param a un entier
 * @return la valeur absolue de a
 **/
int abs(int a) {
    if (a > 0) {
        return a;
    } else {
        return -a;
    }
}
/** Une fonction qui affiche la valeur absolue
 * @param a, un entier
 **/
void afficheAbs(int a) {
    if (a > 0) {
        cout << a << endl;
    } else {
        cout << -a << endl;
    }
}

Observez les appels suivants; y a-t-il une différence entre abs et afficheAbs?

BEGIN SOLUTION

abs renvoie une valeur alors que afficheAbs ne fait qu”afficher une valeur. On notera ci-dessous que, avec abs(3);, Jupyter ne montre pas du tout la valeur alors que, avec abs(3), Jupyter montre la valeur avec son type (int). Inversement afficheAbs affiche la valeur dans tous les cas mais ne la renvoie pas.

END SOLUTION

abs(-3)
abs(-3);
afficheAbs(-3)
afficheAbs(-3);

Essayez de deviner le résultat des appels suivants puis exécutez pour vérifier :

abs(-5) + abs(3)
afficheAbs(-5) + afficheAbs(3)

La seconde cellule vous donne une erreur, comprenez-vous pourquoi?

BEGIN SOLUTION

afficheAbs ne fait qu’afficher une valeur sans la renvoyer (type de retour void); il n’est donc pas possible de réutiliser cette valeur par la suite, par exemple pour faire un calcul.

END SOLUTION

Exercice 2 : une fonction utilisant une fonction#

Complétez la fonction ci-dessous dont on donne la documentation.

⚠️ Vous devez utiliser un appel à l’une des deux fonctions précédentes, afficheAbs ou abs; laquelle faut-il choisir? Pourquoi? ⚠️

/** Distance de deux points sur une droite
 * @param a un entier: la coordonnée du premier point
 * @param b un entier: la coordonnée du deuxième point
 * @return la valeur absolue de la différence entre a et b
 **/
int distance(int a, int b) {
    /// BEGIN SOLUTION
    return abs(b-a);
    /// END SOLUTION
}

Vérifiez le comportement de votre fonction distance sur l’exemple ci-dessous; essayez sur quelques autres exemples; corrigez la fonction si nécessaire :

distance(5,3)

Les tests ci-dessous automatisent partiellement la vérification du comportement de votre fonction; comme la valeur attendue est spécifiée, il ne reste qu’à vérifier que l’on obtient bien true à chaque fois :

distance(5,3) == 2
distance(-4,2) == 6
distance(2,-5) == 7

Exercice 3 : tests automatiques#

Dans l’exercice précédent, on a testé la fonction distance. Cependant, il a fallu exécuter les trois cellules de test séparément et s’assurer pour chacune d’entre elles que true était affiché et pas false. Pour n’être averti que s’il y a un problème et savoir d’où il provient, nous allons rassembler les tests en une seule cellule à l’aide de l’infrastructure d’automatisation des tests vue en cours.

Essayez les exemples suivants. Si vous avez une erreur du type no member named 'cerr', vous avez probablement redémarré le noyau en oubliant d’exécuter la première cellule de cette feuille contenant #include <iostream>.

Astuce

À chaque fois que vous redémarrez le noyau, allez ensuite dans Cellule -> Exécuter toutes les précédentes. Cela exécute toutes les cellules qui sont avant celle où vous vous trouvez. Vous éviterez ainsi de perdre du temps à chercher où sont les cellules qu’il faut ré-exécuter.

CHECK ( 1 < 2 );
CHECK ( 1 > 2 );

On remarque que, si la condition en paramètre de CHECK est vraie, il n’y a aucun affichage. Par contre si la condition est fausse, un message d’erreur indiquant la condition fausse est affiché.

Avec CHECK, les tests de la fonction distance se mettent sous la forme :

CHECK ( distance(5,3)  == 2 );
CHECK ( distance(-4,2) == 6 );
CHECK ( distance(2,-5) == 7 );
// BEGIN HIDDEN TESTS
CHECK ( distance(-5,-2) == 3);
// END HIDDEN TESTS

Exécutez ces tests. Leur exécution ne devrait rien afficher.

Exécutez les deux cellules suivantes pour définir et tester la fonction maxAbs. Corrigez la fonction pour qu’elle passe les tests.

/** Une fonction qui renvoie la valeur absolue du plus grand des deux entiers 
 *  en valeur absolue
 * @param a un entier
 * @param b un entier
 * @return la valeur absolue du plus grand des deux entiers en valeur absolue
 **/
int maxAbs(int a, int b) {
    if (abs(a) >= abs(b)) {
        return a;
    } else {
        return b;
    }
}
CHECK( maxAbs(  6,  2) ==  6 );
CHECK( maxAbs(-15,  5) == 15 );
CHECK( maxAbs( -2, -3) ==  3 ); 

Exercice 4 (à la maison)#

Mêmes consignes que pour l’exercice 1 :

/** somme des valeurs absolues (aussi appelée norme L1)
 * @param a un entier
 * @param b un entier
 * @return la somme des valeurs absolues de a et b
 **/
int sommeAbs(int a, int b) {
    /// BEGIN SOLUTION
    return abs(a) + abs(b);
    /// END SOLUTION
}
sommeAbs(5,-3)
sommeAbs(5,-3)  == 8
sommeAbs(-4,-2) == 6
sommeAbs(2,5) == 7

Exercice 5 : suivre la documentation et les tests#

Implantez la fonction nombreSecondes dont la documentation est donnée ci-dessous :

/** Renvoie en secondes la durée décrite en jours, heures, minutes, secondes
 * @param j un entier représentant le nombre de jours
 * @param h un entier représentant le nombre d heures
 * @param m un entier représentant le nombre de minutes
 * @param s un entier représentant le nombre de secondes
 * @return la durée totale en secondes
**/
/// BEGIN SOLUTION
int nombreSecondes(int j, int h, int m, int s) {
    return s + (60 * (m + 60 * (h + 24*j)));
}
/// END SOLUTION

Vérifiez son fonctionnement sur les exemples et tests ci-dessous :

nombreSecondes(1,1,1,1)
CHECK( nombreSecondes(0,0,0,1)  == 1      );
CHECK( nombreSecondes(0,0,1,0)  == 60     );
CHECK( nombreSecondes(0,1,0,0)  == 3600   );
CHECK( nombreSecondes(1,0,0,0)  == 86400  );
CHECK( nombreSecondes(3,2,5,25) == 266725 );

Bilan#

Dans cette feuille, vous vous êtes familiarisés avec les fonctions : distinction entre afficher et renvoyer, fonction appelant des fonctions, documentation, tests, tests automatiques. Vous avez maintenant le bagage requis pour la suite du TP où vous implanterez la fonction exponentielle.