TP2 - Écriture dans un fichier
Exercice 0 - Instructions
Le TP est noté de cette manière :
- 7/10 : Les 2 1ers exercices compilent.
- 8/10 : Critère du dessus + Les 2 1ers exercices fonctionnent.
- 9/10 : Critère du dessus + Le 3e exercice compile.
- 10/10 : Critère du dessus + Le 3e exercice fonctionne.
- 0/10 : Vous n'avez rien rendu, ou la même chose qu'un·e camarade.
Tous les fichiers seront à rendre au format votrelogin_nomexercice.c
Exemple pour l'exercice 1, avec le login de læ prof :
ppompeani_grep.c
Jetez d'abord un coup d'oeil à la correction du TP précédent.
L'objectif de ce TP est de lire et écrire dans des fichiers.
Exercice 1 - grep.c
On recode la commande grep
du terminal.
Reprendre l'exercice 2 du TP précédent. Vous pourrez partir de votre code, s'il fonctionne, ou de la correction.
Dans tous les cas, relisez bien la correction.
1.1. Recherche
Voici quelques fonctions standards de la librairie standard C :
FILE *fopen(const char *pathname, const char *mode); // man 3 fopen
int fclose(FILE *stream); // man 3 fclose
int fgetc(FILE *stream); // man 3 fgetc
char *fgets(char s[.size], int size, FILE *stream); // man 3 fgets
Laquelle des fonctions ci-dessus ressemble à la fonction char *readline(FILE *file);
de l'exercice ?
Lisez le manuel de ces fonctions dans un terminal (
man ...
) pour trouver la réponse.
1.2. Code
readline
supporte n'importe quelle taille de ligne, grâce à sesrealloc
de taille variable. C'est le comportement le plus flexible. C'est bien 👍.
Mais juste pour l'exercice, on va passer à un buffer de taille fixe.
Définissez une constante MAX_LINE_SIZE
à 1024.
// Au début du fichier
const int MAX_LINE_SIZE = 1024;
Supprimez la fonction readline
du code et utilisez la fonction standard à la place.
Des ajustements sont nécessaires. Aucun malloc
ou realloc
n'est attendu.
Exercice 2 - cp.c
On recode la commande cp
du terminal, qui copie un fichier.
Lisez le manuel pour la commande cp
: man cp
.
Question 2.1
À ton avis, est-ce qu'on va implémenter toutes les options que cp
propose ?
Réponse (cliquez)
Non. On ne va implémenter que le comportement de base, sans option.
Question 2.2
Quel est le premier argument de cp
?
Quel est le second argument ?
Réponse
Est-ce que tu as essayé de répondre à la question toi-même avant de voir la réponse ?
Non
RTFM
RTFM is an initialism and internet slang for the expression "read the fucking manual" – typically used to reply to a basic question where the answer is easily found in the documentation, user guide, owner's manual, man page, online help, internet forum, software documentation or FAQ.
Wikipedia
Oui
- Le premier argument est le fichier à copier.
- Le second argument est la destination vers laquelle on veut copier le fichier.
Exemple :
# Il n'y a qu'un fichier dans le dossier
$ ls
ppompeani_grep.c
# On copie le fichier
$ cp ppompeani_grep.c ppompeani_grep.c.backup
# Le fichier a été copié ! Magie !
$ ls
ppompeani_grep.c
ppompeani_grep.c.backup
Question 2.3
- Est-ce qu'on doit écrire le fichier à copier en lecture ou en écriture ?
- Est-ce qu'on doit écrire le nouveau fichier dans lequel on va copier en lecture ou en écriture ?
Question 2.4
Ok, on commence à coder.
Vérifier que 2 paramètres sont passés en argument, ou quitter avec un message d'erreur.
Question 2.5
Vérifier que le premier paramètre est accessible en lecture et que le second n'existe pas, ou quitter avec un message d'erreur.
On utilisera la fonction suivante :
#include<unistd.h>
int access(const char *pathname, int mode);
Lisez son manuel : man 2 access
.
Question 2.6
Ouvrir les deux fichiers, oui quitter avec un message d'erreur.
Question 2.7
Écrire la fonction suivante, qui copie le fichier file
vers copy
et retourne 1 en cas d'erreur, 0 en cas de succès.
int cp(FILE *file, FILE *copy);
On s'en fiche de lire le premier fichier ligne par ligne. On va le copier par tranches de 1024 octets.
On va donc utiliser un buffer de taille fixe, comme à l'exercice précédent.
On utilisera les fonctions suivantes :
// à appeler avec size = 1
size_t fread(
void ptr[restrict .size * .nmemb],
size_t size,
size_t nmemb,
FILE *stream);
size_t fwrite(
void ptr[restrict .size * .nmemb],
size_t size,
size_t nmemb,
FILE *stream);
// Pour savoir si on a réussi à lire le fichier jusqu'au bout
size_t feof(FILE *stream);
Tu as fini l'exercice 2 ? Bravo ! Dernier exercice :
Exercice 3 - loremipsum.c
Écrire un programme qui prend 3 arguments :
- Un fichier qui contient des mots, un par ligne.
- Un nombre
N
de mots à écrire - Un fichier dans lequel écrire
N
mots aléatoires.
Question 3.1
Vérifier le nombre d'arguments, que le premier argument est accessible en lecture, que le second argument est un nombre, et que le 3e argument n'existe pas.
On utilisera la fonction suivante pour convertir le second argument :
int atoi(const char *nptr);
Lisez son manuel si besoin.
Question 3.2
Écrire la fonction suivante :
char **words(FILE *file, int *length);
Qui retourne un tableau de chaînes de caractères, chaque item est une ligne du fichier file
.
La fonction mettra à jour length
pour indiquer combien de lignes ont été lues.
On pourra utiliser
fgets
, et partir du principe qu'une ligne fait moins de 100 caractères.
Appelez-là dans votre fonction main
.
Question 3.3
Écrire la fonction suivante :
int lorem(FILE *file, char **words, int length, int nbwords);
Qui prend en argument un fichier file
dans lequel elle va écrire nbwords
mots aléatoires du tableau words
.
Elle retourne à la ligne tous les 10 mots, et à la fin du fichier.
On pourra utiliser la fonction
fprintf
, oufwrite
Incorporez-là 🥗 au main
et vérifiez que votre programme fonctionne correctement.
Question 3.4
Mettez à jour votre programme pour que le 3e argument soit optionnel.
S'il n'est pas donné, on affichera le lorem ipsum sur la sortie standard au lieu de l'écrire dans un fichier.
Mais la sortie standard est un fichier, du point de vue de votre programme !
C'est le fichier numéro 1. On vient de voir en cours ce que ça veut dire.
Pour manipuler la sortie standard comme un fichier, plutôt qu'avec des printf
, il nous faut une fonction qui va nous retourner un FILE *
:
FILE *fdopen(int numero_du_fichier, const char *mode);
Lisez son manuel, bien entendu. On utilisera le mode
"a"
.
Question 3.5 bonus
Si le programme affiche sur la sortie standard, et pas dans un fichier, on veut afficher des couleurs !
Chaque mot devra être affiché aléatoirement en blanc, rouge, vert, jaune, bleu foncé, violet ou bleu clair.
Ces couleurs ne sont pas choisies au hasard. Cherche sur le web comment afficher des couleurs dans un terminal en C.
Vous pourrez ajouter un paramètre à
lorem
pour lui indiquer s'il faut afficher des couleurs ou pas