Séance d'exercices 7, Programmation I
Sciences et Technologies du Vivant, Semestre 1

Exercice 1 - Introduction aux pointeurs

Le but de cet exercice est de bien comprendre ce qui se passe dans la mémoire de l'ordinateur lorsqu'on utilise des pointeurs. Rappelez-vous qu'un pointeur est une variable particulière contenant une adresse mémoire. Comme les autre variables, un pointeur possède également sa propre adresse qu'on peut obtenir à l'aide de l'opérateur d'adressage &.

  1. Le programme ci-dessous illustre le fonctionnement des pointeurs en affichant les différentes valeurs contenues dans les variables.

    Lisez-le en essayant de le comprendre. Essayez de déduire quelles vont être les valeurs affichées par les instructions cout.

    #include <iostream>
    
    using namespace std;
    
    int main(int argc, char **argv) {
      int i = 9;
    
      cout << "Contenu de i: '" << i << "'" << endl;
      cout << "Adresse de i: '" << (unsigned int)&i << "'" << endl << endl;
    
      /* On declare un pointeur sur int et on lui
       * affecte l'adresse de i. On dit que p 
       * pointe sur i. */
      int *p = &i;
    
      cout << "Contenu de p: '" << (unsigned int)p << "'" << endl;
      cout << "Adresse de p: '" << (unsigned int)&p << "'" << endl;
      cout << "Contenu de la variable pointee par p: '" << *p << "'" << endl << endl;
    
      // On affecte 10 a l'adresse pointee par p.
      *p = 10;
    
      cout << "Contenu de la variable pointee par p: '" << *p << "'" << endl;
      cout << "Contenu de i: '" << i << "'" << endl;
    
      // Partie a completer
    
    
    
      // Fin de la partie a completer
    
      return 0;
    }
    

  2. Recopiez le programme donné dans emacs, compilez-le et lancez-le. Est-ce que les résultats affichés correspondent à ce que vous aviez prévu au point précédent?

    Remarque: les adresses en mémoire sont toujours affichées sous forme hexadécimale (base 16). Pour les voir sous forme décimale, il faut les convertir en unsigned int, comme dans l'exemple ci-dessus.

  3. Complétez le programme en incrémentant la variable i de 10 (i = i + 10), sans avoir recours directement à la variable i (utilisez un pointeur). Affichez ensuite la valeur de i pour vérifier que l'opération s'est bien déroulée.

  4. Déclarez un nouveau pointeur sur int que vous nommerez q. Faites pointer q sur i. A nouveau, faites-le sans utiliser directement la variable i. Affichez le contenu du pointeur q pour vérifier votre code.

  5. Déclarez une variable f de type float. Initialisez-la à $5$. Echangez ensuite son contenu avec celui de i, sans avoir recours à la variable i. Affichez les valeurs de i et f.

  6. Déclarez une nouvelle variable j de type int que vous initialisez à 8. Faites pointer q sur j. Maintenant, échangez les valeurs de i et j sans utiliser ni i, ni j.

    Affichez finalement les valeurs de i et j.

Exercice 2 - Fonctions et tableaux

  1. Ecrivez une fonction
          void affiche(int *T, int n)
    

    qui affiche à l'écran un tableau d'entiers T passé en argument. La longueur du tableau n est également passée en paramètre.

  2. Déclarez un tableau int T[10] dans la fonction main, et appelez la fonction que vous venez d'écrire pour l'afficher.

    Compilez votre programme et lancez-le. Que constatez-vous? Etes-vous surpris par les valeurs retournées par votre programme? Pouvez-vous les expliquer?

  3. Déclarez un deuxième tableau T2 de 8 éléments en utilisant la fonction new que vous avez vue en cours. Utilisez également la fonction écrite au point a) pour afficher le nouveau tableau. Remarquez-vous une différence entre les deux méthodes d'initialisation de tableaux?

    Remarque: N'oubliez pas qu'avec cette méthode vous devez libérer la mémoire que vous avez réservée à la fin du programme.

  4. Ecrivez une fonction alloue_tab qui alloue un nouveau tableau et retourne un pointeur sur ce tableau. La taille du nouveau tableau sera passée en paramètre.

  5. Ecrivez une fonction statistique qui calcule le minimum, le maximum et la moyenne d'un tableau d'entiers passé en paramètre.

    Remplissez un des trois tableaux de valeurs aléatoires et utilisez la fonction statistique pour afficher ses minimum, maximum et moyenne.

    Indice: Comme une fonction ne peut retourner qu'une seule valeur, le seul moyen de retourner à la fois le minimum, le maximum et la moyenne est d'ajouter trois arguments de type pointeurs. On dit alors que ces arguments sont passés par adresse ou par réference, car on passe leur adresse et non pas leur valeur. L'avantage de cette méthode est que toutes les modifications effectuées sur ces arguments à l'intérieur de la fonction seront également répercutées à l'extérieur.

Exercice 3 - Fonctions et pointeurs

Créez un nouveau programme, auquel vous ajouterez la fonction suivante:

    void fonction1(int *p, int v) {
      *p = v;
    }

  1. Effectuez un appel à fonction1 dans la fonction main. Faites-le de manière à comprendre ce que fait fonction1.
  2. Ecrivez une fonction
          void echange(int *p1, int *p2) {
          }
    

    qui échange le contenu de p1 et p2 sans utiliser d'affectation avec ces variables, mais en se servant de fonction1.

  3. Testez votre fonction echange en l'appelant dans main.

Exercice 4 - Loto ($\dag $)

Ecrivez un programme qui lit les résultats du tirage du Loto (6 numéros) et les stocke dans un tableau. Le programme lira ensuite les 6 numéros que vous avez joués.

La prochaine étape du programme consiste à déterminer combien de numéros corrects vous avez tirés. Pour cela, comparez les deux tableaux de numéros et stockez les numéros corrects dans un nouveau tableau dont la taille sera exactement le nombre de numéros corrects.

Finalement, le programme devra afficher vos numéros ainsi que les numéros corrects.

Remarque: n'écrivez pas tout le code en un seul bloc, mais modularisez-le en utilisant plusieurs fonctions. Idéalement, votre programme devrait contenir les fonctions suivantes: lire_numeros, compte_numeros_corrects, alloue_tableau, stocke_numeros_corrects et affiche_numeros.


Retour