title: Manipulation des flottants et des types structurés number: 5 —

Manipulation des flottants et des types structurés.

Note : les fonctions mathématiques se trouvent dans l’include math.h. Lorsqu’on utilise ces fonctions, il faut aussi inclure la librairie mathématique dans l’exécutable final, ceci se fait au moyen de la directive de compilation -lm. Pour des raisons complexes, il faut que cette directive soit à la fin de la ligne de commande.

cc -o monprogramme monprogramme.c -lm

Exercice 1

Écrire une fonction calculant le minimum et le maximum d’un tableau d’entiers de taille n (et pas 2 fonctions !!!). Quelles sont les alternatives pour retourner le résultat.

Exercice 2

Dans cet exercice, on considère une fonction polynôme du second degré à coefficients flottants (doubles) \(f(x)= ax^2 + bx + c\) . Pour tester vos fonctions, les coefficients \(a\), \(b\) et \(c\) du polynôme seront passés en paramètres de votre programme (ligne de commande).

  • Écrivez une fonction qui calcule \(f(x)\) pour une valeur \(x\). Cette valeur sera lue depuis la ligne de commande. Bonus : si cette valeur n’est pas spécifiée, la demander à l’utilisateur.
  • Écrivez une fonction qui calcule les racines de \(f\) dans \(\mathcal{R}\).
  • Que faudrait-il faire pour calculer les racines de f dans \(\mathcal{C}\) Bonus : Le faire.

Pour saisir au clavier un double dans la variable a: scanf("%lf", &a);

Exercice 3

Extrait d’une annale. Il vous est demander de réaliser tout l’exercice SANS allocation dynamique ! (oui c’est possible … c’est d’ailleurs un bon moyen de comprendre ce que l’on manipule).

On souhaite créer une librairie de manipulation de listes de lectures (playlists) de fichiers musicaux.

1) Chaque morceau (song) est identifié par :

  • Un nom de fichier (obligatoire) (path)
  • Un nom de titre (title)
  • Un nom d’artiste (artist)
  • Un nom d’album (album)
  • Un numéro de piste (track)
  • Un genre (ne considérer que : ROCK, POP, JAZZ, HIP_HOP) (kind)

Tous les champs peuvent être omis, imaginez un fichier sans aucun tag. Pensez a définir des constantes pour les dimensions des tableaux.

  • Définir la constante MAX_STR valant 64.
  • Définir la structure song

2) Écrire deux fonctions pour afficher les informations relatives à une chanson.

  • La première ne doit afficher qu’une ligne avec les informations importantes (titre - album - artiste).
  • La seconde affichera toutes les informations disponibles sur plusieurs lignes en texte lisible (c’est-à-dire sans nombre inutile … typiquement le genre).
  • L’indication Unknown remplacera une information manquante. Il est vivement conseillé de faire des fonctions auxiliaires.

Commencez par n’en faire qu’une des deux.

Pour la saisie des informations vous pourrez vous servir de la fonction scan_song qui vous est fournie. Vous trouverez aussi un main d’exemple (offre non contractuelle, vous pouvez bien entendu l’adapter).

Bonus: Remplacer gets par fgets. Il conviendra de faire une fonction auxiliaire qui traitera le saut de ligne final et qui mangera ce qui ne tient pas dans le buffer.

Saisir une chanson depuis le clavier
int scan_song(struct song *song)
{
  struct song s = {};
  char buffer[12];
  if (!gets(s.path) || strlen(s.path) == 0)
    return 0;
  if (!gets(s.title)) {
  } else if (!gets(s.artist)) {
  } else if (!gets(s.album)) {
  } else if (gets(buffer)) {
    int n = atoi(buffer);
    s.track = n;
    if (gets(buffer)) {
        n = atoi(buffer);
        s.kind = n;
    }
  }
  *song = s;
  return 1;
}
Un exemple de `main`
int main(int argc, char *argv[])
{
    struct song some_song;
    while (scan_song(&some_song)) {
        print_song(some_song);
    }
    return 0;
}

3) Nous appellerons playlist une suite de morceaux. Il existe plusieurs moyens pratiques de représenter une telle liste. Par exemple, on peut utiliser des listes chainées, un tableau ou une structure contenant un tableau. La première solution est présenté dans l’Exercice Structures et pointeurs. En supposant que le nombre maximum de chansons est connu d’avance (MAX_SONG), les deux dernières solutions sont plus pratiques. Quels sont leurs avantages respectifs ?

  • Définir la constante MAX_SONG valant 100.
  • Définir la structure playlist.

4) Nous supposerons qu’une playlist est composée d’un tableau de chansons.

  • Comment connaître le nombre de chansons dans la playlist ?
  • Écrire la fonction song_count() qui, étant donnée une playlist, retourne le nombre de chansons.
  • Écrire la fonction init_list().
  • Écrire la fonction append_song() qui ajoute une chanson à la fin de la liste.

5) À partir d’une playlist nous voulons pouvoir faire des sélections par style musical. Quelle structure peut représenter de telles sous-listes ? Écrire une fonction qui, étant donné une playlist et un genre de musique, retourne la playlist uniquement constituée de ce genre.

6) De la même manière nous aimerions pouvoir construire une liste ne contenant qu’un nom d’artiste particulier. Écrire une telle fonction.

7) À partir d’une playlist, nous aimerions pouvoir la mélanger en place (c’est à dire sans en créer une nouvelle). L’algorithme proposé est le suivant :

  • Pour chaque chanson de la liste
  • Choisir une chanson aléatoirement n’étant pas avant
  • Les permuter.
  • Écrire une telle fonction.

Exercice 4

Trop long par rapport à son intérêt

Écrivez une fonction saisir_point() qui récupère avec scanf() l’abscisse et l’ordonnée flottantes (float) d’un point dans le plan cartésien. Proposez une solution pour que ces coordonnées soient communiquées à la fonction appelante.

Écrivez une fonction qui prend en paramètres les coordonnées de deux points \(A\) et \(B\) et retourne la longueur du segment \([AB]\).

Utilisez les fonctions précédemment définies pour écrire un programme qui demande à l’utilisateur de saisir les coordonnées de trois points \(A\), \(B\) et \(C\) et indique si le triangle ABC est isocèle et/ou rectangle ou équilatéral ou scalène (ni isocèle ni équilatéral).

Testez votre programme avec les points \((0, 0)\), \((0, 1)\) et \((1, 1)\). Que remarquez vous ? Corrigez le problème en introduisant une constante EPSILON pour comparer deux flottants.

Pour saisir au clavier un float dans la variable a: scanf("%f", &a);

Exercice 5

Jouer à la bataille.

Cet exercice est long mais complet, y passer un peu de temps à la maison peut être un bon moyen de pratiquer le C.

  • Modéliser un jeu de carte (32 ou 54 au choix). On pourra utiliser la même “structure” pour représenter les paquets.
  • Faire une fonction qui distribue 2 paquets (sans recouvrement). Pour cela utiliser la fonction rand() (Cette fonction donne de mauvais nombre aléatoires, elle est cependant facile à utiliser). L’algorithme est le suivant: tirer une carte parmi les restantes, remplacer cette carte par la dernière du paquet (et donc réduire votre jeu de carte d’une carte).
  • Faire une fonction pour comparer deux cartes (1 et -1 pour dire qui est la plus forte, 0 en cas d’égalité).
  • Faire la boucle de jeu :
    • Jouer une carte de chaque jeu (au hasard, la première ou la dernière).
      • Celui qui gagne les récupère.
      • En cas d’égalité, défausser une carte de chaque jeu puis tirer une nouvelle carte. Attention cette partie est récursive (une bataille sur une bataille sur une bataille, etc, peut arriver).
      • Le premier paquet vide perd.
  • Faire jouer \(n\) parties et regarder que le hasard et bien fait :).
  • Retentez l’expérience et ce rendre compte que le hasard, n’est pas si bien fait ? Pourquoi ?

Si vous vous ennuyez, transformer ce jeu en bataille “ouverte” avec UN joueur humain. Il vous faudra afficher le jeu de carte à l’écran et demander à l’utilisateur celle qu’il veut jouer.