Les fichiers séquentiels


sommaire du chapitre :

Introduction

1. Définitions et propriétés

2. La mémoire tampon

3. Accès aux fichiers séquentiels
3a. Le type FILE*
3b. Exemple: Créer et afficher un fichier séquentiel

4. Ouvrir et fermer des fichiers séquentiels
4a. Ouvrir un fichier séquentiel
4b. Fermer un fichier séquentiel
4c. Exemples: Ouvrir et fermer des fichiers en pratique

5. Lire et écrire dans des fichiers séquentiels
5a. Traitement par enregistrements
5b. Traitement par caractères
5c. Détection de la fin d'un fichier séquentiel

6. Résumé sur les fichiers

7. Mise à jour d'un fichier séquentiel en C
7a. Ajouter un enregistrement à un fichier
7b. Supprimer un enregistrement dans un fichier
7c. Modifier un enregistrement dans un fichier

Conclusion : Un petit mot de l'auteur...


Introduction

En C, les communications d'un programme avec son environnement se font par l'intermédiaire de fichiers.
Pour le programmeur, tous les périphériques, même le clavier et l'écran, sont des fichiers.
Jusqu'ici, nos programmes ont lu leurs données dans le fichier d'entrée standard, (le clavier) et ils ont écrit leurs résultats dans le fichier de sortie standard (l'écran).
Nous allons voir dans ce chapitre, comment nous pouvons créer, lire et modifier nous-mêmes des fichiers sur les périphériques disponibles.

retour au sommaire


1. Définitions et propriétés

Fichier

Un fichier est un ensemble structuré de données stocké en général sur un support externe (disquette, disque dur, disque optique, bande magnétique, ...).
Un fichier structuré contient une suite d'enregistrements homogènes, qui regroupent le plus souvent plusieurs composantes appartenant ensemble (champs).

Fichier séquentiel

Dans des fichiers séquentiels, les enregistrements sont mémorisés consécutivement dans l'ordre de leur entrée et peuvent seulement être lus dans cet ordre.
Si on a besoin d'un enregistrement précis dans un fichier séquentiel, il faut lire tous les enregistrements qui le précèdent, en commençant par le premier.

En simplifiant, nous pouvons nous imaginer qu'un fichier séquentiel est enregistré sur une bande magnétique.

Propriétés

Les fichiers séquentiels que nous allons considérer dans ce cours auront les propriétés suivantes :
-Les fichiers se trouvent ou bien en état d'écriture ou bien en état de lecture; nous ne pouvons pas simultanément lire et écrire dans le même fichier.
-A un moment donné, on peut uniquement accéder à un seul enregistrement; celui qui se trouve en face de la tête de lecture/écriture.
-Après chaque accès, la tête de lecture/écriture est déplacée derrière la donnée lue en dernier lieu.

Fichiers standards

Il existe deux fichiers spéciaux qui sont définis par défaut pour tous les programmes:
-stdin le fichier d'entrée standard
-stdout le fichier de sortie standard
En général, stdin est lié au clavier et stdout est lié à l'écran, soit les programmes lisent leurs données au clavier et écrivent les résultats sur l'écran.

Exemple :
L'appel suivant du programme PROG lit les données dans le fichier C:\TEST.TXT au lieu du clavier et écrit les résultats sur l'imprimante au lieu de l'écran.
PROG <C:\TEST.TXT>PRN:
En fait, l'affectation de stdin et stdout est gérée par le système d'exploitation; ainsi le programme ne 'sait' pas d'où viennent les données et où elles vont.

retour au sommaire


2. La mémoire tampon

Pour des raisons d'efficacité, les accès à un fichier se font par l'intermédiaire d'une mémoire tampon.
La mémoire tampon est une zone de la mémoire centrale de la machine réservée à un ou plusieurs enregistrements du fichier.
L'utilisation de la mémoire tampon a l'effet de réduire le nombre d'accès à la périphérie d'une part et le nombre des mouvements de la tête de lecture/écriture d'autre part.

retour au sommaire


3. Accès aux fichiers séquentiels

Les problèmes traitant des fichiers ont généralement la forme suivante : un fichier donné par son nom (et en cas de besoin le chemin d'accès sur le médium de stockage) doit être créé, lu ou modifié.
La question qui se pose est alors :

Comment pouvons-nous relier le nom d'un fichier sur un support externe avec les instructions qui donnent accès au contenu du fichier ?

En résumé, la méthode employée sera la suivante :

Avant de lire ou d'écrire un fichier, l'accès est notifié par la commande fopen.
fopen accepte le nom du fichier (ex : "A:\ADRESSES.DAT"), négocie avec le système d'exploitation et fournit un pointeur spécial qui sera utilisé ensuite lors de l'écriture ou la lecture du fichier.
Après les traitements, il faut annuler la liaison entre le nom du fichier et le pointeur à l'aide de la commande fclose.

On peut dire aussi qu'entre les événements fopen() et fclose() le fichier est ouvert.

retour au sommaire

3a. Le type FILE*

Pour pouvoir travailler avec un fichier, un programme a besoin d'un certain nombre d'informations au sujet du fichier:
- adresse de la mémoire tampon
- position actuelle de la tête de lecture/écriture
- type d'accès au fichier: écriture, lecture, ...
- état d'erreur
- ...

Ces informations (dont nous n'aurons pas à nous occuper), sont rassemblées dans une structure du type spécial FILE.
Lorsque nous ouvrons un fichier avec la commande fopen, le système génère automatiquement un bloc du type FILE et nous fournit son adresse.

Tout ce que nous avons à faire dans notre programme est :
-déclarer un pointeur du type FILE * pour chaque fichier dont nous avons besoin
-affecter l'adresse retournée par fopen à ce pointeur
-employer le pointeur à la place du nom du fichier dans toutes les instructions de lecture ou d'écriture
-libérer le pointeur à la fin du traitement à l'aide de fclose

retour au sommaire

3b. Exemple: Créer et afficher un fichier séquentiel

Avant de discuter les détails du traitement des fichiers, nous vous présentons un petit exemple comparatif qui réunit les opérations les plus importantes sur les fichiers.

Problème

On se propose de créer un fichier qui est formé d'enregistrements contenant comme information le nom d'une personne.
Chaque enregistrement est donc constitué d'une seule rubrique, à savoir, le nom de la personne.

L'utilisateur doit entrer au clavier le nom du fichier, le nombre de personnes et les noms des personnes.
Le programme se chargera de créer le fichier correspondant sur disque dur ou sur disquette.
Après avoir écrit et fermé le fichier, le programme va rouvrir le même fichier en lecture et afficher son contenu, sans utiliser le nombre d'enregistrements introduit dans la première partie.

Solution en langage algorithmique

Programme PERSONNEL
chaine NOM_FICHIER , NOM_PERSO
entier C, NB_ENREG

(* Premiere partie : créer et remplir le fichier *)
écrire "Entrez le nom de fichier à créer : "
lire NOM_FICHIER
ouvrir NOM_FICHIER en écriture
écrire "Nombre d'enregistrements à créer : "
lire NB_ENREG
en C ranger 0
TantQue (C < NB_ENREG) Faire
écrire "Entrez le nom de la presonne : "
lire NOM_PERSO
écrire NOM_FICHIER : NOM_PERSO
en C ranger C+1
FinTantQue
fermer NOM_FICHIER

(* Deuxieme partie : Lire et afficher le contenu du fichier *)
ouvrir NOM_FICHIER en lecture
en C ranger 0
TantQue non(FinFichier(NOM_FICHIER)) Faire
lire NOM_FICHIER:NOM_PERSO
écrire "NOM : ",NOM_PERSO
en C ranger C+1
FinTantQue
fermer NOM_FICHIER
FinProgramme

Solution en langage C

#include <stdio.h>
main()
{
FILE *P_FICHIER;
/* pointeur sur FILE */
char NOM_FICHIER[30], NOM_PERS[30];
int C,NB_ENREG;

/* Première partie : Créer et remplir le fichier */
printf("Entrez le nom du fichier à créer : ");
scanf("%s", NOM_FICHIER);
P_FICHIER = fopen(NOM_FICHIER, "w");
/* w pour write */
printf("Nombre d'enregistrements à créer : ");
scanf("%d", &NB_ENREG);
C = 0;
while (C<NB_ENREG)
{
printf("Entrez le nom de la personne : ");
scanf("%s", NOM_PERS);
fprintf(P_FICHIER, "%s\n", NOM_PERS);
C++;
}
fclose(P_FICHIER);

/* Deuxième partie : Lire et afficher le contenu du fichier */
P_FICHIER = fopen(NOM_FICHIER, "r");
/* r pour read */
C = 0;
while (!feof(P_FICHIER))
{
fscanf(P_FICHIER, "%s\n", NOM_PERS);
printf("NOM : %s\n", NOM_PERS);
C++;
}
fclose(P_FICHIER);
return 0;
}

retour au sommaire


4. Ouvrir et fermer des fichiers séquentiels

Avant de créer ou de lire un fichier, nous devons informer le système de cette intention pour qu'il puisse réserver la mémoire pour la zone d'échange et initialiser les informations nécessaires à l'accès du fichier.
Nous parlons alors de l'ouverture d'un fichier.

Après avoir terminé la manipulation du fichier, nous devons vider la mémoire tampon et libérer l'espace en mémoire que nous avons occupé pendant le traitement.
Nous parlons alors de la fermeture du fichier.

L'ouverture et la fermeture de fichiers se font à l'aide des fonctions fopen et fclose définies dans la bibliothèque standard <stdio.h>.

retour au sommaire

4a. Ouvrir un fichier séquentiel

Ouvrir un fichier en langage algorithmique

ouvrir <NomFichier> en écriture
ou bien
ouvrir NomFichier> en lecture
<NomFichier> est une chaîne de caractères constante ou une variable de type chaîne qui représente le nom du fichier sur le médium de stockage.

Ouvrir un fichier en C - fopen

Lors de l'ouverture d'un fichier avec fopen, le système s'occupe de la réservation de la mémoire tampon dans la mémoire centrale et génère les informations pour un nouvel élément du type FILE.
L'adresse de ce bloc est retournée comme résultat si l'ouverture s'est déroulée avec succès.
La commande fopen peut ouvrir des fichiers en écriture ou en lecture en dépendance de son deuxième paramètre ("r" ou "w") :

<PointeurVersFile> = fopen (<NomFichier> , "w" );
ou bien
<PointeurVersFile> = fopen (<NomFichier> , "r" );

-<NomFichier> est une chaîne de caractères constante ou une variable de type chaîne qui représente le nom du fichier sur le médium de stockage
-le deuxième argument détermine le mode d'accès au fichier :
"w" pour "ouverture en écriture" - write -
"r" pour "ouverture en lecture" - read -

<PointeurVersFile> est un pointeur du type FILE* qui sera relié au fichier sur le médium de stockage.
Dans la suite du programme, il faut utiliser au lieu de pour référencer le fichier.

<PointeurVersFile> doit être déclaré comme: FILE *FP

Le résultat de fopen

Si le fichier a pu être ouvert avec succès, fopen fournit l'adresse d'un nouveau bloc du type FILE.
En général, la valeur de cette adresse ne nous intéresse pas; elle est simplement affectée à un pointeur <PointeurVersFile> du type FILE* que nous utiliserons ensuite pour accéder au fichier.

A l'apparition d'une erreur lors de l'ouverture du fichier, fopen fournit la valeur numérique zéro qui est souvent utilisée dans une expression conditionnelle pour assurer que le traitement ne continue pas avec un fichier non ouvert.

Ouverture en écriture

Dans le cas de la création d'un nouveau fichier, le nom du fichier est ajouté au répertoire du médium de stockage et la tête de lecture/écriture est positionnée sur un espace libre du médium.

Si un fichier existant est ouvert en écriture, alors son contenu est perdu.

Si un fichier non existant est ouvert en écriture, alors il est créé automatiquement.
Si la création du fichier est impossible alors fopen indique une erreur en retournant la valeur zéro.

Autres possibilités d'erreurs signalées par un résultat nul :
- chemin d'accès non valide
- pas de disque/bande dans le lecteur
- essai d'écrire sur un médium protégé contre l'écriture
- ...

Ouverture en lecture

Dans le cas de la lecture d'un fichier existant, le nom du fichier doit être retrouvé dans le répertoire du médium et la tête de lecture/écriture est placée sur le premier enregistrement de ce fichier.

Possibilités d'erreurs signalées par un résultat nul :
- essai d'ouvrir un fichier non existant
- essai d'ouvrir un fichier sans autorisation d'accès
- essai d'ouvrir un fichier protégé contre la lecture
- ...

Remarque avancée :
Si un fichier n'a pas pu être ouvert avec succès, (résultat NULL), un code d'erreur est placé dans la variable errno.
Ce code désigne plus exactement la nature de l'erreur survenue. Les codes d'erreurs sont définis dans <errno.h>.
- L'appel de la fonction strerror(errno) retourne un pointeur sur la chaîne de caractères qui décrit l'erreur dans errno.
- L'appel de la fonction perror(s) affiche la chaîne s et le message d'erreur qui est défini pour l'erreur dans errno.

retour au sommaire

4b. Fermer un fichier séquentiel

Fermer un fichier en langage algorithmique

f ermer <NomFichier>

<NomFichier> est une chaîne de caractères constante ou une variable de type chaîne qui représente le nom du fichier que l'on désire fermer.

Fermer un fichier en langage C

fclose(<PointeurVersFile>);

<PointeurVersFile> est un pointeur du type FILE* relié au nom du fichier que l'on désire fermer.

La fonction fclose provoque le contraire de fopen :

Si le fichier a été ouvert en écriture, alors les données non écrites de la mémoire tampon sont écrites et les données supplémentaires (longueur du fichier, date et heure de sa création) sont ajoutées dans le répertoire du médium de stockage.

Si le fichier a été ouvert en lecture, alors les données non lues de la mémoire tampon sont simplement "jetées".

La mémoire tampon est ensuite libérée et la liaison entre le pointeur sur FILE et le nom du fichier correspondant est annulée.

Après fclose() le pointeur <PointeurVersFile> est invalide.
Des erreurs graves pourraient donc survenir si ce pointeur est utilisé par la suite !

retour au sommaire


5. Lire et écrire dans des fichiers séquentiels

Les fichiers que nous employons dans ce manuel sont des fichiers texte, ie : toutes les informations dans les fichiers sont mémorisées sous forme de chaînes de caractères et sont organisées en lignes.
Même les valeurs numériques (types int, float, double, ...) sont stockées comme chaînes de caractères.

Pour l'écriture et la lecture des fichiers, nous allons utiliser les fonctions standard fprintf, fscanf, fputc et fgetc qui correspondent à printf, scanf, putchar et getchar si nous indiquons stdout respectivement stdin comme fichiers de sortie ou d'entrée.

retour au sommaire

5a. Traitement par enregistrements

Les fichiers texte sont généralement organisés en lignes, la fin d'une information dans le fichier est marquée par le symbole "\n".

ATTENTION ! :
Pour pouvoir lire correctement les enregistrements dans un fichier séquentiel, le programmeur doit connaître l'ordre des différentes rubriques (champs) à l'intérieur des enregistrements.

Ecrire une information dans un fichier séquentiel

Ecrire dans un fichier séquentiel en langage algorithmique

écrire <NomFichier>:<Expression1>
écrire <NomFichier>:<Expression2>
...
écrire <NomFichier>:<ExpressionN>

-<NomFichier> est une chaîne de caractères constante ou une variable de type chaîne qui représente le nom du fichier dans lequel on veut écrire.
-<ExpressionN> représentent les rubriques qui forment un enregistrement et dont les valeurs respectives sont écrites dans le fichier.

Ecrire dans un fichier séquentiel en langage C - fprintf

fprintf(<PointeurVersFile> , "<SpecificateurFormat1>\n" , <Expression1>);
fprintf(<PointeurVersFile> , "<SpecificateurFormat2>\n" , <Expression2>);
...
fprintf(<PointeurVersFile> , "<SpecificateurFormatN>\n" , <ExpressionN>);

ou bien

fprintf(<PointeurVersFile> , "<SpecificateurFormat1> \n <SpecificateurFormat2> \n ... <SpecificateurFormatN> \n", <Expression1> , <Expression2> , ... , <ExpressionN>);

-<PointeurVersFile> est un pointeur du type FILE* qui est relié au nom du fichier cible.
-<Expression1>),<Expression2>),...,<ExpressionN> représentent les rubriques qui forment un enregistrement et dont les valeurs respectives sont écrites dans le fichier.
-<SpecificateurFormat1>,<SpecificateurFormat2>,...,<SpecificateurFormatN> représentent les spécificateurs de format pour l'écriture des différentes rubriques.

Remarque :
L'instruction
fprintf(stdout, "Bonjour\n");
est identique à
printf("\Bonjour \n");

ATTENTION !
Notez que fprintf (et printf) écrit toutes les chaînes de caractères sans le symbole de fin de chaîne "\0".
Dans les fichiers texte, il faut ajouter le symbole de fin de ligne "\n" pour séparer les données.

Lire une information dans un fichier séquentiel

Lire dans un fichier séquentiel en langage algorithmique

lire <NomFichier>:<Variable1>
lire <NomFichier>:<Variable2>
...
lire <NomFichier>:<VariableN>

-<NomFichier> est une chaîne de caractères constante ou une variable de type chaîne qui représente le nom du fichier duquel on veut lire.
-<Variable1>, <Variable2>, ..., <VariableN> représentent les variables qui vont recevoir les valeurs des différentes rubriques d'un enregistrement lu dans le fichier.

Lire dans un fichier séquentiel en langage C - fscanf

fscanf(<PointeurVersFile> , "<SpecificateurFormat1>\n" , <AdrVariable1>);
fscanf(<PointeurVersFile> , "<SpecificateurFormat2>\n" , <AdrVariable2>);
...
fscanf(<PointeurVersFile> , "<SpecificateurFormatN>\n" , <AdrVariableN>);

ou bien

fprintf(<PointeurVersFile> , "<SpecificateurFormat1> \n <SpecificateurFormat2> \n ... <SpecificateurFormatN> \n", <AdrVariable1> , <AdrVariable2> , ... , <AdrVariableN>);

-<PointeurVersFile> est un pointeur du type FILE* qui est relié au nom du fichier à lire.
-<AdrVariable1> , <AdrVariable2> , ... , <AdrVariableN> représentent les adresses des variables qui vont recevoir les valeurs des différentes rubriques d'un enregistrement lu dans le fichier.
-<SpecificateurFormat1>,<SpecificateurFormat2>,...,<SpecificateurFormatN> représentent les spécificateurs de format pour l'écriture des différentes rubriques.

Remarque :
L'instruction
fscanf(stdin, "%d \n", &N);
est identique à
scanf("%d \n", &N);

ATTENTION !
Pour les fonctions scanf et fscanf tous les signes d'espacement sont équivalents comme séparateurs.
En conséquence, à l'aide de fscanf, il nous sera impossible de lire toute une phrase dans laquelle les mots sont séparés par des espaces.

retour au sommaire

5b. Traitement par caractères

La manipulation de fichiers avec les instructions fprintf et fscanf n'est pas assez flexible pour manipuler de façon confortable des textes écrits.
Il est alors avantageux de traiter le fichier séquentiellement caractère par caractère.

Ecrire un caractère dans un fichier séquentiel - fputc

fputc(<Caractere> , <PointeurVersFile>);

fputc transfère le caractère indiqué par dans le fichier référencé par et avance la position de la tête de lecture/écriture au caractère suivant.

-<Caractere> représente un caractère (valeur numérique de 0 à 255) ou le symbole de fin de fichier EOF.
-<PointeurVersFile> est un pointeur du type FILE* qui est relié au nom du fichier cible.

Remarque :
L'instruction
fputc("a", stdout);
est identique à
putchar("a");

Lire un caractère dans un fichier séquentiel - fgetc

<Caractere> = fgetc(<PointeurVersFile>);

fgetc fournit comme résultat le prochain caractère du fichier référencé par et avance la position de la tête de lecture/écriture au caractère suivant.
A la fin du fichier, fgets retourne EOF.

-<Caractere> représente une variable du type int qui peut accepter une valeur numérique de 0 à 255 ou le symbole de fin de fichier EOF.
-<PointeurVersFile> est un pointeur du type FILE* qui est relié au nom du fichier à lire.

Remarque :
L'instruction
C = fgetc(stdin);
est identique à
C = getchar();

retour au sommaire

5c. Détection de la fin d'un fichier séquentiel

Lors de la fermeture d'un fichier ouvert en écriture, la fin du fichier est marquée automatiquement par le symbole de fin de fichier EOF (End Of File).
Lors de la lecture d'un fichier, les fonctions finfichier(<NomFichier>) respectivement feof(<PointeurVersFile>) nous permettent de détecter la fin du fichier.

Détection de la fin d'un fichier en langage algorithmique

finfichier(<NomFichier>)

finfichier retourne la valeur logique vrai, si la tête de lecture du fichier référencé par <NomFichier> est arrivée à la fin du fichier; sinon la valeur logique du résultat est faux.

Détection de la fin d'un fichier en langage C - feof

feof(<PointeurVersFile>)

feof retourne une valeur différente de zéro, si la tête de lecture du fichier référencé par est arrivée à la fin du fichier; sinon la valeur du résultat est zéro.

Pour que la fonction feof détecte correctement la fin du fichier, il faut qu'après la lecture de la dernière donnée du fichier, la tête de lecture arrive jusqu'à la position de la marque EOF.
Nous obtenons cet effet seulement si nous terminons aussi la chaîne de format de fscanf par un retour à la ligne "\n" (ou par un autre signe d'espacement).

Exemples :
Une boucle de lecture typique pour lire les enregistrements d'un fichier séquentiel référencé par un pointeur <PointeurVersFile> peut avoir la forme suivante :
while (!feof(<PointeurVersFile>))
{
fscanf(<pointeurVersFile>, "%s\n ... \n", NOM, ... ); ...
}

Le programme suivant lit et affiche le fichier "C:\AUTOEXEC.BAT" en le parcourant caractère par caractère:
#include <stdio.h>
#include <stdlib.h>
main()
{
FILE *FP;
FP = fopen("C:\\AUTOEXEC.BAT", "r");
if (!FP)
{ printf("Impossible d'ouvrir le fichier\n"); exit(-1); }
while (!feof(FP))
{ putchar(fgetc(FP)); }
fclose(FP);
return 0;
}

retour au sommaire


6. Résumé sur les fichiers

 
Algorithmique
C
Ouverture en écriture Ouvrir <Nom> en écriture <Pointeur> = fopen(<Nom>,"w");
Ouverture en lecture Ouvrir <Nom> en lecture <Pointeur> = fopen(<Nom>,"r");
Fermeture Fermer <Nom> fclose(<Pointeur>);
Fonction Fin Fichier FinFichier(<Nom>) feof(<Pointeur>);
Ecriture ecrire <Nom>:<Expression>

fprint(<Pointeur>,"...",<AdresseDansFile>);
fputc(<Caractere>,<Pointeur>);

Lecture lire <Nom>:<Variable> fscanf(<Pointeur>,"...",<AdresseDansFile>);
<Caractere> = fgetc (<Pointeur>);

retour au sommaire


7. Mise à jour d'un fichier séquentiel en C

Dans ce chapitre, nous allons résoudre les problèmes standards sur les fichiers, à savoir :
- l'ajout d'un enregistrement à un fichier
- la suppression d'un enregistrement dans un fichier
- la modification d'un enregistrement dans un fichier

Comme il est impossible de lire et d'écrire en même temps dans un fichier séquentiel, les modifications doivent se faire à l'aide d'un fichier supplémentaire.
Nous travaillons donc typiquement avec au moins deux fichiers : l'ancien fichier ouvert en lecture et le nouveau fichier ouvert en écriture.

retour au sommaire

7a. Ajouter un enregistrement a un fichier

Nous pouvons ajouter le nouvel enregistrement à différentes positions dans le fichier :

Ajout d'un enregistrement à la fin d'un fichier

L'ancien fichier est entièrement copié dans le nouveau fichier, suivi du nouvel enregistrement.

Ajout d'un enregistrement au début d'un fichier

L'ancien fichier est copié derrière le nouvel enregistrement qui est écrit en premier lieu.

Insertion dans un fichier trié relativement à une rubrique commune des enregistrements

Le nouveau fichier est créé en trois étapes :
- copier les enregistrements de l'ancien fichier qui précèdent le nouvel enregistrement
- écrire le nouvel enregistrement
- copier le reste des enregistrements de l'ancien fichier

Exemple :

Le programme suivant effectue l'insertion d'un enregistrement à introduire au clavier dans un fichier trié selon la seule rubrique de ses enregistrements: le nom d'une personne.
Le programme inclut en même temps les solutions aux deux problèmes précédents.
La comparaison lexicographique des noms des personnes se fait à l'aide de la fonction strcmp.

#include <stdio.h>
#include <string.h>
main()
{
/* Déclarations : */
/* Noms des fichiers et pointeurs de référence */
char ANCIEN[30], NOUVEAU[30]; FILE *INFILE, *OUTFILE;
/* Autres variables */
char NOM_PERS[30], NOM_AJOUT[30];
int TROUVE;

/* Ouverture de l'ancien fichier en lecture */
do
{
printf
("Nom de l'ancien fichier : ");
scanf("%s", ANCIEN);
INFILE = fopen(ANCIEN, "r");
if (!INFILE) { printf("\aERREUR: Impossible d'ouvrir le fichier: %s.\n", ANCIEN); }
}
while (!INFILE);

/* Ouverture du nouveau fichier en écriture */
do
{

printf("Nom du nouveau fichier : ");
scanf("%s", NOUVEAU);
OUTFILE = fopen(NOUVEAU, "w");
if (!OUTFILE) { printf("\aERREUR: Impossible d'ouvrir le fichier: %s.\n", NOUVEAU); }
}
while (!OUTFILE);

/* Saisie de l'enregistrement à insérer */
printf("Enregistrement à insérer : ");
scanf("%s",NOM_AJOUT);

/* Traitement */
TROUVE = 0;
/* Copie des enregistrements dont le nom précéde lexicogr. celui à insérer.*/
while (!feof(INFILE) && !TROUVE)
{
fscanf
(INFILE, "%s\n", NOM_PERS);
if (strcmp(NOM_PERS, NOM_AJOUT) > 0) { TROUVE = 1; }
else { fprintf(OUTFILE, "%s\n", NOM_PERS); }
}
/* Ecriture du nouvel enregistrement, */
fprintf(OUTFILE, "%s\n", NOM_AJOUT);
/* suivi du dernier enregistrement lu. */
if (TROUVE) { fprintf(OUTFILE, "%s\n", NOM_PERS); }
/* Copie du reste des enregistrements */
while (!feof(INFILE))
{
fscanf
(INFILE, "%s\n", NOM_PERS);
fprintf(OUTFILE, "%s\n", NOM_PERS);
}

/* Fermeture des fichiers */
fclose(OUTFILE);
fclose(INFILE);
return 0;
}

retour au sommaire

7b. Supprimer un enregistrement dans un fichier

Le nouveau fichier est créé en copiant tous les enregistrements de l'ancien fichier qui précèdent l'enregistrement à supprimer et tous ceux qui le suivent

Solution en C

#include <stdio.h>
#include <string.h>
main()
{
/* Déclarations : */
/* Noms des fichiers et pointeurs de référence */
char ANCIEN[30], NOUVEAU[30]; FILE *INFILE, *OUTFILE;
/* Autres variables */
char NOM_PERS[30], NOM_SUPPR[30];

/* Ouverture de l'ancien fichier en lecture */
do
{

printf("Nom de l'ancien fichier : ");
scanf("%s", ANCIEN);
INFILE = fopen(ANCIEN, "r");
if (!INFILE) { printf("\aERREUR: Impossible d'ouvrir le fichier: %s.\n", ANCIEN); }
}
while
(!INFILE);

/* Ouverture du nouveau fichier en écriture */
do
{
printf
("Nom du nouveau fichier : ");
scanf("%s", NOUVEAU);
OUTFILE = fopen(NOUVEAU, "w");
if (!OUTFILE) { printf("\aERREUR: Impossible d'ouvrir " "le fichier: %s.\n", NOUVEAU); }
}

while (!OUTFILE);

/* Saisie de l'enregistrement à supprimer */
printf("Enregistrement à supprimer : ");
scanf("%s",NOM_SUPPR);

/* Traitement */
/* Copie de tous les enregistrements à l'exception de celui à supprimer. */
while (!feof(INFILE))
{
fscanf(INFILE, "%s\n", NOM_PERS);
if (strcmp(NOM_PERS, NOM_SUPPR) != 0) { fprintf(OUTFILE, "%s\n", NOM_PERS); }
}

/* Fermeture des fichiers */
fclose(OUTFILE);
fclose(INFILE);
return 0;
}

retour au sommaire

7c. Modifier un enregistrement dans un fichier

Le nouveau fichier est créé de tous les enregistrements de l'ancien fichier qui précèdent l'enregistrement à modifier, de l'enregistrement modifié et de tous les enregistrements qui suivent l'enregistrement à modifier dans l'ancien fichier.

Solution en C

#include <stdio.h>
#include <string.h>
main()
{
/* Déclarations : */
/* Noms des fichiers et pointeurs de référence */
char ANCIEN[30], NOUVEAU[30]; FILE *INFILE, *OUTFILE;
/* Autres variables */
char NOM_PERS[30], NOM_MODIF[30], NOM_NOUV[30];

/* Ouverture de l'ancien fichier en lecture */
do
{
printf
("Nom de l'ancien fichier : ");
scanf("%s", ANCIEN);
INFILE = fopen(ANCIEN, "r");
if (!INFILE) { printf("\aERREUR: Impossible d'ouvrir le fichier: %s.\n", ANCIEN); }
}
while
(!INFILE);

/* Ouverture du nouveau fichier en écriture */
do
{
printf
("Nom du nouveau fichier : ");
scanf("%s", NOUVEAU);
OUTFILE = fopen(NOUVEAU, "w");
if (!OUTFILE) { printf("\aERREUR: Impossible d'ouvrir le fichier: %s.\n", NOUVEAU); }
}
while
(!OUTFILE);

/* Saisie de l'enregistrement à modifier, */
printf("Enregistrement à modifier : ");
scanf("%s",NOM_MODIF);
/* et de sa nouvelle valeur. */
printf("Enregistrement nouveau : ");
scanf("%s",NOM_NOUV);

/* Traitement */
/* Copie de tous les enregistrements en remplaçant l'enregistrement à modifier par sa nouvelle valeur. */
while (!feof(INFILE))
{
fscanf
(INFILE, "%s\n", NOM_PERS);
if (strcmp(NOM_PERS, NOM_MODIF) = 0) { fprintf(OUTFILE, "%s\n", NOM_NOUV); }
else { fprintf(OUTFILE, "%s\n", NOM_PERS); }
}

/* Fermeture des fichiers */
fclose(OUTFILE);
fclose(INFILE);
return 0;
}

retour au sommaire


Conclusion : Un petit mot de l'auteur...

Eh ben voilou... on est a la fin de ce que j'appellerai une bonne initiation au C...
Maintenant, il ne vous reste plus qu'a mettre ces connaissances en pratique, et vous pourrez passer au C++ ;)

Bon courage surtout, et ne désespérez pas si cela vous parait un peu obtus au départ...
Ce langage, avec bien-sur le C++, est de loin le plus efficace...

NiKo