Choisissez votre style :
colorisé,
impression
Correction 11
Pointeurs et références
Les solutions suivantes ne sont évidemment pas uniques. Si vous en trouvez de meilleures (ou si vous trouvez des erreurs), faites-le savoir ! Merci.
Par ailleurs, les solutions proposées correspondent à l'état de vos connaissances au moment où la série est abordée. D'autres solutions pourront être envisagées une fois de nouveaux concepts acquis.
Exercice 1 : Pointeurs et références (niveau 1)
Question 1 :
Le code fourni produit l'affichage suivant :
2
3
2
2
3
3
Explication : ptri et ri permettent toutes deux de désigner indirectement la variable i. La différence majeure entre les deux dans cet exemple est que ri ne peut désigner que i alors que ptri peut désigner n'importe quel entier lors de l'exécution de ce programme.
Ainsi, l'affectation ri = j veut dire que la variable désignée par ri, càd i, prend la valeur de j (2 au moment de l'exécution). Cette instruction ne signifie pas que l'adresse de i devient celle de j.
Ceci explique l'affichage d'un "2" produit par cette instruction.
Dans le cas de l'instruction ptri = &j, ptri qui désignait jusqu'alors i désigne désormais j, d'où l'affichage d'un "3".
Question 2 :
| 1 |
int& ri(i); |
Correct : déclaration d'un alias pour la variable i |
| 2 |
int* ptri(&i); |
Correct : déclaration d'un pointeur sur un entier initialisé avec l'adresse de i |
| 3 |
int& rj(0); |
Faux : une référence non constante doit être associée à une variable |
| 4 |
int* ptrj(0); |
Correct en C++98 : le pointeur nul existe bel et bien
en C++11 : le 0 est à remplacer par nullptr
|
| 5 |
int& rk; |
Faux : une référence doit absolument être liée à une variable |
| 6 |
int* ptrk; | Correct (mais pas recommandable) : on peut très bien déclarer un pointeur sans l'initialiser |
Exercice n°23 (pages 61 et 228) de l'ouvrage C++ par la pratique.
#include <iostream>
using namespace std;
int demander_nombre(int a, int b)
{
/* échange les arguments s'ils n'ont pas été donnés dans *
* le bon ordre. */
if (a > b) { int tmp(b); b=a; a=tmp; }
int res;
do {
cout << "Entrez un nombre entier compris entre "
<< a << " et " << b <<" : ";
cin >> res;
} while ((res < a) or (res > b));
return res;
}
int main () {
double valeur1(3.14159265358);
double valeur2(1.42857142857);
double valeur3(-12.344556667);
double* choix(0);
switch (demander_nombre(1,3)) {
case 1: choix = &valeur1; break;
case 2: choix = &valeur2; break;
case 3: choix = &valeur3; break;
}
cout << "Vous avez choisi " << *choix << endl;
return 0;
}
Exercice 3 : structures et références (niveau 1)
Exercice n°26 (pages 64 et 231) de l'ouvrage C++ par la pratique.
3.1 Références
#include <iostream>
using namespace std;
struct Maison {
string adresse;
};
struct Personne {
string nom;
Maison& home;
};
void affiche(const Personne& p) {
cout << p.nom << " habite " << p.home.adresse << endl;
}
int main()
{
Maison m1 = { "12 rue du chateau" };
Personne p1 = { "Pierre", m1 };
Personne p2 = { "Paul" , m1 };
Maison m2 = { "13 rue du chateau" };
Personne p3 = { "Steve", m2 };
Personne p4 = { "Sofia", m2 };
affiche(p1); affiche(p2);
affiche(p3); affiche(p4);
return 0;
}
3.2 Limites des références
Les références ne pouvant pas être modifiées (en tant que telles, i.e. être déplacées), il faut ici les remplacer par des pointeurs :
#include <iostream>
using namespace std;
struct Maison {
string adresse;
};
struct Personne {
string nom;
Maison* home;
};
void affiche(const Personne& p) {
cout << p.nom << " habite " << (*(p.home)).adresse << endl;
// Note : (*X).Y peut aussi s'écrire X->Y, par exemple ici :
// (p.home)->adresse
}
int main()
{
Maison m1 = { "12 rue du chateau" };
Personne p1 = { "Pierre", &m1 };
Personne p2 = { "Paul" , &m1 };
Maison m2 = { "13 rue du chateau" };
Personne p3 = { "Steve", &m2 };
Personne p4 = { "Sofia", &m2 };
affiche(p1); affiche(p2); affiche(p3); affiche(p4);
// déménagement de Pierre (p1)
p1.home = &m2;
cout << "maintenant : ";
affiche(p1); affiche(p2); affiche(p3); affiche(p4);
return 0;
}
Exercice 4 : Intégrales revisitées (pointeurs sur fonctions, niveau 2)
Exercice n°27 (page 65 et 235) de l'ouvrage C++ par la pratique.
#include <iostream>
#include <string>
#include <cmath>
#include <array>
using namespace std;
// ----------------------------------------------------------------------
double f1(double x) { return x*x; }
double f2(double x) { return sqrt(exp(x)); }
double f3(double x) { return log(1.0+sin(x)); }
// ----------------------------------------------------------------------
typedef double (* Fonction)(double);
// ou typedef function <double (double)> Fonction;
// mais dans ce cas il faut inclure <functional>
// option légèrement plus élaborée que ce qui est suggéré par l'énoncé
struct aChoisir {
string description;
Fonction f;
};
// ----------------------------------------------------------------------
constexpr int MAXF(5);
/* notez la syntaxe particulière ici : ne pas mettre les accolades
autour des structure dans le array!
*/
const array <aChoisir, MAXF> choix = { "x carré", f1 ,
"racine d'exponentielle", f2 ,
"log(1+sin(x))", f3 ,
"sinus", sin ,
"exponentielle", exp
};
/* remplacer sin et exp par : (double (*)(double))sin et
(double (*)(double)) exp dans la version avec les functional de C++11
*/
// ----------------------------------------------------------------------
double demander_nombre();
unsigned int demander_fonction();
double integre(Fonction f, const double a, const double b);
// ======================================================================
int main()
{
unsigned int rep(demander_fonction());
double a(demander_nombre());
double b(demander_nombre());
cout.precision(12);
cout << "Integrale de " << choix[rep].description << " entre " << a
<< " et " << b << " :" << endl;
cout << integre(choix[rep].f, a, b) << endl;
return 0;
}
// ======================================================================
double demander_nombre()
{
double res;
cout << "Entrez un nombre réel : " << flush;
cin >> res;
return res;
}
// ======================================================================
unsigned int demander_fonction()
{
unsigned int rep;
do {
cout << "Vous pouvez choisir parmi les fonctions suivantes :" << endl;
for (unsigned int i(0); i < MAXF; i++)
cout << " " << i+1 << "- " << choix[i].description << endl;
cout << "De quelle fonction voulez vous calculer l'intégrale [1-5] ? "
<< flush;
cin >> rep;
} while ((rep < 1) || (rep > MAXF));
return --rep;
}
// ======================================================================
double integre(Fonction f, const double a, const 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;
}
Dernière mise à jour : $Date: 2025/11/13 12:01 $