TP2 - Écriture dans un fichier

Exercice 0 - Instructions

Le TP est noté de cette manière :

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 à ses realloc 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.

Aide : Arrays of constant known size


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

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 :

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.

How to generate a random int in C?

On pourra utiliser la fonction fprintf, ou fwrite

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