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

Remarques

Pour chaque fonction que vous devez écrire, commencez par réfléchir à son en-tête:

Exercice 1 - Insertion dans un tableau(*)

Dans cet exercice vous allez apprendre à insérer une nouvelle valeur au bon endroit dans un tableau trié.

Le programme ci-dessous crée un tableau d'entier triés par ordre croissant. Seuls nb_element-1 éléments sont insérés dans le tableau (la derniière case vaut $0$), de telle manière qu'il reste une place de libre pour un nouvel élement.

Copiez le programme dans Emacs et remplacez les points de suspension par du code demandant à l'utilisateur d'entrer un nombre à insérer dans le tableau. Le programme devra ensuite insérer le nombre dans le tableau, de manière à ce qu'il soit toujours correctement trié par ordre croissant.

Finalement, votre programme devra afficher à l'écran le tableau avec le nouvel élément.

Indice: commencez par identifier la place du nouvel élément dans le tableau, puis déplacez les éléments à sa droite d'une case vers la droite, afin de libérer une position.

      #include <iostream>
      #include <time.h>

      using namespace std;
      
      int main(int argc, char **argv) {
        const int nb_elements = 15;
        int tableau[nb_elements];

        srand(time(0));
        tableau[0] = rand() % 50;

        for (int i=1; i<nb_elements-1; i++)
          tableau[i] = tableau[i-1] + (rand() % 20);
        tableau[nb_elements-1] = 0;

        cout << "Tableau initial:" << endl;
        for (int i=0; i<nb_elements; i++)
          cout << tableau[i] << " ";
        cout << endl;

        ...

        return 0;
      }

Exercice 2 - Fonctions simples

Pour tester les fonctions suivantes, appelez-les dans la fonction main de votre programme:

  1. Ecrivez une fonction min2 qui reçoit deux arguments de type float et retourne le plus petit d'entre eux. Le type de retour devra donc être float.
  2. Ecrivez une fonction min3 qui prend trois arguments de type int 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 ?
  3. Ecrivez une fonction arrondi qui prend un argument de type float et retourne l'argument arrondi à deux décimales.
  4. Ecrivez une fonction traduction qui prend en argument un entier entre 0 et 6 et l'affiche à l'écran en toutes lettres (zero, un, ..., six). Quelles sont les différences entre cette fonction et les précédentes ?

Exercice 3 - Sapin

  1. Ecrivez une fonction qui affiche un triangle d'étoiles, et qui prend en paramètre le nombre de lignes du triangle:
            *
           ***
          *****
    

  2. Utilisez cette fonction pour afficher un sapin:
           *
          ***
           *
          ***
         *****
           *
          ***
         *****
        *******
           *
    

    Vous devrez certainement modifier un peu la fonction écrite au point 1) afin que votre sapin ressemble à celui dessiné ci-dessus.

Exercice 4 - Modularisation

  1. Le code ci-dessous convertit un nombre décimal en binaire, l'affiche et fait la conversion inverse. Recopiez ce code dans un buffer d'Emacs, et essayez de le comprendre. Vous pouvez ensuite le compiler - il devrait fonctionner sans problème - et le tester.

    #include <iostream>
    
    using namespace std;
    
    int main(int argc, char **argv) {
      const int max_bits = 10;
      int decimal, binaire, original, n, bits;
      long puissance2, puissance10;
    
      cout << "Entrez un nombre entier: ";
      cin >> decimal;
    
      // calcul du nombre de bits
      n = decimal;
      bits = 0;
      while (n > 0) {
        bits++;
        n /= 2;
      }
    
      cout << decimal << " a " << bits << " bits." << endl;
      if (bits > 10) {
        cout << "Nous ne pouvons pas convertir de nombres plus grands que " 
    	 << max_bits << " bits." << endl;
        return 0;
      }
    
      // conversion en binaire
      n = decimal;
      binaire = 0;
      for (int i=bits-1; i>=0; i--) {
        puissance2 = 1;
        for (int j=0; j<i; j++)
          puissance2 *= 2;
    
        puissance10 = 1;
        for (int j=0; j<i; j++)
          puissance10 *= 10;
        
        if (n / puissance2 > 0) {
          n = n - puissance2;
          binaire += puissance10;
        }
      }
    
      cout << decimal << " vaut '" << binaire << "' en binaire." << endl;
      
      // calcul du nombre de bits
      n = binaire;
      bits = 0;
      while (n > 0) {
        bits++;
        n /= 10;
      }
    
      cout << decimal << " a " << bits << " bits." << endl;
    
      // conversion de binaire en decimal
      original = 0;
      n = binaire;
      for (int i=bits-1; i>=0; i--) {
        puissance2 = 1;
        for (int j=0; j<i; j++)
          puissance2 *= 2;
    
        puissance10 = 1;
        for (int j=0; j<i; j++)
          puissance10 *= 10;
        
        if (n / puissance10 > 0) {
          n = n - puissance10;
          original += puissance2;
        }
      }
      
      cout << "Nombre original: " << original << endl;
    
      return 0;
    }
    

  2. Bien qu'il fonctionne parfaitement, ce code n'est pas très simple à relire. Notamment, certains morceaux de code sont répétés presque tel quel à plusieurs endroits. Le but de cet exercice est de modifier le code donné afin de le rendre plus simple à comprendre en y ajoutant des fonctions.

    Remarquez que le code qui calcule la puissance d'un nombre est répété à plusieurs reprises. Ecrivez une fonction

          int puissance(int a, int b) {
          }
    

    qui calcule $x=a^b$ et retourne le résultat. Une fois la fonction écrite, remplacez les bouts de code de main qui calculent une puissance par un appel à la fonction puissance. Par exemple,

        puissance2 = 1;
        for (int j=0; j<i; j++)
          puissance2 *= 2;
    

    peut être remplacé par

          puissance2 = puissance(2, j);
    

  3. Observez attentivement les deux bouts de code permettant de calculer le nombre de bits (lignes 14 à 19 et lignes 50 à 55). Etant donné leur similarité, il est facile d'écrire une fonction générique permettant d'effectuer les deux opérations. Remplacez ce code par une fonction de la forme:
        int log_entier(int n, int base) {
          ...
        }
    

  4. Finalement, vous remarquerez que le code pour effectuer une conversion en binaire est également très similaire à celui faisant la conversion en décimal. Ici aussi, remplacez le code correspondant par une fonction appropriée.

    Le code ainsi généré devrait être plus compact et plus facile à comprendre au premier abord.

Exercice 5 - Beau sapin($\small\dag $)

Le sapin généré à l'exercice 3 n'est pas très joli. Il est bien trop allongé et ne ressemble pas beaucoup à un vrai sapin. Le but de cet exercice est de reprendre le code de l'exercice 3 et de l'adapter afin d'afficher le graphique ci-dessous:

       *
      ***
     *****  
      ***
     *****
    *******
     *****
    *******
   *********
      |||

Comme pour l'exercice 3, créez une fonction qui permet de dessiner un étage du sapin.


Retour