Exercice 1.
Utiliser les primitives systèmes pour écrire un
programme C qui affiche le contenu d'un fichier de caractères (dont le
nom est donné en argument) mais en convertissant les lettres en
majuscules. La conversion de minuscule en majuscule peut se faire à
l'aide de la fonction de bibliothèque toupper()
. Proposer
une version où la lecture dans le fichier et l'écriture sur la sortie
standard se font par bloc de 256 octets. Exemple d'exécution :
$ cat toto
Bonjour!
$ ./a.out toto
BONJOUR!
$
Exercice 2.
Ecrire deux programmes C : le premier programme crée
un fichier binaire contenant une liste de 10 entiers (de type int
).
On utilisera la fonction de bibliothèque scanf()
avec le
format %d
pour saisir les entiers au clavier. Le deuxième
programme affiche la liste des entiers stockés dans le fichier. On
utilisera la fonction de bibliothèque printf()
avec le
format %d
pour afficher les entiers à l'écran.
Exercice 3.
Utiliser les primitives système pour écrire un
programme C qui crée un fichier d'une certaine taille (peu importe le
contenu). Le nom du fichier et la taille en octets sont donnés sur la
ligne de commande. Exemple d'exécution :
$ ./a.out toto 2000
$ ls -l toto
-rw-r--r-- 1 violard staff 2000 9 sep 14:52 toto
$
Exercice 4.
Le but de cet exercice est de réaliser la fonction
getchar()
de la bibliothèque standard des E/S en utilisant la primitive
système
read()
: On souhaite définir une fonction
getchar2()
qui a exactement le même profil que
getchar()
et
se comporte exactement de la même façon. On procédera de la manière
suivante :
- 1ère étape) Bien comprendre le fonctionnement de la fonction
getchar()
.
Faire man 3 getchar
pour obtenir quelques
informations sur cette fonction. Compiler et exécuter ce programme test-getchar.c
. Que fait
ce programme ? Que se passe t-il lorsqu'on appuie sur Ctrl+D
pendant l'exécution du programme ? Utiliser ce programme pour copier
un fichier dans un autre (on redirigera l'entrée et la sortie
standard en utilisant les symboles <
et >
sur la ligne de commande).
- 2ème étape) Réaliser une version non bufférisée.
Substituer dans le programme l'identificateur
getchar
par l'identificateur getchar2
et ajouter au programme
votre définition de la fonction getchar2()
de façon à
ce que le programme se comporte toujours de la même façon. Utiliser
la primitive read()
avec 1 comme 3ème argument. Dans
cette version, chaque appel à la fonction getchar2()
provoquera un appel à read()
et la lecture d'1 octet
sur l'entrée standard.
- 3ème étape) Réaliser une version bufférisée. Modifier
votre définition de la fonction
getchar2()
de façon à
utiliser la primitive read()
avec 1024 comme 3ème
argument. Dans cette version, un appel à read()
lit
jusqu'à 1024 octets en avance : les octets sont mémorisés dans une
liste implémentée par un tableau
de taille 1024. Le
tableau est une variable locale à la fonction getchar2()
et doit être déclaré static
de façon à ce que les
données mémorisées dans le tableau ne soient pas effacées au retour
de la fonction. A chaque appel à la fonction getchar2()
,
on teste si la liste est vide, si c'est le cas, on fait un appel à read()
pour la remplir. Si elle n'est pas vide, on enlève le premier
élément de la liste et on retourne cet élement.
Exercice 5.
Ecrire un programme C qui affiche en clair le type du
fichier demandé (répertoire, fichier ordinaire, etc...), ainsi que ses
permissions (lecture, écriture et exécution sous la même forme que la
commande ls
-l
). On utilisera la primitive stat()
.
Exemple d'exécution :
$ ./a.out toto
toto type : fichier normal
protections : rw-r--r--
$
Exercice 6.
On croit souvent que les
primitives système étant de plus bas niveau, elles sont plus efficaces
que les fonctions de bibliothèques équivalentes. On désire confirmer ou
infirmer cette proposition par l'expérimentation.
Pour cela, on demande de rédiger deux programmes pour copier l'entrée
standard sur la sortie standard.
- Le premier utilisera les fonctions de bibliothèque
getchar()
et putchar()
.
- Le deuxième utilisera les primitives système
read()
et write()
et prendra en argument la taille du buffer
utilisé pour la copie. Si cette taille vaut 1, la copie sera
effectuée caractère par caractère.
Vous utiliserez la commande UNIX
time
pour comparer les
temps d'exécution, en considérant la somme des temps CPU en mode
utilisateur et en mode système. Vous effectuerez ces tests pour la copie
d'un fichier d'au moins 10Mo.
En prenant comme taille de buffer les puissances successives de 2 (1, 2,
4, 8, ..., 1024) à partir de quelle taille de buffer est-il plus
intéressant d'utiliser les primitives système que les fonctions de
bibliothèque ?
Exercice 7.
Ecrire
un programme C qui
inverse un fichier de caractères : le
programme affiche les caractères à l'envers en commençant par le dernier
jusqu'au premier caractère contenu dans le fichier. On utilisera la
primitive
lseek()
. Exemple d'exécution :
$ cat toto
Bonjour!
$ ./a.out toto
!ruojnoB$
Exercice
8.
Télécharger ce petit
lexique
qui contient tous les mots de 5 lettres. Ecrire un programme C qui prend
un mot de 5 lettres en argument et qui détermine si ce mot appartient au
lexique. Pour accélérer la recherche, on procédera par dichotomie (en se
servant de la primitive
lseek()
).