Série 5
Fonctions (1)
But
Le but de cette série est de vous faire pratiquer la notion de fonction.Création du projet sous QTCreator
Afin de vous inciter à vous familiariser avec QTCreator, une façon simplifiée de configurer cet outil vous est proposé dans cette série. Inspirez-vous de la vidéo de la semaine passée en utilisant cette fois l'archive serie5.zip.
Exercice 0 : reprise de l'exemple du cours (fonctions, niveau 0)
Cliquez ici si vous souhaitez faire cet exercice.
Exercice 1 : Portée (niveau 1)
Copiez (avec la souris : sélectionnez le texte puis cliquez le bouton du milieu dans votre éditeur) le contenu suivant dans un fichier portee.cc et compilez-le (ne prêtez pas attention aux «Warnings») et lancez l'exécution.
#include <iostream>
using namespace std;
int variable(10);
int main()
{
{
int variable(5);
cout << "Un, la variable vaut : " << variable << endl;
}
{
cout << "Deux, la variable vaut : " << variable << endl;
}
for (int variable(0); variable < 3; variable++) {
cout << "Trois, la variable vaut : " << variable << endl;
}
cout << "Quatre, la variable vaut : " << variable << endl;
for (variable = 0; variable < 3; variable++) {
cout << "Cinq, la variable vaut : " << variable << endl;
}
cout << "Six, la variable vaut : " << variable << endl;
return 0;
}
- Quelles sont les variables locales et globales pour chaque bloc ?
- Expliquez [à votre voisin(e)] les valeurs affichées.
Exercice 2 : Prototypes (niveau 1, puis 2 pour les points 4 & 5)
Écrivez un programme proto.cc dans lequel vous définissez une fonction demander_nombre() respectant le prototype suivant :
int demander_nombre();
-
Placez la définition de la fonction avant le main().
Faites appel à la fonction dans le main() et affichez le résultat renvoyé. -
Que se passe-t-il si l'on déplace la définition de
la fonction demander_nombre() après le
main() et que l'on recompile le
programme ?
(faites-le et vérifiez si le compilateur réagit comme vous vous y attendiez). - Ajoutez ensuite le prototype de la fonction demander_nombre() avant main() et recompilez le programme.
-
Modifiez maintenant la fonction pour qu'elle prenne 2
arguments : les bornes minimales et maximales entre lesquelles
l'utilisateur doit donner le nombre.
La fonction doit boucler tant que l'utilisateur ne donne pas un chiffre valide. - Raffinez encore le programme de sorte que si la borne maximale est inférieure ou égale à la borne minimale, elle ne soit pas prise en compte (c'est-à-dire que l'on peut entrer n'importe quel chiffre plus grand que la borne minimale).
Exercice 3 : Fonctions simples (niveau 1)
Écrivez les fonctions suivantes, et testez-les en les appelant dans la fonction main de votre programme sur des exemples:
- Écrivez une fonction min2 qui reçoit deux arguments de type double et retourne le plus petit d'entre eux. Le type de retour devra donc être double.
- Écrivez une fonction min3 qui prend trois arguments de type double et retourne le plus petit d'entre eux. Comment utiliser la fonction min2 du point précédent pour écrire le corps de min3 en une ligne ?
Exercice 4 : Passage des paramètres (niveau 1)
Écrivez le programme echange.cc dans lequel vous devez écrire (prototype + définition) une fonction echange qui :
- accepte deux arguments de type entier ;
- échange les valeurs de ces deux arguments.
Vous essayerez votre fonction avec le code
int main()
{
int i(10);
int j(55);
cout << "Avant: i=" << i << " et j=" << j << endl;
echange(i,j);
cout << "Après: i=" << i << " et j=" << j << endl;
return 0;
}
Avant: i=10 et j=55 Après: i=55 et j=10
Exercice 5 : Sapin (niveau 2)
On vous donne les deux fonctions suivantes:
void etoiles(int nb_etoiles)
{
for(int i(0); i < nb_etoiles; ++i) {
cout << '*';
}
}
void espaces(int nb_espaces)
{
for(int i(0); i < nb_espaces; ++i) {
cout << ' ';
}
}
- Utilisez ces fonctions pour écrire une fonction qui affiche un triangle d'étoiles, et qui prend en paramètre le nombre de lignes du triangle:
* *** ***** - Utilisez cette fonction pour afficher un sapin:
* *** * *** ***** * *** ***** ******* *Vous devrez modifier un peu la fonction écrite au point 1. afin que votre sapin ressemble à celui dessiné ci-dessus. -
Le sapin précédent n'est pas très joli. Il est bien trop allongé et ne ressemble pas beaucoup à un vrai sapin. Adaptez votre code pour qu'il affiche le graphique ci-dessous:
* *** ***** *** ***** ******* ***** ******* ********* |||
Exercice 6 : calcul de PGDC (algorithme d'Euclide, niveau 2)
(pages 92 et 272 dans la 2e édition).
(PGDC = plus grand diviseur commun)
Buts
Écrivez le programme pgdc.cc qui :
- demande à l'utilisateur d'entrer deux entiers strictement positifs a et b;
- teste si a et b sont bien strictement positifs, et dans le cas contraire les redemande à l'utilisateur.
- trouve les entiers u, v et p satisfaisant l'identité de Bezout (i.e. une équation à valeurs entières) : u a + v b = p, avec p le plus grand commun diviseur de a et b.
Méthode
La méthode utilisée est l'algorithme d'Euclide.
On procédera par itération, comme suit (en notant x / y le quotient et x % y le reste de la division entière de x par y) :
| 0 : initialisation | u0 = 1 | v0 = 0 | ||
|---|---|---|---|---|
| x1 = a | y1 = b | u1 = 0 | v1 = 1 | |
| ... | ... | ... | ... | |
| i+1 : itération | xi+1 = yi | yi+1 = xi % yi | ui+1 = ui-1 - ui(xi / yi) | vi+1 = vi-1 - vi(xi / yi) |
| ... | ... | ... | ... | |
| Valeurs finales | xk-1 | yk-1 != 0 | uk-1 | vk-1 |
| k : condition d'arrêt quand yk = 0 | p = xk | yk = 0 | inutile | inutile |
C'est-à-dire que l'on va calculer de proche en proche les valeurs de x, y, u et v. En calculant à chaque fois les nouvelles valeurs en fonction des anciennes (et en faisant bien attention à mémoriser ce qui est nécessaire à un calcul correct, voir les indications ci-dessous).
Par exemple, yi+1 = xi % yi veut dire : "la nouvelle valeur de y vaut l'ancienne valeur de x modulo l'ancienne valeur de y".
Programmez ces calculs dans une boucle, qui s'execute tant que la condition d'arrêt n'est pas vérifiée.
Pensez à initialiser correctement vos variables avant d'entrer dans la boucle.
Indications
Vu les dépendances entre les calculs, vous aurez besoin de définir (par exemple) les variables : x, y, u, v et q=x/y, r=x%y, prev_u, prev_v, new_u et new_v.
Vous mettrez ces variables à jour à chaque itération, à l'aide des formules de la ligne i+1 et des relations temporelles évidentes entre elle (par exemple prev_u = u).
Testez si y est non nul avant d'effectuer les divisions !
Exemple d'execution
Entrez un nombre entier supérieur ou égal à 1 : 654321
Entrez un nombre entier supérieur ou égal à 1 : 210
Calcul du PGDC de 654321 et 210
x y u v
210 171 1 -3115
171 39 -1 3116
39 15 5 -15579
15 9 -11 34274
9 6 16 -49853
6 3 -27 84127
3 0 70 -218107
PGDC(654321,210)=3
Notes
Remarquez que pour le seul calcul du PGDC, le calcul de x et y par l'algorithme ci-dessus suffit, pas besoin de u et v. Ils ont été introduits ici pour trouver l'équation de Bezout (et vous faire programmer des suites imbriquées). Par exemple sur l'exemple précédent on a :-27 * 654321 + 84127 * 210 = 3.
Exercice 7 : La fonction cosinus (définition et appel de fonction, niveau 2)
Le but de cet exercice est d'écrire un programme cos.cc qui calcule une approximation de la fonction cosinus cos(x) (pour x dans [0, 2*pi])
Méthode
Pour calculer cos(x), on utilisera son développement en série :![]() |
![]() |
![]() |
Tâches
Écrire les fonctions suivantes (qui seront ensuite appelées depuis le main()) :-
double factorielle(int k)
qui calcule la factorielle d'un nombre k
(et la retourne au format double)
Utilisez pour cela une boucle for. - double somme_partielle(double x, int N) qui calcule la somme partielle de la série au rang N (somme des N premiers termes de la série ci-dessus).
Remarques :
-
La fonction factorielle renvoie facilement
des nombres très grands, qui dépassent les capacités de précision de
l'ordinateur. Pour un ordre de grandeur, avec le type double,
la plus grande valeur permise sera 170 (170! = 7.25742e+306).
La valeur retournée pour des nombre supérieurs à ces valeurs limites sera Infinity.
Évitez donc de tester le programme avec de trop grandes valeurs de N. - Vous pouvez raffiner votre programme de sorte à garantir que N soit inférieur ou égal à 85 (par exemple en utilisant la borne maximale dans demander_nombre).
- Notez que pour afficher plus de décimales dans le résultat, vous pouvez utiliser cout.precision, par exemple : cout.precision(12);.


