title: Manipulation des flottants et des types structurés number: 5 —
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
É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.
Dans cet exercice, on considère une fonction polynôme du second degré à coefficients flottants (double
s) \(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).
Pour saisir au clavier un
double
dans la variablea
:scanf("%lf", &a);
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).
Pour cet exercice pensez à faire un main qui teste vos fonctions au fûr et à mesure.
On souhaite créer une librairie de manipulation de listes de lectures (playlists) de fichiers musicaux.
1) Chaque morceau (song) est identifié par :
path
)title
)artist
)album
)track
)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.
MAX_STR
valant 64.song
2) Écrire deux fonctions pour afficher les informations relatives à une chanson.
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).
On ne devrait jamais utiliser la fonction gets
(cf. man 3 gets
), cependant pour des raisons de clarté c’est elle qui est utilisé ici.
Cette fonction entraînant un maximum de warning (c’est vraiment mal de l’utiliser) vous pouvez rajouter -Wno-deprecated-declarations
dans la ligne de compilation pour les retirer.
Bonus: Remplacer
gets
parfgets
. 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.
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;
}
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 ?
MAX_SONG
valant 100.playlist
.4) Nous supposerons qu’une playlist est composée d’un tableau de chansons.
song_count()
qui, étant donnée une playlist, retourne le nombre de chansons.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 :
É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 variablea
:scanf("%f", &a);
Cet exercice est long mais complet, y passer un peu de temps à la maison peut être un bon moyen de pratiquer le C.
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).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.