[TP 7 : Fichiers ](https://mybinder.org/v2/gh/fortierq/binder-mp2i/main?urlpath=git-pull%3Frepo%3Dhttps%253A%252F%252Fgithub.com%252Fmp2i-info%252Fmp2i-info.github.io%26urlpath%3Dlab%252Ftree%252Fmp2i-info.github.io%252F4_c%252Ftp%252F8_sudoku.ipynb%26branch%3Dmain) 

Fonctions¶
Un fichier en C se manipule à travers un objet de type FILE
, qui est une structure contenant les informations sur le fichier.
Dans ce TP, nous allons utiliser les 3 fonctions suivantes pour manipuler des fichiers en C. La documentation suivante est une version simplifiée de https://en.cppreference.com/w/. N'hésitez pas à regarder les exemples.
fopen
FILE * fopen ( const char * filename, const char * mode );
Opens the file whose name is specified in the parameter filename and associates it with a stream that can be identified in future operations by the FILE pointer returned.
filename
: C string containing the name of the file to be opened.mode
: C string containing a file access mode. It can be:"r"
(read): Open file for input operations. The file must exist.
"w"
(write): Create an empty file for output operations. If a file with the same name already exists, its contents are discarded and the file is treated as a new empty file."a"
(append): Open file for output at the end of a file. Output operations always write data at the end of the file, expanding it. The file is created if it does not exist.
fclose
int fclose ( FILE * stream );
Closes the file associated with the stream and disassociates it.
stream
: Pointer to a FILE object that specifies the stream to be closed.
fscanf
int fscanf ( FILE * stream, const char * format, ... );
Reads data from the stream and stores them according to the parameter format into the locations pointed by the additional arguments. Return EOF ($-1$) if end of file is reached.
stream
: Pointer to a FILE object that identifies the input stream to read data from.
format
: C string that contains a sequence of characters that control how characters extracted from the stream are treated. A format specifier for fscanf can follow this prototype:%[width]specifier
, where specifier can be%d
for integers or%s
for strings andwidth
is the maximum number of characters to be read.
... (additional arguments)
: Depending on the format string, the function may expect a sequence of additional arguments, each containing a pointer to allocated storage where the interpretation of the extracted characters is stored with the appropriate type.
fprintf
int fprintf ( FILE * stream, const char * format, ... );
Writes the C string pointed by format to the stream. If format includes format specifiers (subsequences beginning with %), the additional arguments following format are formatted and inserted in the resulting string replacing their respective specifiers.
...
signifie que la fonction peut accepter un nombre quelconque d'arguments.
Codage de César¶
Exercice
Écrire une fonction void encrypt(char* s, int k)
décalant les caractères de s
de k
, dans le code ASCII. Exemple :
char s[] = "mp2i";
encrypt(s, 3);
printf("%s", s); // doit afficher ps5l
Exercice
Écrire une fonction void encrypt_file(const char* filename, int k)
chiffrant le contenu du fichier dont le chemin est filename
, en utilisant le codage de César. Il faut donc :
- Lire le contenu du fichier dans une chaîne de caractères
- Appliquer
encrypt
sur la chaîne de caractères - Écrire la chaîne de caractères chiffrée dans le fichier
On pourra compléter le code suivant (qui suppose qu'il y a au plus 50 caractères dans le fichier) :
void encrypt_file(const char* filename, int k) {
FILE *f = fopen(filename, "r");
if(!f) { // si f = 0, il y a eu une erreur
printf("Le fichier n'a pas pu être ouvert");
return;
}
char s[50];
fscanf(f, "%50s", s); // lit au plus 50 charactères, stockés dans s
fclose(f);
// à compléter
}
Remarque : Si vous testez sur Jupyter, il faut fermer et ouvrir à nouveau le fichier pour voir son nouveau contenu.
Exercice
Exercice (optionnel) : Modifier la fonction précédente pour gérer des fichiers de taille arbitraire (avec un nombre quelconque de caractères).
Exercice
Écrire une fonction void decrypt_file(const char* filename, int k)
pour déchiffrer un fichier chiffré avec le codage de César.
Décimales de $\pi$¶
Le fichier pi.txt
, qui est dans le même dossier que ce notebook, contient 10 millions de décimales de $\pi$ :
! head -c50 pi10M.txt
14159265358979323846264338327950288419716939937510
Exercice
Écrire une fonction int nth(int)
telle que nth(n)
renvoie le n
ième chiffre de $\pi$ après la virgule. On pourra utiliser fscanf(f, "%1d", &d);
qui permet de lire un chiffre dans f
.
Vérifier que le 939ème chiffre de $\pi$ est un 7.
Exercice
Calculer, dans un tableau de taille 10, le nombre d'apparitions de chaque chiffre de $\pi$. Vérifier que les chiffres ont l'air uniformément répartis entre 0 et 9.
Exercice
Il est conjecturé que $\pi$ est un nombre univers, c'est-à-dire qu'on peut trouver à l'intérieur de ses décimales toute suite finie de chiffres. Par exemple, on peut trouver le nombre $9265$ dans $\pi$ puisque $\pi = 3.1415\mathbf{9265}...$.
Écrire une fonction int pos(int)
renvoyant la position de la première position d'un nombre dans les décimales de $\pi$. Si on arrive à la fin du fichier des décimales, on renverra $-1$.
Application : Chercher la position d'apparition de votre date d'anniversaire (sous la forme jjmmaa, par exemple $251200$ pour le $25/12/2000$) dans les décimales de $\pi$.