Exercice 1 | Exercice 2 | Exercice 3 | Exercice 4 | Exercice 5 | Exercice 6 | Exercice 7 |
En C++, une fonction est identifiée par son nom et par les types de ses paramètres. On peut en effet imaginer que certaines fonctions se comportent différemment selon le type de paramètre transmis : on n'inverse par exemple pas une matrice de la même manière que l'on inverse un nombre réel.
Dans cet exercice par contre, le contenu de la fonction n'est pas modifié car on échange toujours 2 objets de la même façon. Ce qui change par contre ici, c'est le type des paramètres et de la variable intermédiaire.
void echange(double& a, double& b) { double copie(a); a=b; b=copie; } void echange(char& a, char& b) { char copie(a); a=b; b=copie; }
![]() |
Notez que le langage C++ offre une possibilité de
faire ce genre de surcharges plus facilement : définir des fonctions
indépendamment du type de leurs arguments.
Ce sont les templates, que nous verrons au second semestre.
C'est un peu comme si on écrivait la fonction générique : void echange(<type>& a, <type>& b) { <type> copie(a); a = b; b = copie; } justement sans avoir à préciser le type. La façon correct de l'écrire en C++ est : template<typename Type> void echange(Type& a, Type& b) { Type copie(a); a = b; b = copie; } |
![]() |
![]() template<typename Type> void echange(Type& a, Type& b) { b = std::move(tmp); // Cela rend tmp invalide (mais peu importe ici puisqu'on ne l'utilise plus) } |
Je vous conseille de toujours commenter vos programmes, et en particulier de dire ce que fait chaque fonction, quels sont ses arguments et à quoi correspond la valeur de retour.
Cette fonction récursive est construite sur le schéma vu en cours :
if (n == 0) return 1;On pourrait même optimiser un peu plus et écrire :
if (n <= 1) return 1;
n * factorielleRecursive(n-1)
La base est assez simple :
unsigned int n;
unsigned int n(demander_nombre(0, 12));
cout << "Méthode itérative :" << endl; cout << " " << n << "! = " << factorielleIterative(n) << endl; cout << "Méthode récursive :" << endl; cout << " " << n << "! = " << factorielleRecursive(n) << endl;
On a donc finalement le programme suivant :
#include <iostream> #include <limits> #include <string> using namespace std; /* ---------------------------------------------------------------------- * Sortie : n! * ---------------------------------------------------------------------- */ unsigned int factorielleIterative(unsigned int n) { unsigned int fact(1); for (unsigned int i(2); i <= n; ++i) fact *= i; return fact; } /* ---------------------------------------------------------------------- * Sortie : n! * ---------------------------------------------------------------------- */ unsigned int factorielleRecursive(unsigned int n) { if (n == 0) return 1; else return (n * factorielleRecursive(n-1)); } /* -------------------------------------------------------------- * si b < a. * Sortie : le nombre saisi par l'utilisateur * -------------------------------------------------------------- */ unsigned int demander_nombre(unsigned int a, unsigned int b) { unsigned int res; do { cout << "Entrez un nombre entier "; if (a >= b) else cout << "compris entre " << a << " et " << b; cout << " : "; cin >> res; if (cin.fail()) { << "pas du charabia !" << endl; cin.clear(); // "jette" toute la ligne cin.ignore(numeric_limits<streamsize>::max(), '\n'); res = a-1; } } while ((res < a) or ((a < b) and (res > b))); return res; } // ---------------------------------------------------------------------- int main() { char rep; do { unsigned int n(demander_nombre(0, 12)); cout << " " << n << "! = " << factorielleIterative(n) << endl; cout << " " << n << "! = " << factorielleRecursive(n) << endl; do { cout << "Voulez-vous recommencer [o/n] ? "; cin >> rep; } while ((rep != 'o') and (rep != 'n')); } while (rep == 'o'); return 0; }
Cet exercice est très similaire au précédent et se fait de la même façon.
Le programme complet est :
#include <iostream> #include <limits> #include <string> using namespace std; int demander_nombre(int min, int max); int Fibonacci(int n); int FibonacciIteratif(int n); // ---------------------------------------------------------------------- int main() { char rep; do { int n(demander_nombre(0, 40)); cout << " F(" << n << ") = " << FibonacciIteratif(n) << endl; cout << " F(" << n << ") = " << Fibonacci(n) << endl; do { cout << "Voulez-vous recommencer [o/n] ? "; cin >> rep; } while ((rep != 'o') and (rep != 'n')); } while (rep == 'o'); return 0; } /* ---------------------------------------------------------------------- * Sortie : F(n) * ---------------------------------------------------------------------- */ int FibonacciIteratif(int n) { for (int i(1); i <= n; ++i) { Fn = Fn_1 + Fn_2; // pour n>=1 on calcule F(n)=F(n-1)+F(n-2) Fn_2 = Fn_1; // et on decale... Fn_1 = Fn; } return Fn; } /* ---------------------------------------------------------------------- * Sortie : F(n) * ---------------------------------------------------------------------- */ int Fibonacci(int n) { if (n == 0) return 0; else if (n == 1) return 1; else return Fibonacci(n-1) + Fibonacci(n-2); } /* -------------------------------------------------------------- * si b < a. * Sortie : le nombre saisi par l'utilisateur * -------------------------------------------------------------- */ int demander_nombre(int a, int b) { int res; do { cout << "Entrez un nombre int "; if (a >= b) else cout << "compris entre " << a << " et " << b; cout << " : "; cin >> res; if (cin.fail()) { << "pas du charabia !" << endl; cin.clear(); // "jette" toute la ligne cin.ignore(numeric_limits<streamsize>::max(), '\n'); res = a-1; } } while ((res < a) or ((a < b) and (res > b))); return res; }
#include <iostream> #include <cmath> using namespace std; double f(double x); double integre(double a, double b); double demander_nombre(); int main() { double a(demander_nombre()); double b(demander_nombre()); cout.precision(12); cout << "Integrale de f(x) entre " << a << " et " << b << " :" << endl; cout << integre(a,b) << endl; return 0; } double f(double x) { return x*x; } // double f(double x) { return x*x*x ; } // double f(double x) { return 1.0/x ; } // double f(double x) { return sin(x); } double integre(double a, double b) { double res; res = 41.0 * ( f(a) + f(b) ) + 216.0 * ( f((5*a+b)/6.0) + f((5*b+a)/6.0) ) + 27.0 * ( f((2*a+b)/3.0) + f((2*b+a)/3.0) ) + 272.0 * f((a+b)/2.0) ; res *= (b-a)/840.0; return res; } double demander_nombre() { double res; cin >> res; return res; }
On peut remarquer que A ET A = A. NON(A ET A) vaut donc NON(A). On peut alors écrire la fonction non ainsi :
bool non(bool A) { return non_et(A, A); }
Comme NON(NON(C)) = C, on a NON(NON(A ET B)) = A ET B. On peut donc écrire la fonction et ainsi:
bool et(bool A, bool B) { return non(non_et(A, B)); }
NON(A OU B) = NON(A) ET NON(B). Donc, (A OU B) = NON(NON(A OU B)) = NON(NON(A) ET NON(B)). On peut donc écrire la fonction ou ainsi:
bool ou(bool A, bool B) { return non_et(non(A), non(B)) }
Ces relations sont intéressantes en électronique: il suffit d'un seul type de composant (effectuant la fonction non_et) pour réaliser n'importe quel circuit logique.
Aucune difficulté majeure pour cet exercice qui est niveau 2 uniquement parce que l'énoncé est moins détaillé.
Voici le code correspondant :
#include <iostream> #include <limits> using namespace std; int demander_nombre(int min, int max); unsigned int cherche(unsigned int borneInf, unsigned int borneSup); constexpr unsigned int MIN(1); constexpr unsigned int MAX(100); // ---------------------------------------------------------------------- int main() { << endl << endl; const unsigned int solution( cherche(MIN, MAX) ); << endl; return 0; } /* ---------------------------------------------------------------------- * Recherche d'un nombre par dichotomie dans un intervalle [a b] * Sortie : la solution * ---------------------------------------------------------------------- */ unsigned int cherche(unsigned int a, unsigned int b) { // cout << "[ " << a << ", " << b << " ]" << endl; if (b < a) { return b; } unsigned int pivot((a+b)/2); char rep; do { cin >> rep; } while ((rep != '=') and (rep != '<') and (rep != '>')); switch (rep) { case '=': return pivot; case '<': return cherche(a, pivot-1); case '>': return cherche(pivot+1, b); } }
Le seul petit truc auquel il faut penser est peut être le switch : oui ! on peut faire un switch sur un caractère.
#include <iostream> #include <cmath> using namespace std; double const epsilon(1e-6); double f(double x) { return (x-1.0)*(x-1.5)*(x-2.0); } double df(double x) { return (f(x+epsilon)-f(x))/epsilon; } double itere(double x) { return x - f(x) / df(x); } int main() { double x1,x2; cin >> x2; do { x1 = x2; cout << " au point " << x1 << " : "<< endl; cout << " f(x) = " << f(x1) << endl; cout << " f'(x) = " << df(x1) << endl; x2 = itere(x1); cout << " nouveau point = " << x2 << endl; } while (abs(x2-x1) > epsilon); cout << "Solution : " << x2 << endl; return 0; }