TP "bibliothèque de chansons"

Transcription

TP "bibliothèque de chansons"
Soutien info 2A
TP Bibliothèque de Chansons
notions : structures, listes chaı̂nées, fichiers
Tous les exercices de ce TP construisent pas à pas un programme complet. Il est indispensable
de créer et utiliser un Makefile.
On veut réaliser une application de gestion de liste de chansons.
Les chansons seront chargées depuis un fichier texte dans lequel chaque chanson est définie
par 4 éléments :
— l’identifiant de la chanson, unique pour chaque chanson : un entier
— son titre : une chaı̂ne de caractère de longueur quelconque
— son (ses) auteur(s) : idem
— le format du fichier de la chanson ("WAV" ou "MP3" par exemple) : une chaı̂ne de 3 caractères
Exercice 1
Structure de donnée pour représenter une chanson
1. Proposez une structure de données pour représenter une chanson (unique). Implantez
cette structure de donnée dans un module chanson (chanson.h / chanson.c)
2. Ajoutez une fonction affichant une chanson passée en paramètre.
3. Dans un fichier main.c, écrivez un programme principal qui construit une variable chanson
depuis le code et l’affiche à l’écran.
Exercice 2
Parsing de chanson
1. Ajoutez au module chanson une fonction ... parseChanson(...) qui prend en paramètre
une chaı̂ne de caractères encodant toutes les informations d’une chanson, extrait les informations de la chaı̂ne et construit et retourne une variable de type ‘chanson” (question
précédente).
On supposera que les informations sont encodées dans la chaı̂ne au moyen du format
suivant :
<rang>\t<format>\t<titre chanson>\t<auteur chanson>
où \t est le caractère représentant une tabulation.
Exemples de chaı̂nes valides :
4420 AIF Ready to Start
4 MP3 changer le monde
Arcade Fire
Jeune UMP
Choisissez le prototype de la fonction de telle sorte qu’elle puisse retourner une erreur si
la chaı̂ne ne respecte pas le format attendu.
Pour cette question, il faudra utiliser les fonctions :
1
— char *strtok(char *str, const char *delim) pour parcourir la ligne lue mot par mot
— int sscanf(const char *str, const char *format, ...) ou int atoi(const char *nptr) pour
convertir une chaı̂ne en nombre entier
— char *strdup(const char *s) pour dupliquer une chaı̂ne
2. Modifiez le fichier main.c pour tester votre fonction ... parseChanson(...) : lire une chanson
au clavier (au moyen de la fonction char *gets(char *s, int size, FILE *stream)), construire
une variable chanson et l’afficher à l’écran.
Exercice 3 Fichier de chansons
On dispose d’un fichier texte de chansons (disponible ici), dont voici un extrait :
3212
6365
2408
4142
...
MP3
WAV
MP3
AIF
Take On Me
a ha
Mysterious Ways
Angelique Kidjo
Rolling in the Deep
ADELE
Lovesong
ADELE
Chaque ligne contient le rang de la chanson, son titre et son auteur.
! ! !Attention : ce fichier contient quelques lignes incorrectes, qui doivent être ignorées :
— des lignes vides
— des lignes ne commençant pas par un entier.
Toutes les erreurs possibles figurent entre les lignes 5 et 9 du fichier. Ces lignes peuvent être
supprimées dans le premier temps de l’exercice si elles vous genent pour avancer.
Le but de cet exercice est d’écrire une fonction qui prend en paramètre le nom du fichier, lit
une à une les chansons du fichier (au moyen de la fonction char *fgets(char *s, int size, FILE
*stream)) et affiche les fonctions sur la sortie standard.
1. Dans un nouveau module “fichier.h” (fichier.h / fichier.c), écrivez une fonction ... lire_fichier_musique
(char * chemin_fichier, int *p_nb) qui lit une à une les chansons dans le fichier nommé
chemin fichier, stocke le nombre de chansons lues dans *p_nb et affiche les fonctions sur
la sortie standard.
2. Modifiez le main pour qu’il affiche la liste chargée depuis le fichier.
3. optionnel - Écrivez une fonction qui affiche les chansons d’un artiste donné.
Exercice 4 Liste chaı̂née de chanson
On veut pouvoir stocker en mémoire un nombre quelconque de chansons dans une “bibliothèque”. Le nombre de chanson est inconnu à l’avance et il convient de pouvoir en ajouter
“indéfiniement”. On utilisera donc des listes chaı̂nées...
1. Dans un module ”liste” (liste.h / liste.c), définissez le type ”liste de chansons”.
2. Dotez ce module des principales fonctions implantant le type abstrait ”liste” : estVide(),
ajout_tete(), supp_tete(), visualiser(), detruire_liste().
3. Modifiez la fonction lire_fichier_musique pour retourner une liste de chansons.
4. Modifiez le programme principal pour tester vos listes, pour que par exemple il :
— Crée une liste de chansons
— lit un fichier de chansons en les rangeant dans une liste et affiche la liste
— Supprime les deux chansons en tête de la liste et affiche la liste
— Demande à l’utilisateur une nouvelle chanson et affiche la liste
— Supprime deux chansons et affiche la liste
— Demande à l’utilisateur une nouvelle chanson et affiche la liste
— Détruit la liste puis l’affiche
2
5. Ajoutez une fonction ... rechercher_par_titre(...) qui prend en paramètre une liste de
chansons et le titre d’une chanson, et retourne le maillon de la liste contenant la chanson
nommée titre, ou NULL si cette chanson n’existe pas.
Modifiez le programme principal pour tester cette fonction.
Rappel : pour comparer deux chaı̂nes de caractères, utiliser int strcmp(const char *s1,
const char *s2);.
Exercice 5 Liste triée
On veut pouvoir trier la liste des chansons par identifiant. Pour cela, ajoutez au module liste
une fonction ... trier_par_identifiant(...) qui prend en paramètre une liste non triée et
retourne une nouvelle liste triée.
Vous implanterez l’algorithme de tri dit ”par insertion” décrit ci-dessous :
Creer une liste vide pour recevoir les chansons triees
Pour chaque chanson de la liste non triee passee en parametre :
trouver la place (le maillon) ou inserer la chanson dans la liste triee
inserer la chanson au bon endroit dans la liste triee
finpour
retourner la liste triee
Exercice 6 Liste triée - pointeur de fonction
Copiez/collez la fonction ... trier_par_identifiant(...) dans une nouvelle fonction ...
trier_titre(...) qui retourne une liste triée par titre de chanson. Il vous faudra utiliser la
fonction int strcmp(const char *s1, const char *s2);.
Vous remarquerez que, entre les deux fonctions de tri, seul la méthode utilisée pour comparer
deux chansons change. L’algorithme en lui même reste le même. Si il y avait moyen d’indiquer
à l’algorithme quel procédé de comparaison (quelle fonction de comparaison ou comparateur )
utiliser, il deviendrait possible d’avoir une fonction de tri de liste générique. Apparait ici l’un
des intérêts des pointeurs de fonction.
1. Lisez attentivement le cours sur les pointeurs de fonctions, page 110-113 du polycopié
”Polycop PET semestre 2” disponible sur le site web du soutien.
2. Ecrivez une fonction int compare_identifiant( <chanson1>, <chanson2>) qui prend deux chansons en paramètre et retourne un entier positif, nul ou négatif suivant que la chanson1 est
”plus grande”, ”égale” ou ”plus petite” que la chanson2.
3. Ecrivez une fonction ... tri_generique( ..., <comparateur) qui prend, en paramètre un
pointeur de fonction ”comparateur” de même prototype que compare_identifiant( ).
4. Modifiez le main pour trier les chansons par rang au moyen de la nouvelle fonction de tri.
Exercice 7 Playlist de chansons
Une playlist de chanson est une série de chansons de la bibliothèque.
Un fichier playlist est un fichier texte qui comprend les identifiants entiers des chansons de la
playlist.
Un fichier exemple est disponible ici.
Dans un nouveau module “playlist.h” (playlist.h playlist.c), écrivez une fonction ... lire_fichier_playlist
(... qui affiche dans le terminal les chansons composant la playlist.
Cette fonction prend en paramètre le nom d’un fichier playlist ainsi qu’une bibliothèque de
chansons (c’est à dire, dans notre programme, une liste chaı̂née de chansons) et :
3
— ouvre le fichier playlist
— affiche le nombre de chansons référencées dans le fichier
— affiche dans le Terminal le titre de chaque chanson de la playlist
Il faut, pour cela, rechercher dans la bibliothèque les chansons de la playlist, à partir de
leur identifiant.
On ajoutera donc avantageusement dans le module “liste” une fonction ... rechercher_par_identifiant
(...) qui prend en paramètre la bibliothèque (c’est à dire une liste de chansons) et un
identifiant de chanson, et retourne le maillon de la liste contenant la chanson nommée
titre (ou NULL si cette chanson n’existe pas).
Exercice 8 Liste chainée pour stocker une playlist de chansons
Pour stocker une playlist en mémoire, on décide d’avoir recours à une liste chaı̂née de pointeurs
sur des chansons : la bibliothèque reste, comme précédemment, une liste chaı̂née de “structure
chanson” qui contient toutes les chansons, et la playlist pointe dans les chansons de cette
bibliothèque.
1. À votre avis, pourquoi fait-on ce choix ? Pourquoi ne stocke-t-on pas directement les
chansons dans la playlist ?
2. Dans un module liste playlist.h / liste playlist.c, définissez le type ”liste de
pointeurs sur chanson”.
3. Dotez ce module des principales fonctions implantant le type abstrait liste : pl_estVide()
, pl_ajout_tete(), pl_supp_tete(), pl_visualiser(), pl_detruire_liste() - et d’autres, pourquoi pas par exemple des fonctions permettant de trier une playlist...
Dans le nom de ces fonctions, notez l’usage du préfixe “pl ”, qui permet de distinguer ces
fonctions de celles du module “liste” qui manipulent des listes de chansons.
Vous pouvez remarquer que le corps de ces fonctions sera très proche du corps des fonctions
du module “liste” ; plutôt que de tout écrire, il peut être intéressant de copier/coller puis
adapter ces fonctions du module “liste”...
4. Modifiez la fonction ... lire_fichier_playlist(... de l’exercice précédent pour qu’elle retourne une liste chaı̂née représentant la playlist.
Modifiez le programme principal pour afficher les chansons de la playlist.
Exercice 9 Et ensuite...
Maintenant que l’ossature est prête, vous pouvez à loisir étendre votre programme de gestion
de bibliothèque de chansons...
Par exemple :
— ajouter au module “liste” une fonctionnalité retournant une “playlist” composée de toutes
les chansons d’un artiste donné
— ajouter des fonctionnalités permettant de changer l’ordre d’une chanson dans une “playlist”
— merger deux playlist
— stocker plusieurs playlist en mémoire
— ajouter un menu en ligne de commande
— ... etc ! ...
4

Documents pareils