Vous êtes sur la page 1sur 111

Leçon 9

Programmer les fichiers

I- Les fichiers séquentiels


II- Les fichiers textes
III- Exercices d'entrainement

Bibliographie
Les fichiers, organisation et accès Mc BELAID Pages Bleues Internationales
Les fichiers séquentiels Faber Frédéric (site web http://www.ltam.lu/fabfr)
Langage C et algorithmique Magali Contensin (site web)
Programmer les fichiers en Pascal Mc BELAID Pages Bleues Internationales

Avant d’aborder la programmation des fichiers, nous vous recomendons de consulter l’ouvrage

« Les fichiers, organisation et accès Mc BELAID Pages Bleues Internationales »

Qui traite de la notion de fichiers en détails et des supports de stockage et les méthodes d’accès.
I- Les fichiers séquentiels

En programmation, les communications d’un programme avec les périphériques ( clavier, écran et
mémoires externes) se font par l’intermédiaire des fichiers. Les programmes lisent les données dans
les fichiers et les écrivent dans les fichiers.

1. Définitions
2. Accès aux fichiers séquentiels
3. Ouvrir et fermer des fichiers séquentiels
4. Lire et écrire dans des fichiers séquentiels
5. Résumé sur les fichiers
6. Mise à jour d'un fichier séquentiel en C

1. Définitions
Fichier

Un fichier (angl.: file) est un ensemble structuré de données stocké en général sur un
support externe (disque dur, disque optique, autres mémoires externes, ...). Un fichier
structuré contient une suite d'enregistrements de même types, qui regroupent plusieurs
(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.

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, c’est à dire les programmes
lisent leurs données au clavier et écrivent les résultats sur l'écran.
2. Accès aux fichiers séquentiels
La question qui se pose est alors:

Comment accéder à 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 pour ouvrir
le fichier en lecture ou en écriture. fopen accepte le nom du fichier (par exemple:
"F:\Fichier1.DAT"), le système d'exploitation 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 et le fichier est
fermé.

2.1. 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.

En C, 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.
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 le disque
dur.

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.

En langage algorithmique

Algorithme FichierPERS
Chaîne NOM_FICHIER, NOM_PERS
Entier C,_NB_ENREG

(* Première partie : créer et remplir le fichier *)


Ecrire ("Entrez le nom du fichier à créer : ")
Lire (NOM_FICHIER)
Ouvrir (NOM_FICHIER en écriture)
Ecrire ("Nombre d'enregistrements à créer : ")
Lire (NB_ENREG)
C  0
Tant que (C < NB_ENREG) faire
début
| écrire ("Entrez le nom de la personne : ")
| lire (NOM_PERS)
| écrire (NOM_FICHIER:NOM_PERS)
| C  C+1
fin

Fermer (NOM_FICHIER)

(* Deuxième partie: Lire et afficher le contenu du fichier *)


Ouvrir (NOM_FICHIER en lecture)
C  0
Tant que non(finfichier(NOM_FICHIER)) faire
Début
| lire (NOM_FICHIER:NOM_PERS)
| écrire ("NOM : ",NOM_PERS)
| C  C+1
fin
Fermer (NOM_FICHIER)
Fin.

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"); /* 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"); /* 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;
}
3. Ouvrir et fermer des fichiers en pratique

En pratique, il faut contrôler si l'ouverture d'un fichier a été accomplie avec succès avant
de continuer les traitements. Pour le cas d'une erreur, nous allons envisager deux réactions
différentes:

a) Répéter l'essai jusqu'à l'ouverture correcte du fichier

#include <stdio.h>
main()
{
FILE *P_FICHIER; /* pointeur sur FILE */
char NOM_FICHIER[30]; /* nom du fichier */
. . .

do
{
printf("Entrez le nom du fichier : ");
scanf("%s", NOM_FICHIER);
P_FICHIER = fopen(NOM_FICHIER, "w");
/* ou bien */
/* P_FICHIER = fopen(NOM_FICHIER, "r"); */
if (!P_FICHIER)
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", NOM_FICHIER);
}
while (!P_FICHIER);

. . .

fclose(P_FICHIER);
return 0;
}

b) Abandonner le programme en retournant un code d'erreur non nul - exit

#include <stdio.h>
#include <stdlib.h>
main()
{
FILE *P_FICHIER; /* pointeur sur FILE */
char NOM_FICHIER[30]; /* nom du fichier */
. . .

printf("Entrez le nom du fichier : ");


scanf("%s", NOM_FICHIER);
P_FICHIER = fopen(NOM_FICHIER, "w");
/* ou bien */
/* P_FICHIER = fopen(NOM_FICHIER, "r"); */
if (!P_FICHIER)
{
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", NOM_FICHIER);
exit(-1); /* Abandonner le programme en */
} /* retournant le code d'erreur -1 */

. . .

fclose(P_FICHIER);
return 0;
}

2.2 Fermer un fichier séquentiel

Fermer un fichier en langage C

fclose( <PFichier> );

<PFichier> 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 de stockage.

Si le fichier a été ouvert en lecture, alors les données non lues de la mémoire tampon (qui perd
son contenu, une fois le programme fini) sont simplement perdues.

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 <PFichier> est invalide. Des erreurs graves pourraient donc
survenir si ce pointeur est utilisé par la suite!

3.1. Ouvrir un fichier séquentiel

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") :

<PFichier> = fopen ( <Nom> , "w" );

ou bien

<PFichier> = fopen ( <Nom> , "r" );

<Nom> est une chaîne de caractères constante ou une variable de type chaîne qui représente
le nom du fichier sur le support 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 -

* <PFichier> 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 <PFichier> au lieu de <Nom> pour référencer le
fichier.

* <PFichier> doit être déclaré comme:

FILE *PFichier;

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 <PFichier> 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
support de stockage et la tête de lecture/écriture est positionnée sur un espace libre du support.

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 support 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,
4. Lire et écrire dans des fichiers séquentiels
Enregistrements de type texte (chaînes de caractères)

Dans ce cas 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.

4.1. Traitement par enregistrements


4.2. Traitement par caractères
4.3. Détection de la fin d'un fichier séquentiel

4.1 Traitement par enregistrements

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

Tête de
Lecture/Ecriture

\n 1 1 1 \n M A H D I \n 1 1 2 \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.

a) Ecrire une information dans un fichier séquentiel

fprintf( <PFichier>, "<Form1>\n", <Expr1>);


fprintf( < PFichier >, "<Form2>\n", <Expr2>);
...
fprintf( < PFichier >, "<FormN>\n", <ExprN>);

ou bien

fprintf(<PFichier >,"<Form1>\n<Form2>\n...\n<FormN>\n", <Expr1>,


<Expr2>, ... , <ExprN>);

* < PFichier > est un pointeur du type FILE* qui est relié au nom du fichier cible.

* <Expr1>, <Expr2>, ... , <ExprN> représentent les rubriques qui forment un enregistrement et dont
les valeurs respectives sont écrites dans le fichier.
* <Form1>, <Form2>, ... , <FormN> 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.

b) Lire une information dans un fichier séquentiel

fscanf

fscanf( < PFichier >, "<Form1>\n", <Adr1>);


fscanf( < PFichier >, "<Form2>\n", <Adr2>);
...
fscanf( < PFichier >, "<FormN>\n", <AdrN>);

ou bien

fscanf(<PFichier >,"<Form1>\n<Form2>\n...\n<FormN>\n", <Adr1>,


<Adr2>, ... , <AdrN>);
* < PFichier > est un pointeur du type FILE* qui est relié au nom du fichier à lire.

* <Adr1>, <Adr2>, ... , <AdrN> représentent les adresses des variables qui vont recevoir les valeurs
des différentes rubriques d'un enregistrement lu dans le fichier.

* <Form1>, <Form2>, ... , <FormN> représentent les spécificateurs de format pour la lecture 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.
4.2. 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.

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

fputc( <Car> , < PFichier > );

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

représente un caractère (valeur numérique de 0 à 255) ou le symbole de fin de


fichier EOF.
< PFichier > est un pointeur du type FILE* qui est relié au nom du fichier cible.

Remarque

L'instruction

fputc('a', stdout);

est identique à

putchar('a');

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

<Car> = fgetc( <PFichier> );


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

<Car> 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.

<PFichier> est un pointeur du type FILE* qui est relié au nom du fichier à lire.

Remarque

L'instruction

Car = fgetc(stdin);

est identique à

Car = getchar();
4.3. 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(<Nom>)respectivement feof(<PFichier>) nous
permettent de détecter la fin du fichier:

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

<PFichier> est un pointeur du type FILE* qui est relié au nom du fichier à lire.

Exemple

Une boucle de lecture typique pour lire les enregistrements d'un fichier séquentiel référencé
par un pointeur PFichier peut avoir la forme suivante:

while (!feof(FP))
{
fscanf(FP, "%s\n ... \n", NOM, ... );
. . .
}

Exemple

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 *PFichier;
FP = fopen("C:\\AUTOEXEC.BAT", "r");
if (!PFichier)
{
printf("Impossible d'ouvrir le fichier\n");
exit(-1);
}
while (!feof(PFichier))
putchar(fgetc(PFichier));
fclose(PFichier);
return 0;
}

Dans une chaîne de caractères constante, il faut indiquer le symbole '\' par '\\', pour qu'il ne
soit pas confondu avec le début d'une séquence d'échappement (p.ex: \n, \t, \a, ...).
5. Résumé sur les fichiers

Traitement Instruction en C
Ouverture en écriture < PFichier > = fopen(<Nom>,"w");
Ouverture en lecture < PFichier > = fopen(<Nom>,"r");
Fermeture fclose(<PFichier >);
Fonction fin de fichier feof(<PFichier >)
fprintf(<PFichier >,"...",<Adr>);
Ecriture
fputc(<Car>, < PFichier >);
fscanf(<PFichier >,"...",<Adr>);
Lecture
<Car> = fgetc(<PFichier >);

6. 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'ajoute 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:

6.1. Ajouter un enregistrement à un fichier


6.2. Supprimer un enregistrement dans un fichier
6.3. Modifier un enregistrement dans un fichier

6.1. Ajouter un enregistrement à un fichier

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

a) Ajoute à la fin du fichier

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

b) Ajoute au début du fichier

L'ancien fichier est copié derrière le nouvel enregistrement qui est écrit en premier lieu.
c) 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.

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.

Programme en langage 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_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;
}

6.2. 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:

Programme en langage 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;
}

6.3. 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:

Programme en langage 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;
}
II- Les fichiers textes (non séquentiels)
Un fichier texte est un fichier qui est lisible, il peut être édité dans n’importe quel éditeur de
texte. En programmation on utilise les fichiers textes pour lire et/ou écrire des informations.

Lorsque vous voulez obtenir des informations sur le fichier, vous pouvez utiliser la
commande file.

> file donnees.txt


donnees.txt: ASCII text

1. Ouverture d'un fichier

La fonction FILE *fopen(char *nomfic, char *mode) ouvre le fichier dont le nom
est donné comme premier argument, selon le mode d'ouverture précisé (w = écriture, r
= lecture, a = ajout en fin de fichier) et l'assigne à un flux, i.e. à une variable
de type FILE *.

Dans le programme ci-dessous, nom_fic est une chaîne de caractères qui contient le nom du
fichier à ouvrir, et fic est une variable de type FILE *.

// ouverture du fichier
fic = fopen(nom_fic, "r"); // ouvrir en lecture
if(fic == NULL){
printf("Impossible d'ouvrir le fichier %s\n", nom_fic);
exit(1);
}
printf(".............. Ouverture du fichier %s\n", nom_fic);

Fermeture d'un fichier

// fermeture du fichier
if(fclose(fic) == EOF){
printf("Probleme de fermeture du fichier %s", nom_fic);
exit(1);
}
printf(".............. Fermeture du fichier %s\n", nom_fic);

Lecture des données d'un fichier

fgets

La fonction char *fgets(char *chaine, int max, FILE *fichier) lit une chaîne
de caractères sur le flux fichier et la stocke dans la chaîne chaine. Elle lit au
maximum max - 1 caractères, elle s'arrête dès qu'elle rencontre un caractère de passage à la
ligne et place un \0 à la fin de la chaîne. Lorsqu'elle rencontre la fin de fichier, elle retourne la
chaîne NULL.

Prenons un programme qui affiche le contenu d'un fichier et compte le nombre de lignes de ce
fichier :

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void verif_et_recup_arg(int nb, char *arguments[], int nb_souhaite,


char *chaine)
{
if(nb != nb_souhaite){
printf("Usage : lignes nom_fichier\n");
exit(1);
}

strcpy(chaine, arguments[1]);
}

int main(int argc, char *argv[]) {


FILE *fic;
int nb_lignes;
char ligne_lue[512];
char nom_fic[255];

verif_et_recup_arg(argc, argv, 2, nom_fic);

// ouverture du fichier
fic = fopen(nom_fic, "r"); // ouvrir en lecture
if(fic == NULL){
printf("Impossible d'ouvrir le fichier %s\n", nom_fic);
exit(1);
}
printf(".............. Ouverture du fichier %s\n", nom_fic);

// compter et afficher les lignes du fichier


nb_lignes = 0;
while(fgets(ligne_lue, 512, fic) != NULL){
printf("\t%s", ligne_lue);
nb_lignes++;
}
printf("le fichier %s comporte %d lignes\n", nom_fic, nb_lignes);

// fermeture du fichier
if(fclose(fic) == EOF) {
printf("Probleme de fermeture du fichier %s", nom_fic);
exit(1);
}
printf(".............. Fermeture du fichier %s\n", nom_fic);

return 0;
}
NB : le \n n'est pas placé dans le printf("\t%s", ligne_lue); qui affiche le contenu de
la variable ligne_lue car fgets stocke le caractère de retour à la ligne quand il le lit. Si nous
avions demandé printf("\t%s\n", ligne_lue);. Nous aurions obtenu sur la console une
ligne blanche entre chaque ligne du fichier.

> ls
donnees.txt lignes.c
> more donnees.txt
une chaine sur la 1ere ligne
une autre chaine sur la 2eme ligne
14
3.5
une chaine sur la 5eme ligne
derniere ligne avant la fin
> gcc -Wall lignes.c -o lignes
> ./lignes
Usage : lignes nom_fichier
> ./lignes donnee.txt
Impossible d'ouvrir le fichier donnee.txt
> ./lignes donnees.txt
.............. Ouverture du fichier donnees.txt
une chaine sur la 1ere ligne
une autre chaine sur la 2eme ligne
14
3.5
une chaine sur la 5eme ligne
derniere ligne avant la fin le fichier donnees.txt comporte
6 lignes
.............. Fermeture du fichier donnees.txt
>

fscanf

La fonction fscanf(FILE *fichier, char *format, adr_var_1, adr_var_2,


...) prend comme premier argument le flux dans lequel elle doit lire et stocke les données
lues selon le format défini par la chaîne format dans les variables adr_var_ passées par
adresse.

Le programme ci-dessous utilise la fonction scanf pour stocker dans des variables les
informations d'un fichier annuaire qui comporte sur chaque ligne un nom, un prénom, le
numéro de téléphone et l'adresse mail d'une personne.

NB : on suppose que le nom de la personne ne comporte pas d'espace.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void verif_et_recup_arg(int nb, char *arguments[], int nb_souhaite,


char *chaine)
{
if(nb != nb_souhaite){
printf("Usage : annuaire nom_fichier\n");
exit(1);
}

strcpy(chaine, arguments[1]);
}

int main(int argc, char *argv[])


{
FILE *fic;
int nb_lignes, t1, t2, t3, t4, t5;
char nom_fic[255], nom[255], prenom[255], mail[255];

verif_et_recup_arg(argc, argv, 2, nom_fic);

// ouverture du fichier
fic = fopen(nom_fic, "r"); // ouvrir en lecture
if(fic == NULL){
printf("Impossible d'ouvrir le fichier %s\n", nom_fic);
exit(1);
}
printf(".............. Ouverture du fichier %s\n\n", nom_fic);

// recuperer les donnees de l'annuaire


nb_lignes = 0;
while(fscanf(fic, "%s %s %d %d %d %d %d %s", nom, prenom,\
&t1, &t2, &t3, &t4, &t5, mail) != EOF){
printf("\tnom = %s\n \tprenom = %s\n \ttel = %.2d %.2d %.2d %.2d
%.2d\n \tmail = %s\n\n",\
nom, prenom, t1, t2, t3, t4, t5, mail);
nb_lignes++;
}
printf("le fichier %s comporte %d lignes\n", nom_fic, nb_lignes);

// fermeture du fichier
if(fclose(fic) == EOF){
printf("Probleme de fermeture du fichier %s", nom_fic);
exit(1);
}
printf(".............. Fermeture du fichier %s\n", nom_fic);

return 0;
}
Écriture de données dans un fichier

fputs

La fonction int fputs(char *chaine, FILE *fic) écrit la chaîne de


caractères chaine sur le flux fic. Elle retourne le dernier caractère de la chaîne en cas de
succès (EOF en cas d'erreur).

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[])


{
FILE *fic;
int nb_lignes;
char ligne_lue[512];

// ouverture du fichier
fic = fopen("resultat.txt", "w"); // ouvrir en ecriture
if(fic == NULL){
printf("Impossible d'ouvrir le fichier resultat.txt\n");
exit(1);
}

do{
fgets(ligne_lue, 512, stdin);
fputs(ligne_lue, fic);
}
while(strcmp(ligne_lue, "FIN\n") != 0);

// fermeture du fichier
if(fclose(fic) == EOF) {
printf("Probleme de fermeture du fichier resultat.txt\n");
exit(1);
}

printf("les donnees ont ete stockees dans resultat.txt\n");

return 0;
}
fprintf

La fonction int fprintf(FILE *fic, char *format, var_1, var_2, ...) écrit
les données var_ dans le fluxfic en respectant le format spécifié par la chaîne format. Elle
retourne le nombre de caractères écrits sur le flux.

Le programme ci-dessous ajoute une entrée dans l'annuaire :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])


{
FILE *fic;
char nom_fic[255], nom[255], prenom[255], mail[255];
int t1, t2, t3, t4, t5;

// stockage des donnees issues de la ligne de commandes


if(argc != 10){ //10 car num. tel. = 5 blocs d'entiers
printf("Usage : annuaire nom_fichier nom prenom tel mail\n");
exit(1);
}
strcpy(nom_fic, argv[1]);
strcpy(nom, argv[2]);
strcpy(prenom, argv[3]);
strcpy(mail, argv[9]);
t1 = atoi(argv[4]);
t2 = atoi(argv[5]);
t3 = atoi(argv[6]);
t4 = atoi(argv[7]);
t5 = atoi(argv[8]);

// ouverture du fichier
fic = fopen(argv[1], "a"); // ouvrir en ajout
if(fic == NULL){
printf("Impossible d'ouvrir le fichier %s\n", nom_fic);
exit(1);
}

// ajouter les donnees dans l'annuaire


fprintf(fic, "\n%s %s %.2d %.2d %.2d %.2d %.2d %s", nom, prenom,
t1, t2, t3, t4, t5, mail);

// fermeture du fichier
if(fclose(fic) == EOF){
printf("Probleme de fermeture du fichier %s", nom_fic);
exit(1);
}

printf("Les informations ont ete stockees dans l'annuaire\n");

return 0;
}
Exercices d’entrainement
 Exercice 1
 Exercice 2
 Exercice 3
 Exercice 4
 Exercice 5
 Exercice 6
 Exercice 7
 Exercice 8
 Exercice 9
 Exercice 10
 Exercice 11
 Exercice 12
 Exercice 13
 Exercice 14
 Exercice 15
 Exercice 16

Exercice 1

Créer sur disque (C :) puis afficher à l'écran le fichier INFORM.TXT dont les informations sont
structurées de la manière suivante:

Numéro de matricule (entier)

Nom (chaîne de caractères)

Prénom (chaîne de caractères)

Le nombre d'enregistrements à créer est à entrer au clavier par l'utilisateur.

Exercice 2

Ecrire un programme qui crée sur disque un fichier INFBIS.TXT qui est la copie exacte
(enregistrement par enregistrement) du fichier INFORM.TXT.
Exercice 3

Ajouter un nouvel enregistrement (entré au clavier) à la fin de INFORM.TXT et sauver le


nouveau fichier sous le nom INFBIS.TXT.

Exercice 4

Insérer un nouvel enregistrement dans INFORM.TXT en supposant que le fichier est trié
relativement à la rubrique NOM et sauver le nouveau fichier sous le nom INFBIS.TXT.

Exercice 5

Supprimer dans INFORM.TXT tous les enregistrements:

a) dont le numéro de matricule se termine par 8

b) dont le prénom est "Mahdi" (utiliser strcmp)

c) dont le nom est un palindrome. Définir une fonction d'aide PALIN qui fournit le résultat 1
si la chaîne transmise comme paramètre est un palindrome, sinon la valeur zéro.

Sauver le nouveau fichier à chaque fois sous le nom INFBIS.TXT.

Exercice 6

Créer sur disque puis afficher à l'écran le fichier FAMILLE.TXT dont les informations sont
structurées de la manière suivante:

Nom de famille

Prénom du père

Prénom de la mère
Nombre d'enfants

Prénoms des enfants

Le nombre d'enregistrements à créer est entré au clavier.

Attention: Le nombre de rubriques des enregistrements varie avec le nombre d'enfants !

Exercice 7

Ecrire un programme qui crée sur disque le fichier MOTS.TXT contenant une série de 50
mots au maximum (longueur maximale d'un mot: 50 caractères). La saisie des mots se
terminera à l'introduction du symbole '*' qui ne sera pas écrit dans le fichier.

Exercice 8

Ecrire un programme qui affiche le nombre de mots, le nombre de palindromes ainsi que la
longueur moyenne des mots contenus dans le fichier MOTS.TXT.

Exercice 9

Ecrire un programme qui charge les mots du fichier MOTS.TXT dans la mémoire centrale, les
trie d'après la méthode par propagation (méthode de la bulle) et les écrit dans un deuxième
fichier MOTS_TRI.TXT sur la disque. Les mots seront mémorisés à l'aide d'un tableau de
pointeurs sur char et la mémoire nécessaire sera réservée de façon dynamique.

Exercice 10

A l'aide d'un éditeur de textes, créer un fichier NOMBRES.TXT qui contient une liste de
nombres entiers. Dans le fichier, chaque nombre doit être suivi par un retour à la ligne.
Ecrire un programme qui affiche les nombres du fichier, leur somme et leur moyenne.
Exercice 11

Ecrire un programme qui remplace, dans un fichier contenant un texte, les retours à la ligne
par des espaces. Si plusieurs retours à la ligne se suivent, seulement le premier sera
remplacé. Les noms des fichiers source et destination sont entrés au clavier.

Exercice 12

Ecrire un programme qui détermine dans un fichier un texte dont le nom est entré au
clavier, le nombre de phrases terminées par un point, un point d'interrogation ou un point
d'exclamation.

Utiliser une fonction d'aide FIN_PHRASE qui décide si un caractère transmis comme
paramètre est un des séparateurs mentionnés ci-dessus. FIN_PHRASE retourne la valeur
(logique) 1 si le caractère est égal à '.', '!' ou'?' et 0 dans le cas contraire.

Exercice 13

Ecrire un programme qui détermine dans un fichier un texte dont le nom est entré au
clavier:

- le nombre de caractères qu'il contient,

- le nombre de chacune des lettres de l'alphabet

(sans distinguer les majuscules et les minuscules),

- le nombre de mots,

- le nombre de paragraphes (c.-à-d.: des retours à la ligne),

Les retours à la ligne ne devront pas être comptabilisés dans les caractères. On admettra que
deux mots sont toujours séparés par un ou plusieurs des caractères suivants:

- fin de ligne
- espace

- ponctuation: . : , ; ? !

- parenthèses: ( )

- guillemets: "

- apostrophe: '

Utiliser une fonction d'aide SEPA qui décide si un caractère transmis comme paramètre est
l'un des séparateurs mentionnés ci-dessus. SEPA restituera la valeur (logique) 1 si le
caractère est un séparateur et 0 dans le cas contraire. SEPA utilise un tableau qui contient les
séparateurs à détecter.

Exemple:

Nom du fichier texte : C:LITTERA.TXT


Votre fichier contient:
12 paragraphes
571 mots
4186 caractères
dont
279 fois la lettre a
56 fois la lettre b
...
3 fois la lettre z
et 470 autres caractères

Exercice 14

Ecrire un programme qui affiche le contenu d'un fichier texte sur un écran de 25 lignes et 80
colonnes en attendant la confirmation de l'utilisateur (par 'Enter') après chaque page
d'écran. Utiliser la fonction getchar.

Exercice 15

Ecrire un programme qui vérifie la validité d'une série de numéros de CB (Cartes Bancaires)
mémorisés dans un fichier. Un numéro de CB est composé de trois parties: un numéro de
compte, un séparateur '-' et un numéro de contrôle. Un numéro de CB est correct:
- si le reste de la division entière de la valeur devant le séparateur '-' par 97 est différent de
zéro et égal à la valeur de contrôle.

- si le reste de la division par 97 est zéro et la valeur de contrôle est 97.

Exemple:

Nombre de CB 15742-28 : 15742 modulo 97 = 28 correct


Nombre de CB 72270-5 : 72270 modulo 97 = 5 correct
Nombre de CB 22610-10 : 22610 modulo 97 = 9 incorrect
Nombre de CB 50537-0 : 50537 modulo 97 = 0
nombre incorrect, car la valeur de contrôle devrait être 97.
Nombre de CB 50537-97 : 50537 modulo 97 = 0 correct

Utiliser une fonction CB _TEST qui obtient comme paramètres les deux parties numériques
d'un nombre de CB et qui affiche alors un message indiquant si le numéro de CB est valide
ou non.

Pour tester le programme, créer à l'aide d'un éditeur de texte un fichier CB.TXT qui contient
les numéros ci-dessus, suivis par des retours à la ligne.

Exercice 16

Deux fichiers FA et FB dont les noms sont à entrer au clavier contiennent des nombres
entiers triés dans l'ordre croissant. Ecrire un programme qui copie le contenu de FA et FB
respectivement dans les tableaux TABA et TABB dans la mémoire centrale. Les tableaux
TABA et TABB sont fusionnés dans un troisième tableau trié en ordre croissant TABC. Après
la fusion, la tableau TABC est sauvé dans un fichier FC dont le nom est à entrer au clavier.

La mémoire pour TABA, TABB et TFUS dont les nombres d'éléments sont inconnus, est
réservée dynamiquement après que les longueurs des fichiers FA et FB ont été détectées.
Corrigés des exercices d’entrainement
Exercice 1

#include <stdio.h>
#include <stdlib.h>
main()
{
/* Déclarations : */
/* Nom du fichier et pointeur de référence */
char NOM_FICH[] = "C:\\INFORM.TXT";
FILE *FICHIER;
/* Autres variables */
char NOM[30], PRENOM[30];
int MATRICULE;
int I,N_ENR;

/* Ouverture du nouveau fichier en écriture */


FICHIER = fopen(NOM_FICH, "w");
if (!FICHIER)
{
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", NOM_FICH);
exit(-1);
}
/* Saisie des données et création du fichier */
printf("*** Création du fichier %s ***\n", NOM_FICH);
printf("Nombre d'enregistrements à créer : ");
scanf("%d",&N_ENR);
for (I=1; I<=N_ENR; I++)
{
printf("Enregistrement No: %d \n", I);
printf("Numéro de matricule : ");
scanf("%d",&MATRICULE);
printf("Nom : ");
scanf("%s",NOM);
printf("Prénom : ");
scanf("%s",PRENOM);
fprintf(FICHIER, "%d\n%s\n%s\n", MATRICULE, NOM, PRENOM);
}
/* Fermeture du fichier */
fclose(FICHIER);

/* Ouverture du fichier en lecture */


FICHIER = fopen(NOM_FICH, "r");
if (!FICHIER)
{
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", NOM_FICH);
exit(-1);
}
/* Affichage du fichier */
printf("*** Contenu du fichier %s ***\n", NOM_FICH);
while (!feof(FICHIER))
{
fscanf(FICHIER, "%d\n%s\n%s\n", &MATRICULE, NOM, PRENOM);
printf("Matricule : %d\t", MATRICULE);
printf("Nom et prénom : %s %s\n", NOM, PRENOM);
}
/* Fermeture du fichier */
fclose(FICHIER);
return 0;
}

Exercice 2

#include <stdio.h>
#include <stdlib.h>
main()
{
/* Déclarations : */
/* Noms des fichiers et pointeurs de référence */
char ANCIEN[] = "C:\\INFORM.TXT";
char NOUVEAU[] = "C:\\INFBIS.TXT";
FILE *INFILE, *OUTFILE;
/* Autres variables */
char NOM[30], PRENOM[30];
int MATRICULE;

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


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

/* Copie de tous les enregistrements */


while (!feof(INFILE))
{
fscanf (INFILE, "%d\n%s\n%s\n", &MATRICULE, NOM, PRENOM);
fprintf(OUTFILE, "%d\n%s\n%s\n", MATRICULE, NOM, PRENOM);
}
/* Fermeture des fichiers */
fclose(OUTFILE);
fclose(INFILE);
return 0;
}
Exercice 3

#include <stdio.h>
#include <stdlib.h>
main()
{
/* Déclarations : */
/* Noms des fichiers et pointeurs de référence */
char ANCIEN[] = "C:\\INFORM.TXT";
char NOUVEAU[] = "C:\\INFBIS.TXT";
FILE *INFILE, *OUTFILE;
/* Autres variables */
char NOM[30], PRENOM[30];

int MATRICULE;
char NOM_NOUV[30], PRE_NOUV[30];
int MATRI_NOUV;
/* Ouverture de l'ancien fichier en lecture */
INFILE = fopen(ANCIEN, "r");
if (!INFILE)
{
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", ANCIEN);
exit(-1);
}
/* Ouverture du nouveau fichier en écriture */
OUTFILE = fopen(NOUVEAU, "w");
if (!OUTFILE)
{
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", NOUVEAU);
exit(-1);
}

/* Saisie de l'enregistrement à ajouter */


printf("Enregistrement à ajouter : \n");
printf("Numéro de matricule : ");
scanf("%d",&MATRI_NOUV);
printf("Nom : ");
scanf("%s",NOM_NOUV);
printf("Prénom : ");
scanf("%s",PRE_NOUV);
/* Copie des enregistrements de l'ancien fichier */
while (!feof(INFILE))
{
fscanf (INFILE, "%d\n%s\n%s\n", &MATRICULE, NOM, PRENOM);
fprintf(OUTFILE, "%d\n%s\n%s\n", MATRICULE, NOM, PRENOM);
}
/* Ecriture du nouvel enregistrement à la fin du fichier */
fprintf(OUTFILE,"%d\n%s\n%s\n",MATRI_NOUV,NOM_NOUV,PRE_NOUV);
/* Fermeture des fichiers */
fclose(OUTFILE);
fclose(INFILE);
return 0;
}

Exercice 4

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main()
{
/* Déclarations : */
/* Noms des fichiers et pointeurs de référence */
char ANCIEN[] = "C:\\INFORM.TXT";
char NOUVEAU[] = "C:\\INFBIS.TXT";
FILE *INFILE, *OUTFILE;
/* Autres variables */
char NOM[30], PRENOM[30];
int MATRICULE;
char NOM_NOUV[30], PRE_NOUV[30];
int MATRI_NOUV;
int TROUVE;

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


INFILE = fopen(ANCIEN, "r");
if (!INFILE)
{
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", ANCIEN);
exit(-1);
}

/* Ouverture du nouveau fichier en écriture */


OUTFILE = fopen(NOUVEAU, "w");
if (!OUTFILE)
{
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", NOUVEAU);
exit(-1);
}

/* Saisie de l'enregistrement à insérer */


printf("Enregistrement à ajouter : \n");
printf("Numéro de matricule : ");
scanf("%d",&MATRI_NOUV);
printf("Nom : ");
scanf("%s",NOM_NOUV);
printf("Prénom : ");
scanf("%s",PRE_NOUV);

/* Copie des enregistrements dont le nom */


/* précéde lexicogr. celui à insérer. */
TROUVE = 0;
while (!feof(INFILE) && !TROUVE)
{
fscanf (INFILE, "%d\n%s\n%s\n", &MATRICULE, NOM, PRENOM);
if (strcmp(NOM, NOM_NOUV) > 0)
TROUVE = 1;
else
fprintf(OUTFILE, "%d\n%s\n%s\n", MATRICULE,NOM,PRENOM);
}

/* Ecriture du nouvel enregistrement, */


fprintf(OUTFILE,"%d\n%s\n%s\n",MATRI_NOUV,NOM_NOUV,PRE_NOUV);
/* et du dernier enregistrement lu. */
if (TROUVE)
fprintf(OUTFILE, "%d\n%s\n%s\n", MATRICULE, NOM, PRENOM);

/* Copie du reste des enregistrements */


while (!feof(INFILE))
{
fscanf (INFILE, "%d\n%s\n%s\n", &MATRICULE, NOM, PRENOM);
fprintf(OUTFILE, "%d\n%s\n%s\n", MATRICULE, NOM, PRENOM);
}

/* Fermeture des fichiers */


fclose(OUTFILE);
fclose(INFILE);
return 0;
}

Exercice 5

a) Supprimer les enregistrements, dont le numéro de matricule se termine par 8

#include <stdio.h>
#include <stdlib.h>
main()
{
/* Déclarations : */
/* Noms des fichiers et pointeurs de référence */
char ANCIEN[] = "C:\\INFORM.TXT";
char NOUVEAU[] = "C:\\INFBIS.TXT";
FILE *INFILE, *OUTFILE;
/* Autres variables */
char NOM[30], PRENOM[30];
int MATRICULE;

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


INFILE = fopen(ANCIEN, "r");
if (!INFILE)
{
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", ANCIEN);
exit(-1);
}
/* Ouverture du nouveau fichier en écriture */
OUTFILE = fopen(NOUVEAU, "w");
if (!OUTFILE)
{
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", NOUVEAU);
exit(-1);
}
/* Copie de tous les enregistrements à l'exception */
/* de ceux dont le numéro de matricule se termine */
/* par 8. */
while (!feof(INFILE))
{
fscanf (INFILE, "%d\n%s\n%s\n", &MATRICULE, NOM, PRENOM);
if (MATRICULE%10 != 8)
fprintf(OUTFILE, "%d\n%s\n%s\n", MATRICULE,NOM,PRENOM);
}
/* Fermeture des fichiers */
fclose(OUTFILE);
fclose(INFILE);
return 0;
}

b) Supprimer les enregistrements, dont le prénom est "Mahdi" (utiliser strcmp)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main()
{
/* Déclarations */
. . .
/* Ouverture de l'ancien fichier en lecture */
. . .
/* Ouverture du nouveau fichier en écriture */
. . .
/* Copie de tous les enregistrements à l'exception */
/* de ceux dont le prénom est 'Mahdi'. */
while (!feof(INFILE))
{
fscanf (INFILE, "%d\n%s\n%s\n", &MATRICULE, NOM, PRENOM);
if (strcmp(PRENOM,"Mahdi") != 0)
fprintf(OUTFILE, "%d\n%s\n%s\n", MATRICULE,NOM,PRENOM);
}
/* Fermeture des fichiers */
. . .
}

c) Supprimer les enregistrements, dont le nom est un palindrome. Définir une fonction d'aide PALI qui
fournit le résultat 1 si la chaîne transmise comme paramètre est un palindrome, sinon la valeur zéro.

#include <stdio.h>
#include <stdlib.h>
main()
{
/* Prototype de la fonction PALI */
int PALI(char *CH);
/* Déclarations */
. . .
/* Ouverture de l'ancien fichier en lecture */
. . .
/* Ouverture du nouveau fichier en écriture */
. . .
/* Copie de tous les enregistrements à l'exception */
/* des palindromes. */
while (!feof(INFILE))
{
fscanf (INFILE, "%d\n%s\n%s\n", &MATRICULE, NOM, PRENOM);
if (!PALIN(NOM))
fprintf(OUTFILE, "%d\n%s\n%s\n", MATRICULE,NOM,PRENOM);
}
/* Fermeture des fichiers */
. . .
}

int PALIN(char *CH)


{
/* Variable locale */
char *CH2;
/* Placer CH2 à la fin de la chaîne */
for (CH2=CH; *CH2; CH2++)
;
CH2--;
/* Contrôler si la chaîne désignée par CH est un palindrome */
for (; CH<CH2; CH++,CH2--)
if (*CH != *CH2) return 0;
return 1;
}

Exercice 6

#include <stdio.h>
#include <stdlib.h>
main()
{
/* Déclarations : */
/* Nom du fichier et pointeur de référence */
char NOM_FICH[] = "C:\\FAMILLE.TXT";
FILE *FICHIER;
/* Autres variables */
char NOM[30], PERE[30], MERE[30], ENFANT[30];
int J,N_ENFANTS;
int I,N_ENR;

/* Ouverture du nouveau fichier en écriture */


FICHIER = fopen(NOM_FICH, "w");
if (!FICHIER)
{
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", NOM_FICH);
exit(-1);
}

/* Saisie des données et création du fichier */


printf("*** Création du fichier %s ***\n", NOM_FICH);
printf("Nombre d'enregistrements à créer : ");
scanf("%d",&N_ENR);
for (I=1; I<=N_ENR; I++)
{
printf("Enregistrement No: %d \n", I);
printf("Nom de famille : ");
scanf("%s", NOM);
printf("Prénom du père : ");
scanf("%s", PERE);
printf("Prénom de la mère : ");
scanf("%s", MERE);
printf("Nombre d'enfants : ");
scanf("%d", &N_ENFANTS);
fprintf(FICHIER, "%s\n%s\n%s\n%d\n",
NOM, PERE, MERE, N_ENFANTS);
for (J=1; J<=N_ENFANTS; J++)
{
printf("Prénom %d. enfant : ", J);
scanf("%s", ENFANT);
fprintf(FICHIER, "%s\n", ENFANT);
}
}
/* Fermeture du fichier */
fclose(FICHIER);
/* Réouverture du fichier */
FICHIER = fopen(NOM_FICH, "r");
if (!FICHIER)
{
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", NOM_FICH);
exit(-1);
}
/* Affichage du fichier */
printf("*** Contenu du fichier %s ***\n", NOM_FICH);
while (!feof(FICHIER))
{
fscanf (FICHIER, "%s\n%s\n%s\n%d\n",
NOM, PERE, MERE, &N_ENFANTS);
printf("\n");
printf("Nom de famille : %s\n", NOM);
printf("Nom du père : %s %s\n", PERE, NOM);
printf("Nom de la mère : %s %s\n", MERE, NOM);
printf("Noms des enfants : \n", N_ENFANTS);
for (J=1; J<=N_ENFANTS; J++)
{
fscanf(FICHIER, "%s\n", ENFANT);
printf("\t%d. : %s %s\n", J, ENFANT, NOM);
}
}
/* Fermeture du fichier */
fclose(FICHIER);
return 0;
}

Exercice 11.7

#include <stdio.h>
#include <stdlib.h>
main()
{
/* Déclarations : */
/* Nom du fichier et pointeur de référence */
char NOM_FICH[] = "C:\\MOTS.TXT";
FILE *FICHIER;
/* Autres variables */
char CHAINE[50];

/* Ouverture du nouveau fichier en écriture */


FICHIER = fopen(NOM_FICH, "w");
if (!FICHIER)
{
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", NOM_FICH);
exit(-1);
}
/* Saisie des données et création du fichier */
printf("*** Création du fichier %s ***\n", NOM_FICH);
do
{
printf("Entrez un mot ('*' pour finir) : ");
scanf("%s", CHAINE);
if (CHAINE[0] != '*')
fprintf(FICHIER, "%s\n", CHAINE);
}
while (CHAINE[0] != '*');
/* Fermeture du fichier */
fclose(FICHIER);
return 0;
}

Exercice 11.8

#include <stdio.h>
#include <stdlib.h>
main()
{
/* Prototypes des fonctions appelées */
int PALI(char *CH);
int LONG_CH(char *CH);
/* Déclarations : */
/* Nom du fichier et pointeur de référence */
char NOM_FICH[] = "C:\\MOTS.TXT";
FILE *FICHIER;
/* Autres variables */
char CHAINE[50];
int N_PALI; /* nombre de palindromes */
int N_MOTS; /* nombre de mots */
int L_TOT; /* longueur totale de tous les mots */

/* Ouverture du nouveau fichier en écriture */


FICHIER = fopen(NOM_FICH, "r");
if (!FICHIER)
{
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", NOM_FICH);
exit(-1);
}
/* Compter les palindromes et accumuler */
/* les longueurs des mots. */
L_TOT =0;
N_PALI=0;
N_MOTS=0;
while (!feof(FICHIER))
{
fscanf(FICHIER, "%s\n", CHAINE);
N_MOTS++;
L_TOT += LONG_CH(CHAINE);
N_PALI += PALI(CHAINE);
}
/* Fermeture du fichier */
fclose(FICHIER);
/* Affichage des résultats */
printf("Le fichier %s contient :\n", NOM_FICH);
printf("\t%d \tmots d'une longueur moyenne de :\n", N_MOTS);
printf("\t%.1f \tcaractères et\n", (float)L_TOT/N_MOTS);
printf("\t%d \tpalindromes\n", N_PALI);
return 0;
}

int PALI(char *CH)


{
/* Variable locale */
char *CH2;
/* Placer CH2 à la fin de la chaîne */
for (CH2=CH; *CH2; CH2++)
;
CH2--;
/* Contrôler si la chaîne désignée par CH est un palindrome */
for (; CH<CH2; CH++,CH2--)
if (*CH != *CH2) return 0;
return 1;
}

int LONG_CH(char *CH)


{
char *P;
for (P=CH ; *P; P++) ;
return P-CH;
}

Exercice 9

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main()
{
/* Déclarations : */
/* Noms des fichiers et pointeurs de référence */
char ANCIEN[] = "C:\\MOTS.TXT";
char NOUVEAU[] = "C:\\MOTS_TRI.TXT";
FILE *INFILE, *OUTFILE;
/* Tableau de pointeurs */
char *TAB[50];
/* Autres variables */
char CHAINE[50];
char *AIDE; /* pour la permutation */
int N_MOTS; /* nombre de mots du fichier */
int I; /* ligne à partir de laquelle TAB est trié */
int J; /* indice courant */
int FIN; /* ligne où la dernière permutation a eu lieu */
/* permet de ne pas trier un sous-ensemble déjà trié */

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


INFILE = fopen(ANCIEN, "r");
if (!INFILE)
{
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", ANCIEN);
exit(-1);
}
/* Initialisation du du compteur des mots */
N_MOTS = 0;
/* Lecture du fichier dans la mémoire centrale */
while (!feof(INFILE))
{
fscanf (INFILE, "%s\n", CHAINE);
/* Réservation de la mémoire */
TAB[N_MOTS] = malloc(strlen(CHAINE)+1);
if (TAB[N_MOTS])
strcpy(TAB[N_MOTS], CHAINE);
else
{
printf("\aPas assez de mémoire \n");
exit(-1);
}
N_MOTS++;
}
/* Fermeture du fichier */
fclose(INFILE);
/* Tri du tableau par propagation de l'élément maximal. */
for (I=N_MOTS-1 ; I>0 ; I=FIN)
{
FIN=0;
for (J=0; J<I; J++)
if (strcmp(TAB[J],TAB[J+1])>0)
{
FIN=J;
AIDE = TAB[J];
TAB[J] = TAB[J+1];
TAB[J+1] = AIDE;
}
}
/* Ouverture du nouveau fichier en écriture */
OUTFILE = fopen(NOUVEAU, "w");
if (!OUTFILE)
{
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", NOUVEAU);
exit(-1);
}
/* Copie du tableau dans le nouveau fichier */
for (I=0; I<N_MOTS; I++)
fprintf(OUTFILE, "%s\n", TAB[I]);
/* Fermeture du fichier */
fclose(OUTFILE);
return 0;
}

Exercice 10

#include <stdio.h>
#include <stdlib.h>
main()
{
/* Déclarations : */
/* Noms des fichiers et pointeurs de référence */
char NOM_FICH[] = "C:\\NOMBRES.TXT";
FILE *FICHIER;
/* Autres variables */
int NOMBRE; /* nombre actuel lu dans le fichier */
int N; /* compteur des nombres */
long SOMME; /* somme des nombres */

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


FICHIER = fopen(NOM_FICH, "r");
if (!FICHIER)
{
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", NOM_FICH);
exit(-1);
}
/* Lecture du fichier et comptabilité */
N=0;
SOMME=0;
while (!feof(FICHIER))
{
fscanf (FICHIER, "%d\n", &NOMBRE);
SOMME += NOMBRE;
N++;
}
/* Fermeture du fichier */
fclose(FICHIER);
/* Affichage des résultats */
printf("Le fichier %s contient %d nombres.\n", NOM_FICH, N);
printf("La somme des nombres est : %ld\n", SOMME);
printf("La moyenne des nombres est : %f\n", (float)SOMME/N);
return 0;
}

Exercice 11

#include <stdio.h>

main()
{
/* Déclarations : */
/* Noms des fichiers et pointeurs de référence */
char ANCIEN[30], NOUVEAU[30];
FILE *INFILE, *OUTFILE;
/* Autres variables */
char C; /* caractère lu dans le fichier */
char N_RET; /* Compteur des retours à la ligne consécutifs */

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


do
{
printf("Nom du fichier source : ");
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);

/* Copier tous les caractères et remplacer le */


/* premier retour à la ligne d'une suite par */
/* un espace. */
N_RET=0;
while (!feof(INFILE))
{
C=fgetc(INFILE);
if (!feof(INFILE))
{
if (C == '\n')
{
N_RET++;
if (N_RET > 1)
fputc('\n', OUTFILE);
else
fputc(' ', OUTFILE);
}
else
{
N_RET=0;
fputc(C, OUTFILE);
}
}
}
/* Fermeture des fichiers */
fclose(OUTFILE);
fclose(INFILE);
return 0;
}
Remarque :

Après la lecture par fgetc, il faut s'assurer encore une fois que le caractère lu est différent de EOF.
Nous obtenons ainsi une construction un peu lourde:

while (!feof(INFILE))
{
C=fgetc(INFILE);
if (!feof(INFILE))
{
. . .
}
}

Il est possible de réunir plusieurs instructions dans le bloc conditionnel de la structure while, en les
séparant par des virgules. En pratique, on retrouve cette solution souvent pour éviter des
constructions inutilement lourdes:

while (C=fgetc(INFILE), !feof(INFILE))


{
. . .
}
Exercice 12

#include <stdio.h>
main()
{
/* Prototype de la fonction FIN_PHRASE */
int FIN_PHRASE(char C);
/* Déclarations : */
/* Noms des fichiers et pointeurs de référence */
char NOM_FICH[30];
FILE *FICHIER;
/* Autres variables */
char C; /* caractère lu dans le fichier */
char NP; /* Compteur de phrases */

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


do
{
printf("Nom du fichier texte : ");
scanf("%s", NOM_FICH);
FICHIER = fopen(NOM_FICH, "r");
if (!FICHIER)
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", NOM_FICH);
}
while (!FICHIER);
/* Compter les symboles de fin de phrase */
NP=0;
while (!feof(FICHIER))
NP += FIN_PHRASE(fgetc(FICHIER));
/* Fermeture du fichier */
fclose(FICHIER);
/* Affichage du résultat */
printf("Le fichier %s contient %d phrases.\n", NOM_FICH, NP);
return 0;
}

int FIN_PHRASE(char C)
{
return (C=='.' || C=='!' || C=='?');
}

Exercice 11.13

#include <stdio.h>
main()
{
/* Prototype de la fonction FIN_PHRASE */
int SEPA(char C);
/* Déclarations : */
/* Noms des fichiers et pointeurs de référence */
char NOM_FICH[30];
FILE *FICHIER;

/* Autres variables */
char C; /* caractère lu dans le fichier */
int ABC[26]; /* compteurs des lettres de l'alphabet */
int NTOT; /* nombre total des caractères */
int NAUTRES; /* nombre des caractères qui ne font pas
partie de l'alphabet */
int NMOTS; /* nombre des mots */
int NPARA; /* nombre de paragraphes (retours à la ligne) */
int I; /* indice d'aide */
int DANS_MOT; /* indicateur logique: */
/* vrai si la tête de lecture se trouve */
/* actuellement à l'intérieur d'un mot. */

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


do
{
printf("Nom du fichier texte : ");
scanf("%s", NOM_FICH);
FICHIER = fopen(NOM_FICH, "r");
if (!FICHIER)
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", NOM_FICH);
}
while (!FICHIER);
/* Initialisations des variables */
for (I=0; I<26; I++)
ABC[I]=0;
NTOT =0;
NAUTRES =0;
NMOTS =0;
NPARA =0;
DANS_MOT=0;
/* Examination des caractères du fichier */
while (!feof(FICHIER))
{
C=fgetc(FICHIER);
if (!feof(FICHIER))
{
/* Comptage au niveau caractères */
if (C=='\n')
NPARA++;
else
{
NTOT++;
if (C>='a' && C<='z')
ABC[C-'a']++;
else if (C>='A' && C<='Z')
ABC[C-'A']++;
else
NAUTRES++;
}

/* Comptage des mots */


if (SEPA(C))
{
if (DANS_MOT)
{
NMOTS++;
DANS_MOT=0;
}
}
else
DANS_MOT=1;
}
}
/* Fermeture du fichier */
fclose(FICHIER);
/* Affichage du résultat */
printf("Votre fichier contient :\n");
printf("\t%d paragraphes\n", NPARA);
printf("\t%d mots\n", NMOTS);
printf("\t%d caractères\ndont\n", NTOT);
for (I=0; I<26; I++)
printf("\t%d fois la lettre %c\n", ABC[I], 'a'+I);
printf("et %d autres caractères\n", NAUTRES);
return 0;
}

int SEPA(char C)
{
/* Tableau contenant tous les séparateurs de mots */
char SEP[12] = { '\n', ' ', ',', ';', '.', ':',
'?', '!', '(', ')', '"', '\'' };
int I;

/* Comparaison de C avec tous les éléments du tableau */


for (I=0 ; C!=SEP[I] && I<12 ; I++) ;
if (I==12)
return 0;
else
return 1;
/* ou bien simplement : */
/* return (I != 12); */
}

Exercice 14

#include <stdio.h>
main()
{
/* Noms des fichiers et pointeurs de référence */
char NOM_FICH[30];
FILE *FICHIER;
/* Autres variables */
char C; /* caractère actuel */
int NLIGNE, NCOLO; /* position actuelle sur l'écran */

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


do
{
printf("Nom du fichier texte : ");
scanf("%s", NOM_FICH);
FICHIER = fopen(NOM_FICH, "r");
if (!FICHIER)
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", NOM_FICH);
}
while (!FICHIER) ;
getchar();
/* Initialisations des variables */
NLIGNE = 0; NCOLO = 0;
/* Affichage du fichier */
while (!feof(FICHIER))
{
C=fgetc(FICHIER);
if (!feof(FICHIER))
{
NCOLO++;
if (NCOLO==80 || C=='\n') /* fin de la ligne */
{
NLIGNE++;
if (NLIGNE==25) /* fin de l'écran */
{
getchar();
NLIGNE=1;
}
printf("%c",C);
NCOLO=1;
}
else
printf("%c",C);
}
}
/* Fermeture du fichier */
fclose(FICHIER);
return 0;
}

Exercice 15

#include <stdio.h>
#include <stdlib.h>
main()
{
/* Prototype de la fonction CB _TEST */
void CB_TEST(long COMPTE, int CONTROLE);
/* Déclarations : */
/* Noms des fichiers et pointeurs de référence */
char NOM_FICH[] = "C:\\CB.TXT";
FILE *FICHIER;
/* Autres variables */
long COMPTE; /* nombre du compte CB */
int CONTROLE; /* nombre de contrôle */

/* Ouverture du fichier CB.TXT en lecture */


FICHIER = fopen(NOM_FICH, "r");
if (!FICHIER)
{
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", NOM_FICH);
exit(-1);
}

/* Lecture des nombres et appel de la fonction CB_TEST */


/* A l'aide de la chaîne de format, scanf lit les deux */
/* parties du nombre de CB, les convertit en long resp. */
/* en int et affecte les résultats aux variables COMPTE */
/* et CONTROLE. */
while (!feof(FICHIER))
{
fscanf (FICHIER, "%ld-%d\n", &COMPTE, &CONTROLE);
CB_TEST(COMPTE, CONTROLE);
}
/* Fermeture du fichier */
fclose(FICHIER);
return 0;
}

void CB_TEST(long COMPTE, int CONTROLE)


{
int RESTE;
RESTE = COMPTE % 97;
if (RESTE == 0)
RESTE = 97;
if (RESTE == CONTROLE)
printf ("Le nombre CB %ld-%d est valide\n",
COMPTE, CONTROLE);
else
printf ("Le nombre CB %ld-%d n'est pas valide\n",
COMPTE, CONTROLE);
}

Exercice 16

#include <stdio.h>
#include <stdlib.h>
main()
{
/* Prototype de la fonction FUSION */
void FUSION(int *A, int *B, int *FUS, int N, int M);
/* Déclarations : */
/* Noms des fichiers et pointeurs de référence */
char FICH_A[30], FICH_B[30], FICH_FUS[30];
FILE *FA, *FB, *FFUS;
/* Autres variables */
int *TABA, *TABB, *TFUS; /* pointeurs pour les tableaux */
int LA, LB; /* Longueurs de FA et FB */
int N; /* Nombre lu ou écrit dans un fichier */
int I; /* Indice d'aide */

/* Ouverture du fichier FA en lecture */


do
{
printf("Nom du fichier FA : ");
scanf("%s", FICH_A);
FA = fopen(FICH_A, "r");
if (!FA)
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", FICH_A);
}
while (!FA);
/* Détection de la longueur de FA */
for (LA=0; !feof(FA); LA++)
fscanf(FA,"%d\n", &N);
/* Fermeture du fichier FA */
fclose(FA);
/* Allocation de la mémoire pour TABA */
TABA = malloc (LA*sizeof(int));
if (!TABA)
{
printf("\a Pas assez de mémoire pour TABA\n");
exit(-1);
}

/* Réouverture du fichier FA en lecture */


FA = fopen(FICH_A, "r");
/* Copie du contenu de FA dans TABA */
for (I=0; I<LA; I++)
fscanf(FA,"%d\n", TABA+I);
/* Fermeture du fichier FA */
fclose(FA);

/* Mêmes opérations pour FB : */


/* Ouverture du fichier FB en lecture */
do
{
printf("Nom du fichier FB : ");
scanf("%s", FICH_B);
FB = fopen(FICH_B, "r");
if (!FB)
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", FICH_B);
}
while (!FB);
/* Détection de la longueur de FB */
for (LB=0; !feof(FB); LB++)
fscanf(FB,"%d\n", &N);
/* Fermeture du fichier FB */
fclose(FB);
/* Allocation de la mémoire pour TABB */
TABB = malloc (LB*sizeof(int));
if (!TABB)
{
printf("\a Pas assez de mémoire pour TABB\n");
exit(-1);
}
/* Réouverture du fichier FB en lecture */
FB = fopen(FICH_B, "r");
/* Copie du contenu de FB dans TABB */
for (I=0; I<LB; I++)
fscanf(FB,"%d\n", TABB+I);
/* Fermeture du fichier FB */
fclose(FB);

/* Allocation de la mémoire pour TFUS */


TFUS = malloc ((LA+LB)*sizeof(int));
if (!TFUS)
{
printf("\a Pas assez de mémoire pour TFUS\n");
exit(-1);
}

/* Fusion des tableaux TA et TB dans TFUS */


FUSION (TABA, TABB, TFUS, LA, LB);

/* Ouverture du fichier FFUS en écriture */


do
{
printf("Nom du fichier FFUS : ");
scanf("%s", FICH_FUS);
FFUS = fopen(FICH_FUS, "w");
if (!FFUS)
printf("\aERREUR: Impossible d'ouvrir "
"le fichier: %s.\n", FICH_FUS);
}
while (!FFUS);
/* Copier le contenu de TFUS dans FFUS */
for (I=0; I<(LA+LB); I++)
fprintf(FFUS,"%d\n", *(TFUS+I));
/* Fermeture du fichier FFUS */
fclose(FFUS);
return 0;
}

void FUSION(int *A, int *B, int *FUS, int N, int M)


{
/* Variables locales */
/* Indices courants dans A, B et FUS */
int IA,IB,IFUS;

/* Fusion de A et B dans FUS */


IA=0, IB=0; IFUS=0;
while ((IA<N) && (IB<M))
if (*(A+IA)<*(B+IB))
{
*(FUS+IFUS)=*(A+IA);
IFUS++;
IA++;
}
else
{
FUS[IFUS]=B[IB];
IFUS++;
IB++;
}
/* Si A ou B sont arrivés à la fin, alors */
/* copier le reste de l'autre tableau. */
while (IA<N)
{
*(FUS+IFUS)=*(A+IA);
IFUS++;
IA++;
}
while (IB<M)
{
*(FUS+IFUS)=*(B+IB);
IFUS++;
IB++;
}
}
Algorithmique et programmation en C
Travaux dirigés corrigés
Travaux dirigés 1

Exercice 1 :
Ecrire un programme qui lit un caractère au clavier et affiche le caractère ainsi que son code
numérique en employant getchar et printf,
#include <stdio.h>
main()
{
int C ;
printf("introduire un caractère suivi de 'Enter'\n");
C = getchar();
printf("Le caractère %c a le code ASCII %d\n", C, C);
return 0;
}
Exercice 2 :
Ecrire un programme qui calcule et affiche la distance DIST (type double) entre deux points A et B
du plan dont les coordonnées (XA, YA) et (XB, YB) sont entrées au clavier comme entiers.

#include <stdio.h>
#include <math.h>
main()
{
int XA, YA, XB, YB;
double DIST;
/* Attention: La chaîne de format que nous utilisons */
/* s'attend à ce que les données soient séparées par */
/* une virgule lors de l'entrée. */
printf("Entrez les coordonnées du point A : XA,YA ");
scanf("%d,%d", &XA, &YA);
printf("Entrez les coordonnées du point B : XB,YB ");
scanf("%d,%d", &XB, &YB);
DIST=sqrt(pow(XA-XB,2)+pow(YA-YB,2));
printf("La distance entre A(%d,% d) et B(%d, %d) est %.2f\n",XA,
YA, XB, YB, DIST);
return 0;
}

Exercice 3 :
Ecrivez un programme qui calcule les solutions réelles d'une équation du second degré
ax2+bx+c = 0 en discutant la formule.
Utilisez une variable d'aide D pour la valeur du discriminant b2-4ac et décidez à l'aide de D, si
l'équation a une, deux ou aucune solution réelle. Utilisez des variables du type int pour A, B et C.
Considérez aussi les cas où l'utilisateur entre des valeurs nulles pour A; pour A et B; pour A, B et C.
Affichez les résultats et les messages nécessaires sur l'écran.
Modifier le programme afin de considérer le cas des solutions complexes.
#include <stdio.h>
#include <math.h>
main()
{
/* Calcul des solutions réelles et complexes d'une équation du
second degré */
int A, B, C;
double D; /* Discriminant */
printf("Calcul des solutions réelles et complexes d'une équation
du second \n");
printf("degré de la forme ax^2 + bx + c = 0 \n\n");
printf("Introduisez les valeurs pour a, b, et c : ");
scanf("%i %i %i", &A, &B, &C);
/* Calcul du discriminant b^2-4ac */
D = pow(B,2) - 4.0*A*C;
/* Distinction des différents cas */
if (A==0 && B==0 && C==0) /* 0x = 0 */
printf("Tout réel est une solution de cette équation.\n");
else if (A==0 && B==0) /* Contradiction: c # 0 et c = 0 */
printf("Cette équation ne possède pas de solutions.\n");
else if (A==0) /* bx + c = 0 */
{
printf("La solution de cette équation du premier degré est :\n");
printf(" x = %.4f\n", (double)C/B);
}
else if (D<0) /* b^2-4ac < 0 */
{
printf("Les solutions complexes de cette équation sont les
suivantes :\n");
printf(”x1 = %.4f + i%.4f\n”, (double)(-B),(double)(sqrt(-
D)/(2*A))) ;
printf(”x2 = %.4f + i%.4f\n”, (double)(-B),(double)(-sqrt(-
D)/(2*A))) ;
}
else if (D==0) /* b^2-4ac = 0 */
{
printf("Cette équation a une seule solution réelle :\n");
printf(" x = %.4f\n", (double)-B/(2*A));
}
else /* b^2-4ac > 0 */
{
printf("Les solutions réelles de cette équation sont :\n");
printf(" x1 = %.4f\n", (double)(-B+sqrt(D))/(2*A));
printf(" x2 = %.4f\n", (double)(-B-sqrt(D))/(2*A));
}
return 0;
}
Travaux dirigés 2
Exercice 1 :
Calculez la somme des N premiers termes de la série harmonique : 1 + 1/2 + 1/3 + ... + 1/N

#include <stdio.h>
main()
{
int N; /* nombre de termes à calculer */
int I; /* compteur pour la boucle */
float SOM; /* Type float à cause de la précision du résultat. */
do
{
printf ("Nombre de termes: ");
scanf ("%d", &N);
}while (N<1);
for (SOM=0.0, I=1 ; I<=N ; I++)
SOM += (float)1/I;
printf("La somme des %d premiers termes est %f \n", N, SOM);
return 0;
}
Exercice 2 :
Affichez un triangle isocèle formé d'étoiles de N lignes (N est
fourni au clavier).
#include <stdio.h>
main()
{
int LIG; /* nombre de lignes */
int L; /* compteur des lignes */
int ESP; /* nombre d'espaces */
int I; /* compteur des caractères */
do
{
printf("Nombres de lignes : ");
scanf("%d", &LIG);
}while (LIG<1 || LIG>20);
for (L=0 ; L<LIG ; L++)
{
ESP = LIG-L-1;
for (I=0 ; I<ESP ; I++)
putchar(' ');
for (I=0 ; I<2*L+1 ; I++)
putchar('*');
putchar('\n');
}
return 0;
}

Exercice 3 :
a) Calculez la racine carrée X d'un nombre réel positif A par approximations successives en
utilisant la relation de récurrence suivante:
XJ+1 = (XJ + A/XJ) / 2 X1 = A
La précision du calcul J est à entrer par l'utilisateur.
b) Assurez-vous lors de l'introduction des données que la valeur pour A est un réel positif et que J
est un entier naturel positif, plus petit que 50.
c) Affichez lors du calcul toutes les approximations calculées :
La 1ère approximation de la racine carrée de ... est ...
La 2e approximation de la racine carrée de ... est ...
La 3e approximation de la racine carrée de ... est ...
...

#include <stdio.h>
main()
{
double A; /* donnée */
double X; /* approximation de la racine carrée de A */
int N; /* degré/précision de l'approximation */
int J; /* degré de l'approximation courante */
do
{
printf("Entrer le réel positif A : ");
scanf("%lf", &A);
}while(A<0);
do
{
printf("Entrer le degré de l'approximation : ");
scanf("%d", &N);
}
while(N<=0 || N>=50);
for(X=A, J=1 ; J<=N ; J++)
{
X = (X + A/X) / 2;
printf("La %2d%s approximation de la racine carrée"
" de %.2f est %.2f\n", J, (J==1)?"ère":"e", A, X);
}
return 0;
}
Exercice 4
Affiche la table des produits pour N variant de 1 à 10 :
X*Y I 0 1 2 3 4 5 6 7 8 9 10
--------------------------------------------------
0 I 0 0 0 0 0 0 0 0 0 0 0
1 I 0 1 2 3 4 5 6 7 8 9 10
2 I 0 2 4 6 8 10 12 14 16 18 20
3 I 0 3 6 9 12 15 18 21 24 27 30
4 I 0 4 8 12 16 20 24 28 32 36 40
5 I 0 5 10 15 20 25 30 35 40 45 50
6 I 0 6 12 18 24 30 36 42 48 54 60
7 I 0 7 14 21 28 35 42 49 56 63 70
8 I 0 8 16 24 32 40 48 56 64 72 80
9 I 0 9 18 27 36 45 54 63 72 81 90
10 I 0 10 20 30 40 50 60 70 80 90 100
#include <stdio.h>
main()
{
const int MAX = 10; /* nombre de lignes et de colonnes */
int I; /* compteur des lignes */
int J; /* compteur des colonnes */
/* Affichage de l'en-tête */
printf(" X*Y I");
for (J=0 ; J<=MAX ; J++)
printf("%4d", J);
printf("\n");
printf("------");
for (J=0 ; J<=MAX ; J++)
printf("----");
printf("\n");
/* Affichage du tableau */
for (I=0 ; I<=MAX ; I++)
{
printf("%3d I", I);
for (J=0 ; J<=MAX ; J++)
printf("%4d", I*J);
printf("\n");
}
return 0;
}
Travaux dirigés 3
Exercice 1
Ecrire un programme qui saisit la dimension N d’un tableau de int (le tableau est initialement
définit avec une taille maximum MAX que N ne doit pas excéder) remplit le tableau par des valeurs
entrées au clavier et l’affiche.
Le programme doit ensuite effacer toutes les occurrences de la valeur 0 dans le tableau, tasser les
éléments restants et afficher le tableau ainsi modifier.
Pour cela écrire les fonctions suivantes :
void SaisirTableau (int *Tab, int N) ;
void AfficherTableau(int *Tab, int N) ;
int TasserTableau(int *Tab , int N) ;

#include <stdio.h>
#define MAX 50
void SaisirTableau(int *, int ) ;
void AfficherTableau(int *, int) ;
int TasserTableau(int *, int) ;
main()
{
/* Déclarations */
int T[MAX]; /* tableau donné */
int N,M; /* dimension */
/* Saisie de la dimension */
do
{
printf("Dimension du tableau (max.%d) : ",MAX);
scanf("%d", &N );
}while(N>MAX) ;
/* Saisie des données */
SaisirTableau(T,N) ;
/* Affichage du tableau */
AfficherTableau(T,N) ;
/*Tasser les elements du tableau */
M = TasserTableau(T,N) ;
/* Edition des résultats */
AfficherTableau(T ,M) ;
}
void SaisirTableau(int *Tab, int N)
{
int i ;
for (i=0; i<N; i++)
{
printf("Elément %d : ", i);
scanf("%d", &Tab[i]);
}
}
void AfficherTableau(int *Tab, int N)
{
int i ;
printf("Tableau donné : \n");
for (i=0; i<N; i++)
printf("%d ", Tab[i]);
printf("\n");
}
int TasserTableau(int * Tab, int N)
{
int i,j ;
/* Effacer les zéros et comprimer : */
/* Copier tous les éléments de i vers j et */
/* augmenter j pour les éléments non nuls. */
for (i=0, j=0 ; i<N ; i++)
{
Tab[j] = Tab[i] ;
if (Tab[i])
j++ ;
}
/* La nouvelle dimension du tableau est retournée */
return j ;
}

Exercice 2
Ecrire un programme qui saisit la dimension N d’un tableau de int remplit le tableau par des
valeurs entrées au clavier et l’affiche.
Copier ensuite toutes les composantes strictement positives dans un deuxième tableau Tpos et
toutes les valeurs strictement négatives dans un tableau Tneg. Afficher Tpos et Tneg.
Ecrire la fonction suivante :
int TrierTableau(int *, int *, int *,int)

#include <stdio.h>
#define MAX 50
main()
{
/* Déclarations */
/* Les tableaux et leurs dimensions */
int T[MAX], TPOS[MAX], TNEG[MAX];
int N,M, Npos, NNEG;
int I; /* indice courant */
/* Saisie de la dimension */
do
{
printf("Dimension du tableau (max.%d) : ",MAX);
scanf("%d", &N );
}while(N>MAX) ;
/* Saisie des données */
SaisirTableau(T,N) ;
/* Affichage du tableau */
AfficherTableau(T,N) ;
/*Tasser les elements du tableau */
M = TasserTableau(T,N) ;
/* Trier le tableau */
Npos = TrierTableau(T,TPOS,TNEG,M) ;
/* Edition des resultats */
printf(”Elements positifs : \n”) ;
AfficherTableau(TPOS,Npos) ;
printf(”Elements négatifs : \n”) ;
AfficherTableau(TNEG,N-Npos) ;
}
int TrierTableau(int *T, int *TPOS, int *TNEG, int N)
{
int npos=0, nneg=0;
int i ;
/* Transfert des données */
for (i=0; i<N; i++)
{
if (T[i]>0)
{
TPOS[npos]=T[i];
npos++;
}
if (T[i]<0)
{
TNEG[nneg]=T[i];
nneg++;
}
}
return npos ;
}

Exercice 3 :
Ecrire un programme qui calcul le produit scalaire de deux vecteurs d’entiers U et V de même
dimension.
Ecrire la fonction suivante :
long ProduitScalaire(int *U,int *V, int dimension)

#include <stdio.h>
#define MAX 50
long ProduitScalaire(int *,int *, int) ;
main()
{
/* Déclarations */
int U[MAX], V[MAX]; /* tableaux donnés */
int N; /* dimension */
int I; /* indice courant */
long PS; /* produit scalaire */
/* Saisie des données */
do
{
printf("Dimension du tableau (max.%d) : ",MAX);
scanf("%d", &N );
}while(N>MAX) ;
printf("** Premier tableau **\n");
for (I=0; I<N; I++)
{
printf("Elément %d : ", I);
scanf("%d", &U[I]);
}
printf("** Deuxième tableau **\n");
for (I=0; I<N; I++)
{
printf("Elément %d : ", I);
scanf("%d", &V[I]);
}
/* Calcul du produit scalaire */
PS = ProduitScalaire(U,V,N) ;
/* Edition du résultat */
printf("Produit scalaire : %ld\n", PS);
}
long ProduitScalaire(int *U, int *V,int N)
{
long ps ;
int i ;
for (ps=0, i=0; i<N; i++)
ps += (long)U[i]*V[i];
Return ps ;
}

Travaux dirigés 4
Exercice 1 :
Ecrire un programme qui lit les dimensions L et C d'un tableau T à deux dimensions du type int
(dimensions maximales: 50 lignes et 50 colonnes). Remplir le tableau par des valeurs entrées au
clavier et afficher le tableau ainsi que la somme de tous ses éléments.
Pour cela on écrira les fonctions suivantes :
void RemplirTableau(void)
void AfficherTableau(void)

#include <stdio.h>
void RemplirTableau(void) ;
void AfficherTableau(void) ;
int T[50][50]; /* tableau donné */
int L, C; /* dimensions */
main()
{
/* Déclarations */
long SOM; /* somme des éléments - type long */
/* Saisie des données */
printf("Nombre de lignes (max.50) : ");
scanf("%d", &L );
printf("Nombre de colonnes (max.50) : ");
scanf("%d", &C );
RemplirTableau() ;
AfficherTableau() ;
/* Calcul de la somme */
for (SOM=0, I=0; I<L; I++)
for (J=0; J<C; J++)
SOM += T[I][J];
/* Edition du résultat */
printf("Somme des éléments : %ld\n", SOM);
return 0;
}
void RemplirTableau(void)
{
int i,j ;
for (i=0; i<L; i++)
for (j=0; j<C; j++)
{
printf("Elément[%d][%d] : ",i,j);
scanf("%d", &T[i][j]);
}
}
void AfficherTableau(void)
{
int i,j ;
printf("Tableau donné :\n");
for (i=0; i<L; i++)
{
for (j=0; j<C; j++)
printf("%d\t", T[i][j]);
printf("\n");
}
}

Exercice 2 :
Ecrire un programme qui réalise l'addition de deux matrices A et B de même dimension N x M (N
et M sont saisies au clavier).
rappel :
| a | b | + | a’ | b’ | = | a + a’ | b + b’ |
| c | d | | c’ | d’ | | c + c‘ | d + d’ |

#include <stdio.h>
main()
{
/* Déclarations */
int A[50][50]; /* matrice donnée */
int B[50][50]; /* matrice donnée */
int C[50][50]; /* matrice résultat */
int N, M; /* dimensions des matrices */
int I, J; /* indices courants */
/* Saisie des données */
printf("Nombre de lignes (max.50) : ");
scanf("%d", &N );
printf("Nombre de colonnes (max.50) : ");
scanf("%d", &M );
printf("*** Matrice A ***\n");
for (I=0; I<N; I++)
for (J=0; J<M; J++)
{
printf("Elément[%d][%d] : ",I,J);
scanf("%d", &A[I][J]);
}
printf("*** Matrice B ***\n");
for (I=0; I<N; I++)
for (J=0; J<M; J++)
{
printf("Elément[%d][%d] : ",I,J);
scanf("%d", &B[I][J]);
}
/* Affichage des matrices */
printf("Matrice donnée A :\n");
for (I=0; I<N; I++)
{
for (J=0; J<M; J++)
printf("%7d", A[I][J]);
printf("\n");
}
printf("Matrice donnée B :\n");
for (I=0; I<N; I++)
{
for (J=0; J<M; J++)
printf("%7d", B[I][J]);
printf("\n");
}
/* Affectation du résultat de l'addition à C */
for (I=0; I<N; I++)
for (J=0; J<M; J++)
C[I][J] = A[I][J]+B[I][J];
/* Edition du résultat */
printf("Matrice résultat C :\n");
for (I=0; I<N; I++)
{
for (J=0; J<M; J++)
printf("%7d", C[I][J]);
printf("\n");
}
return 0;
}
Exercice 3 :
Ecrire un programme qui réalise le produit de deux matrices carrées de même dimension.
rappel :
| a | b | * | a’ | b’ | = | a *a’ + b*c’ | a*b’ + b*d’ |
| c | d | | c’ | d’ | | c*a’ + d*c‘ | c*b’ + d*d’ |

#include <stdio.h>
main()
{
/* Déclarations */
int A[50][50]; /* matrice donnée */
int B[50][50]; /* matrice donnée */
int C[50][50]; /* matrice résultat */
int N ; /* dimension des matrices (les matrices sont carrées)*/
int i,j,k; /* indices courants */
/* Saisie des données */
printf("Nombre de lignes et de colonnes (max.50) : ");
scanf("%d", &N );
printf("*** Matrice A ***\n");
for (i=0; i<N; i++)
for (j=0; j<N; j++)
{
printf("Elément[%d][%d] : ",i,j);
scanf("%d", &A[i][j]);
}
printf("*** Matrice B ***\n");
for (i=0; i<N; i++)
for (j=0; j<N; j++)
{
printf("Elément[%d][%d] : ",i,j);
scanf("%d", &B[i][j]);
}
/* Affichage des matrices */
printf("Matrice donnée A :\n");
for (i=0; i<N; i++)
{
for (j=0; j<N; j++)
printf("%7d", A[i][j]);
printf("\n");
}
printf("Matrice donnée B :\n");
for (i=0; i<N; i++)
{
for (j=0; j<N; j++)
printf("%7d", B[i][j]);
printf("\n");
}
/* Affectation du résultat du produit à C */
for (i=0; i<N; i++)
for (j=0; j<N; j++)
{
C[i][j] = 0 ;
for(k = 0 ; k<N ; k++)
C[i][j] += A[i][k]*B[k][j];
}
/* Edition du résultat */
printf("Matrice résultat C :\n");
for (i=0; i<N; i++)
{
for (j=0; j<N; j++)
printf("%7d", C[i][j]);
printf("\n");
}
}
Travaux dirigés 5
Exercice 1 :
Réécrire la fonction longueur (strln dans string.h) qui calcul la longueur d’une chaîne de caractères.
Prototype : int longueur(char *)

int longueur(char *chaine)


{
int i=0 ;
while(chaine[i] != ‘\0’)
i++ ;
return i ;
}
Exercice 2 :
En utilisant la précédence lexicographique écrire une fonction qui convertie les chaînes de
caractères minuscules en chaînes de caractères majuscules.
Prototype : void majuscule(char *)

#include<stdio.h>
void majuscule(char *) ;
main()
{
char chaine[] = "Ceci est une chaine !" ;
majuscule(chaine) ;
printf("%s\n",chaine) ;
}
void majuscule(char *chaine)
{
int i=0;
while(chaine[i] != '\0')
{
if ((chaine[i] >= 'a') && (chaine[i] <= 'z'))
chaine[i] += (int)'A' - (int)'a' ;
i++ ;
}
}
Exercice 3 :
Ecrire un programme qui lit deux chaînes de caractères, et qui indique leur précédence
lexicographique dans le code de caractères de la machine (ici: code ASCII). On écrira pour cela la
fonction precedence qui récupère les deux chaînes en paramètre et qui retourne 1 si la première
chaîne précède la deuxième, 2 si la deuxième précède la première, 0 si elle sont égale.
Prototype : int precedence(char *,char *)

#include <stdio.h>
int precedence(char *,char *) ;
main()
{
/* Déclarations */
char CH1[50], CH2[50]; /* chaînes à comparer */
int r ;
/* Saisie des données */
printf("Entrez la première chaîne à comparer : ");
gets(CH1);
printf("Entrez la deuxième chaîne à comparer : ");
gets(CH2);
r = precedence (CH1,CH2) ;
if(r==0)
printf("\"%s\" est égal à \"%s\"\n", CH1, CH2);
else if (r == 1)
printf("\"%s\" précède \"%s\"\n", CH1, CH2);
else
printf("\"%s\" précède \"%s\"\n", CH2, CH1);
}
int precedence (char *CH1,char *CH2)
{
int I; /* indice courant */
int r ;
for (I=0; (CH1[I]==CH2[I]) && CH1[I] && CH2[I]; I++) ;
if (CH1[I]==CH2[I])
r = 0 ;
else if (CH1[I]<CH2[I])
r = 1 ;
else
r = 2 ;
return r;
}
Exercice 4 :
Ecrire une procédure qui lit une chaîne de caractères et l'interprète comme un entier positif dans la
base décimale. On écrira 2 fonctions :
La fonction chaine2entier qui récupère une chaîne de caractère et retourne un entier.
Prototype : int chaine2entier(char *)
La fonction estentier qui récupère un caractère et retourne 0 s’il ne correspond pas à un chiffre 1
s’il correspond à un chiffre.
Prototype : int estentier(char) ;

#include<stdio.h>
int estentier(char) ;
int chaine2entier(char *) ;
main()
{
/* Déclarations */
char CH[100]; /* chaîne numérique à convertir */
long N; /* résultat numérique */
printf("Entrez un nombre entier et positif : ");
gets(CH);
printf("%s\n",CH) ;
N = chaine2entier(CH) ;
if(N<0)
printf("%s ne représente pas correctement un entier positif.\n",
CH);
else
printf("La chaine %s a pour valeur %d\n" ,CH,N) ;
}
int chaine2entier(char *CH)
{
int I;
int N = 0 ;
int OK = 1 ;
for (I=0; OK && CH[I]; I++)
if (estentier(CH[I]))
N = N*10 + (CH[I]-'0');
else
OK=0;
if (OK)
return N ;
else
return -1 ;
}
int estentier(char c)
{
if ((c>='0')&&(c<='9'))
return 1 ;
else
return 0 ;
}
Séries d’exercices supplémentaires
Série d’exercices 1 (Les variables)
1. Écrivez un programme qui permute les valeurs de deux variables lues au clavier

2. Écrivez un programme qui effectue une permutation circulaire vers la droite de 4 variables
lues au clavier

3. Écrivez un programme qui donne le maximum de 3 nombres lus au clavier et effectuez des
tests pour :
258
420
8 -6 1

4. Écrivez un programme qui calcule la moyenne de 4 nombres lus au clavier et donne le


minimum

5. Écrivez un programme qui calcule le prix TTC d'un prix HT entré au clavier

6. Écrivez un programme qui calcule le pourcentage d'un nombre, ce nombre ainsi que le
pourcentage sont entrés au clavier

7. Écrivez un programme qui donne une température en degrés celsius à partir d'une
température Fahrenheit (C = (5/9) * (F - 32))

8. Écrivez un programme qui donne la mention d'un étudiant en fonction de sa note entrée au
clavier

Attention, lorsque vous réalisez une division, le type du résultat dépend de la valeur du diviseur et
du dividende : la division 5/9 fournira la valeur 0, la division 5.0/9.0 fournira la valeur 0.55

Si vous utilisez des variables entières dans une division et que vous voulez un résultat réel, vous
pouvez changer leur type en écrivant : (float)nom_var_dividende / (float)nom_var_diviseur
Série d’exercices 2 (Structures de contrôle)
1. Écrivez le programme qui affiche chaque numéro de marche montée par un robot qui se
rend au 3ème étage, sachant qu'un étage comporte 20 marches

2. Écrivez un programme qui calcule la moyenne des notes entrées itérativement au clavier et
qui affiche la moyenne quand l'utilisateur entre -1

3. Écrivez un programme qui calcule la factorielle d'un nombre entré au clavier

4. Modifiez ce programme pour qu'il demande le nombre dont on souhaite calculer la


factorielle jusqu'à ce que l'utilisateur entre -1

5. Donnez le programme qui affiche le nombre de marches et le numéro de l'étage montés,


sachant que le nombre de marches par étage et le nombre d'étages à monter sont entrés au
clavier. Utilisez deux boucles while.

Qu'est-ce qui sera affiché sur la console si on entre au clavier 2 pour l'étage et 0 pour le
nombre de marches par étage ?

Qu'est-ce qui sera affiché sur la console si on entre au clavier 0 pour l'étage et 0 pour le
nombre de marches par étage ?

6. Écrivez un programme qui affiche un rectangle du nombre de lignes par le nombre de


colonnes donné par l'utilisateur.
ex :

> entrez la largeur et la hauteur : 4 6


+--+
| |
| |
| |
| |
+--+
>

7. Afficher le triangle de Pascal pour 8 lignes (de 0 à 7)


Série d’exercices 3 (Les tableaux)
1. Écrivez un programme qui trouve la précision de l'ordinateur, i.e. la valeur de la
variable precision qui est telle que 1.0 + precision = 1.0.

2. Écrivez un programme qui réalise la pyramide de 19 x en utilisant un tableau de 19 cases.


Ce tableau représente la ligne à afficher, au départ, il contient 19 x, à la ligne suivante deux
espaces sont ajoutés (_xx...xx_), et ainsi de suite jusqu'à la dernière ligne qui ne comporte
plus qu'un seul x.

3. Reprenez le programme de la factorielle pour qu'il utilise la ligne de commande pour


connaître la valeur dont il faut calculer la factorielle.

4. Écrivez un programme qui permet de jouer au jeu du pendu. Le joueur 1 entre le mot,
l'ordinateur l'enregistre et affiche une série de lignes blanches pour que le joueur 2 ne puisse
pas lire le mot, il affiche ensuite une série d'étoiles qui correspond au nombre de lettres du
mot à trouver. Le joueur 2 propose des caractères jusqu'à ce qu'il ait trouvé le mot, ou qu'il
ait perdu (nombre de coups > 10). À chaque fois que le joueur 2 propose un caractère
l'ordinateur affiche le mot avec des * et les caractères déjà trouvés

Entrez un mot : bonjour

*******
caractere ? a
*******
caractere ? o
*o**o**
caractere ? u
*o**ou*
caractere ? n
*on*ou*
caractere ? j
*onjou*
caractere ? s
*onjou*
caractere ? b
bonjou*
caractere ? r
bonjour
VOUS AVEZ GAGNE

5. Écrivez un programme qui permet à deux joueurs de joueur au jeu du morpion à neuf cases.
Le principe est le suivant, dès que le joueur 1 a réussi à aligner 3 croix (3 * pour le joueur
2), il a gagné. S'il n'y a plus de cases de libre et qu'aucun joueur n'a gagné il y a match nul.

1 2 3
A . . .
B . . .
C . . .

joueur 1 : A 2
1 2 3
A . x .
B . . .
C . . .

joueur 2 : A 1
1 2 3
A * x .
B . . .
C . . .

joueur 1 : B 2
1 2 3
A * x .
B . x .
C . . .

joueur 2 : C 2
1 2 3
A * x .
B . x .
C . * .

joueur 1 : B 1
1 2 3
A * x .
B x x .
C . * .

joueur 2 : B 3
1 2 3
A * x .
B x x *
C . * .

joueur 1 : A 3
1 2 3
A * x x
B x x *
C . * .

joueur 2 : C 3
1 2 3
A * x x
B x x *
C . * *

joueur 1 : C 1
1 2 3
A * x x
B x x *
C x * *

Le joueur 1 a gagné
Série d’exercices 4 (Les fonctions)
1. Écrivez une fonction int somme(int x, int y) qui retourne l'addition de x et y.

2. Écrivez une fonction void somme(int *resultat, int x, int y) qui additionne x
et y et place le résultat de cette addition dans la variable resultat.

3. Écrivez une fonction minuscule char minuscule(char car) qui retourne le caractère
en minuscule (sinon elle retourne le caractère car sans le modifier).

4. Écrivez une fonction minuscule void minuscule(char *car) qui modifie le caractère
passé par adresse, elle le transforme en minuscule s'il est en majuscule.

5. Écrivez une fonction int compter_occurrences(char car, int taille, char


*mot) qui retourne le nombre d'occurrences d'un caractère car dans une chaîne mot de
taille taille. Utilisez cette fonction dans le main en lisant le mot avec un scanf puis
essayez de l'utiliser lorsque le mot est entré sur la ligne de commandes.

6. Écrivez une fonction int compter_voyelles(int taille, char *mot) qui


retourne le nombre de voyelles dans la chaîne mot de taille taille.

7. Réécrivez la fonction compter_occurrences avec la taille de la chaîne et le mot qui sont


des variables globales.
Série d’exercices 5 (Les fonctions et fichiers)
1. Modifiez le programme qui affiche un rectangle en fonction d'une largeur et une longueur
donnée afin qu'il affiche des rectangles pour le fichier de test suivant :

5 8
8 5
0 3
1 3
2 3
3 3
4 0
15 1
1 9
1 1

Vous écrirez une fonction void afficher_rectangle(int longueur, int


hauteur) qui fait appel à la fonction void afficher_ligne(char car_cadre,
char car_interieur, int nb) vue dans le cours sur les fonctions. La fonction
afficher_rectangle sera appelée pour chaque ligne du fichier avec les données lues sur la
ligne (1er nombre = largeur, 2ème nombre = hauteur).

> ./rect test.txt

rectangle de 8 lignes par 5 colonnes :


+---+
| |
| |
| |
| |
| |
| |
+---+

rectangle de 5 lignes par 8 colonnes :


+------+
| |
| |
| |
+------+

rectangle de 3 lignes par 0 colonnes :


++
||
++

rectangle de 3 lignes par 1 colonnes :


++
||
++

rectangle de 3 lignes par 2 colonnes :


++
||
++

rectangle de 3 lignes par 3 colonnes :


+-+
| |
+-+

rectangle de 0 lignes par 4 colonnes :

rectangle de 1 lignes par 15 colonnes :


+-------------+

rectangle de 9 lignes par 1 colonnes :


++
||
||
||
||
||
||
||
++

rectangle de 1 lignes par 1 colonnes :


++

Qu'est-ce que le test fait apparaître lorsque le rectangle a 0 ou 1 colonne ?

Comment corriger ce problème ?

2. Écrivez un programme qui prend en entrée le nom du fichier contenant l'annuaire, ainsi que
le nom, prénom, numéro de téléphone et l'e-mail d'une personne et qui génère un autre
fichier annuaire en classant alphabétiquement la personne. NB : on suppose que les entrées
de l'annuaire sont classées alphabétiquement.
> more annuaire.txt
Alessandra Denis 04 91 11 36 13 alessand@club-internet.fr
Contensin Magali 04 91 11 36 13 contensin@cmi.univ-mrs.fr
Ifrah Sandrine 04 91 11 35 21 ifrah@cmi.univ-mrs.fr
> ./ajouter annuaire.txt Dupont Georges 04 91 22 43 44
dupont@bidule.fr
> more annuaire2.txt
Alessandra Denis 04 91 11 36 13 alessand@club-internet.fr
Contensin Magali 04 91 11 36 13 contensin@cmi.univ-mrs.fr
Dupont Georges 04 91 22 43 44 dupont@bidule.fr
Ifrah Sandrine 04 91 11 35 21 ifrah@cmi.univ-mrs.fr
>

3. Modifiez le programme qui affiche toutes les lignes de l'annuaire afin qu'il affiche le numéro
de téléphone du nom d'une personne passé sur la ligne de commande. Si ce nom n'existe pas
dans l'annuaire, il affichera un message d'erreur.

4. Écrivez un programme qui classe les entrées d'un annuaire alphabétiquement (par rapport
uniquement au nom) et stocke l'annuaire trié dans un fichier annuaire_trie.txt
Corrigés des séries d’exercices supplémentaires

Série d’exercices 1
1. Écrivez un programme qui permute les valeurs de deux variables lues au clavier

// programme qui permute les valeurs de 2 entiers entres au clavier

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int nb1, nb2, inter;

//saisie
printf("Entrez deux entiers : ");
if(scanf("%d%d", &nb1, &nb2) != 2){
printf("erreur de saisie\n");
exit(1);
}
printf("nb1 contient %d et nb2 contient %d\n", nb1, nb2);

//permutation
inter = nb1;
nb1 = nb2;
nb2 = inter;

//affichage du resultat
printf("nb1 contient %d et nb2 contient %d\n", nb1, nb2);

return 0;
}

2. Écrivez un programme qui effectue une permutation circulaire vers la droite de 4 variables
lues au clavier

// permutation circulaire de 4 entiers lus au clavier

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int x, y, z, t, inter;

//saisie
printf("Entrez quatre entiers : ");
if(scanf("%d%d%d%d", &x, &y, &z, &t) != 4){
printf("erreur de saisie\n");
exit(1);
}

printf("x = %d, y = %d, z = %d et t = %d\n", x, y, z, t);

//permutation circulaire
inter = x;
x = y;
y = z;
z = t;
t = inter;

//affichage du resultat
printf("x = %d, y = %d, z = %d et t = %d\n", x, y, z, t);

return 0;
}

3. Écrivez un programme qui donne le maximum de 3 nombres lus au clavier et effectuez des
tests pour :
258
420
8 -6 1

// maximum de 3 nombres lus au clavier

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int x, y, z;

//saisie
printf("Entrez trois nombres : ");
if(scanf("%d%d%d", &x, &y, &z) != 3){
printf("erreur de saisie\n");
exit(1);
}

//recherche du maximum
if(x > y) { // comparer x et z
if(x > z)
printf("le plus grand nombre est %d\n", x);
else
printf("le plus grand nombre est %d\n", z);
}
else { // comparer y et z
if(y > z)
printf("le plus grand nombre est %d\n", y);
else
printf("le plus grand nombre est %d\n", z);
}

return 0;
}

4. Écrivez un programme qui calcule la moyenne de 4 nombres lus au clavier et donne le


minimum

// calculer la moyenne de 4 nombres et donner le minimum

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
int x, y, z, t;
float moyenne;

//saisie
printf("Entrez quatre entiers : ");
if(scanf("%d%d%d%d", &x, &y, &z, &t) != 4){
printf("erreur de saisie\n");
exit(1);
}

// calcul de la moyenne
moyenne = (float)(x+y+z+t)/4;
printf("la moyenne est %.2f\n", moyenne);

//recherche du minimum
if((x < y) && (x < z) && (x < t))
printf("le plus petit nombre est %d\n", x);
else if((y < x) && (y < z) && (y < t))
printf("le plus petit nombre est %d\n", y);
else if((z < x) && (z < y) && (z < t))
printf("le plus petit nombre est %d\n", z);
else
printf("le plus petit nombre est %d\n", t);

return 0;
}

5. Écrivez un programme qui calcule le prix TTC d'un prix HT entré au clavier

// programme qui calcule un prix TTC

#include <stdio.h>
#include <stdlib.h>

#define TVA 0,07


int main(void)
{
float nb, prix;

//saisie
printf("Entrez un prix : ");
if(scanf("%f", &nb) != 1){
printf("erreur de saisie\n");
exit(1);
}

// calcul du prix
prix = (nb * TVA)/100 + nb;

// affichage du resultat
printf("%.2f euros HT = %.2f euros TTC\n", nb, prix);

return 0;
}

6. Écrivez un programme qui calcule le pourcentage d'un nombre, ce nombre ainsi que le
pourcentage sont entrés au clavier

// programme qui calcule un pourcentage d'un nombre

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
float nb, res;
int pourcent;

//saisie
printf("Entrez un nombre et un pourcentage : ");
if(scanf("%f%d", &nb, &pourcent) != 2){
printf("erreur de saisie\n");
exit(1);
}

// calcul du pourcentage
res = (nb * pourcent)/100;

// affichage du resultat
printf("%d pourcent de %.2f = %.2f\n", pourcent, nb, res);

return 0;
}
7. Écrivez un programme qui donne une température en degrés celsius à partir d'une
température Fahrenheit (C = (5/9) * (F - 32))

// programme qui donne une temperature en degres Celsius


// a partir d'une temperature en degres Fahrenheit
// C = (5/9)*(F-32)

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
float fahr;
float deg;

//saisie
printf("Entrez une temperature en degres Fahrenheit : ");
if(scanf("%f", &fahr) != 1){
printf("erreur de saisie\n");
exit(1);
}

// calcul des degres Celsius


deg = (5.0/9.0)*(fahr - 32);

// affichage du resultat
printf("%.2f degres F = %.2f degres C\n", fahr, deg);

return 0;
}

8. Écrivez un programme qui donne la mention d'un étudiant en fonction de sa note entrée au
clavier

// programme qui donne la mention d'un etudiant


// en fonction de sa note entree au clavier

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
float note;

//saisie
printf("Entrez une note : ");
if(scanf("%f", &note) != 1){
printf("erreur de saisie\n");
exit(1);
}

if((note < 0) || (note > 20))


printf("la note n'est pas valide\n");
else{
if(note < 10)
printf("refuse\n");
else{ // la note est au moins egale a la moyenne
printf("admis avec la mention ");
// determiner la mention en fonction de la note
if(note < 12)
printf("passable\n");
else { // la note est au moins egale a 12
if(note < 14)
printf("assez bien\n");
else { // la note est au moins egale a 14
if(note < 16)
printf("bien\n");
else { // la note est au moins egale a 16
if(note < 18)
printf("tres bien\n");
else { // la note est au moins egale a 18
if(note <= 20)
printf("felicitations du jury\n");
}
}
}
}
}
}

return 0;
}

Autre version :

// programme qui donne la mention d'un etudiant


// en fonction de sa note entree au clavier

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
float note;

//saisie
printf("Entrez une note : ");
if(scanf("%f", &note) != 1){
printf("erreur de saisie\n");
exit(1);
}

if((note < 0) || (note > 20))


printf("la note n'est pas valide\n");
else if(note < 10)
printf("refuse\n");
else{ // la note est au moins egale a la moyenne
printf("admis avec la mention ");
// determiner la mention en fonction de la note
if(note < 12)
printf("passable\n");
else if(note < 14) // la note est au moins egale a 12
printf("assez bien\n");
else if(note < 16) // la note est au moins egale a 14
printf("bien\n");
else if(note < 18) // la note est au moins egale a 16
printf("tres bien\n");
else if(note <= 20) // la note est au moins egale a 18
printf("felicitations du jury\n");
}
return 0;
}
Série d’exercices 2
1. Écrivez le programme qui affiche chaque numéro de marche montée par un robot qui se
rend au 3ème étage, sachant qu'un étage comporte 20 marches

#include <stdio.h>

int main(void){

int nb_marches = 0;

while(nb_marches < 60){


nb_marches++;
printf("%d ", nb_marches);
}

return 0;
}

2. Écrivez un programme qui calcule la moyenne des notes entrées itérativement au clavier et
qui affiche la moyenne quand l'utilisateur entre -1

// saisie de notes jusqu'a ce que l'utilisateur entre -1,


// puis calcul de la moyenne

#include <stdio.h>
#include <stdlib.h>

int main(void){
float note_cou; // note courante saisie
int nb_notes = 0; // nbre de notes saisies
float total_notes = 0.0; // somme totale des notes saisies

printf("Entrez une note : ");


if(scanf ("%f", &note_cou) != 1){
printf("erreur de saisie\n");
exit(1);
}
while (note_cou != -1) // tant qu'on n'a pas entre -1
{
if ((note_cou >=0) && (note_cou <=20))
{
total_notes += note_cou; // ajoute la note
courante a la somme des notes
nb_notes++; // une note de plus a
ete saisie !
}
else
{
printf("Note invalide, elle ne sera pas prise en
compte dans le calcul...\n");
}

printf("Entrez une note : ");


scanf ("%f", &note_cou);
}

if (nb_notes != 0) // pour eviter la division par zero :)


{
printf ("moyenne des notes : %.2f\n",
total_notes/nb_notes);
}
else
{
printf("aucune note n'a ete entree...\n");
}
return 0;
}

3. Écrivez un programme qui calcule la factorielle d'un nombre entré au clavier

#include <stdio.h>
#include <stdlib.h>

long fact (short nombre) {

short indice;
long factorielle = 1; // pour stocker le resultat

if (nombre == 0) // cas particulier ou il n'y a rien a calculer


return 1;

for(indice = nombre ; indice > 0; indice--)


factorielle = factorielle * indice;

return factorielle;
}

int main(void)
{
int nombre_lu;

printf("De quel nombre souhaitez-vous la factorielle ? ");


if(scanf("%d", &nombre_lu) != 1){
printf("erreur de saisie\n");
exit(1);
}
printf("Factorielle (%d) = %ld\n", nombre_lu,
fact(nombre_lu));

return 0;
}
4. Modifiez ce programme pour qu'il demande le nombre dont on souhaite calculer la
factorielle jusqu'à ce que l'utilisateur entre -1

#include <stdio.h>
#include <stdlib.h>

long fact (short nombre) {

short indice;
long factorielle = 1; // pour stocker le resultat

if (nombre == 0) // cas particulier ou il n'y a rien a calculer


return 1;

for(indice = nombre ; indice > 0; indice--)


factorielle = factorielle * indice;

return factorielle;
}

int main(void)
{
int nombre_lu;

printf("De quel nombre souhaitez-vous la factorielle ? ");


if(scanf("%d", &nombre_lu) != 1){
printf("erreur de saisie\n");
exit(1);
}
while (nombre_lu != -1)
{
printf("Factorielle (%d) = %ld\n", nombre_lu,
fact(nombre_lu));
printf("De quel nombre souhaitez-vous la factorielle ? ");
if(scanf("%d", &nombre_lu) != 1){
printf("erreur de saisie\n");
exit(1);
}
}

return 0;
}

5. Donnez le programme qui affiche le nombre de marches et le numéro de l'étage montés,


sachant que le nombre de marches par étage et le nombre d'étages à monter sont entrés au
clavier. Utilisez deux boucles while.

// Programme qui affiche le nombre de marches et le numero de l'etage


montes,
// sachant que le nombre de marches par etage et le nombre d'etages a
monter
// sont entres au clavier
#include <stdio.h>
#include <stdlib.h>

#define NB_MARCH_ETAGE 20

int main(void)
{
int num_etage_cou = 0; // numero d'etage courant
int num_marche = 0; // numero de marche dans l'etage
int num_etage_a_atteindre;
int nbre_marches_etage; // nbre de marches par etage

printf("A quel etage faut-il se rendre ? ");


if(scanf("%d", &num_etage_a_atteindre) != 1){
printf("erreur de saisie\n");
exit(1);
}
printf("Combien de marches par etage ? ");
if(scanf("%d", &nbre_marches_etage) != 1){
printf("erreur de saisie\n");
exit(1);
}

while (num_etage_cou < num_etage_a_atteindre) //tant qu'on a pas


atteint l'etage
{
num_marche = 0;
while (num_marche < nbre_marches_etage) //tant qu'on a pas
monte toutes les marches de l'etage
{
num_marche++; // on monte une marche...
printf("Etage %d, marche numero %d\n",
num_etage_cou, num_marche);
}
num_etage_cou++; //on a monte un etage
}
return 0;
}

6. Écrivez un programme qui affiche un rectangle du nombre de lignes par le nombre de


colonnes donné par l'utilisateur.
ex :

> entrez la largeur et la hauteur : 4 6


+--+
| |
| |
| |
| |
+--+
>
#include <stdio.h>
#include <stdlib.h>

int main(void){

int largeur, hauteur;


int i, j; //indices de boucle

printf("entrez la largeur et la hauteur : ");


if(scanf("%d %d", &largeur, &hauteur) != 2){
printf("erreur de saisie\n");
exit(1);
}

for(i=1; i<=hauteur; i++){

if((i == 1) || (i == hauteur))
{
printf("+");
for(j=2; j<largeur; j++)
printf("-");
printf("+");
}
else{
printf("|");
for(j=2; j<largeur; j++)
printf(" ");
printf("|");
}

printf("\n");
}

return 0;
}

Autre solution :

#include <stdio.h>
#include <stdlib.h>

#define TYPE_BORD 1
#define TYPE_CENTRE 2

void afficher_ligne(int taille, short type)


{
char car_extreme;
char car_remplissage;
int i;

switch (type)
{
case TYPE_BORD :
car_extreme = '+';
car_remplissage = '-';
break;
case TYPE_CENTRE :
car_extreme = '|';
car_remplissage = ' ';
break;
default : // TOUJOURS mettre le default dans le switch,
meme si ce cas est anormal...
printf("erreur dans le break fonction
afficher_ligne\n");
exit (-1);
}

printf("%c", car_extreme);
for (i=2;i<taille;i++)
printf("%c", car_remplissage);
printf("%c\n", car_extreme);
}

int main(void)
{
int nb_cols = 0;
int nb_lignes = 0;
int i;

printf("Entrez la largeur et la hauteur : ");


if(scanf ("%d%d", &nb_cols, &nb_lignes) != 2){
printf("erreur de saisie\n");
exit(1);
}
afficher_ligne(nb_cols, TYPE_BORD);
for (i=2;i<nb_lignes;i++)
afficher_ligne(nb_cols, TYPE_CENTRE);
afficher_ligne(nb_cols, TYPE_BORD);
return 0;
}

7. Afficher le triangle de Pascal pour 8 lignes (de 0 à 7)

//programme qui affiche le triangle de pascal pour les lignes de 0 a 7

#include <stdio.h>
#include <stdlib.h>

long fact (short nombre) {

short indice;
long factorielle = 1; // pour stocker le resultat

if (nombre == 0) // cas particulier ou il n'y a rien a calculer


return 1;
for(indice = nombre ; indice > 0; indice--)
factorielle = factorielle * indice;

return factorielle;
}

int main(void)
{
int lig, col;

for (lig=0 ; lig<8 ; lig++)


{
for (col=0 ; col<=lig ; col++)
{
printf("%ld ", fact(lig)/(fact(col)*fact(lig-col)));
}
printf("\n");
}
return 0;
}
Série d’exercices 3
1. Écrivez un programme qui trouve la précision de l'ordinateur, i.e. la valeur de la
variable precision qui est telle que 1.0 + precision = 1.0.

// precision.c
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
double precision = 1.0;

while (1.0 + precision != 1.0){


printf("%.20lf\n", precision);
precision /= 10.0;
}
printf("La precision est : %g\n", precision);

return 0;
}

2. Écrivez un programme qui réalise la pyramide de 19 x (vue en algorithmique) en utilisant un


tableau de 19 cases. Ce tableau représente la ligne à afficher, au départ, il contient 19 x, à la
ligne suivante deux espaces sont ajoutés (_xx...xx_), et ainsi de suite jusqu'à la dernière
ligne qui ne comporte plus qu'un seul x.

// pyramide.c

#include <stdio.h>
#include <stdlib.h>

#define NB_ETOIL 19 /* nombre d'etoiles de la base de la pyramide */

int main (void)


{
char tableau[NB_ETOIL+1];// la case representee par le "+1" servira
a stocker le caractere de fin de chaine : '\0'
int i;

// initialisation du tableau avec des etoiles


i=0;
while (i<NB_ETOIL)
{
tableau[i++] = '*';
}
tableau[i] = '\0';//ajout du caractere de fin de chaine pour pouvoir
l'afficher avec printf %s

// construction et affichage de la pyramide


i=0;
while (i<=NB_ETOIL/2)
{
printf("%s\n", tableau); // affichage du contenu du tableau
tableau[i] = ' '; // remplace la premiere etoile par un espace
tableau[NB_ETOIL-1-i] = ' ';// remplace la derniere etoile par un
espace
i++;
}

return 0;
}

3. Reprenez le programme de la factorielle pour qu'il utilise la ligne de commande pour


connaître la valeur dont il faut calculer la factorielle.

// fact_commande.c

#include <stdio.h>
#include <stdlib.h>

long fact (short nombre) {

short indice;
long factorielle = 1; // pour stocker le resultat

if (nombre == 0) // cas particulier ou il n'y a rien a calculer


return 1;

for(indice = nombre ; indice > 0; indice--)


factorielle = factorielle * indice;

return factorielle;
}

int main(int argc, char *argv[])


{
int nombre_lu;

if(argc != 2){ // si le nombre d'arguments est incorrect


printf("usage : %s valeur\n", argv[0]); //affiche le nom du
programme (argv[0]) suivi de "valeur"
printf("ou valeur est le nombre dont vous souhaitez calculer la
factorielle\n");
exit(1);
}

nombre_lu = atoi(argv[1]); // conversion chaine->entier de


l'argument sur la ligne de commande

printf("Factorielle (%d) = %ld\n", nombre_lu, fact(nombre_lu));

return 0;
}
4. Écrivez un programme qui permet de jouer au jeu du pendu. Le joueur 1 entre le mot,
l'ordinateur l'enregistre et affiche une série de lignes blanches pour que le joueur 2 ne puisse
pas lire le mot, il affiche ensuite une série d'étoiles qui correspond au nombre de lettres du
mot à trouver. Le joueur 2 propose des caractères jusqu'à ce qu'il ait trouvé le mot, ou qu'il
ait perdu (nombre de coups > 10). À chaque fois que le joueur 2 propose un caractère
l'ordinateur affiche le mot avec des * et les caractères déjà trouvés

// un programme de pendu qui autorise 10 essais.


// le cas ou le nombre de lettres a trouver est > a 10

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define VRAI 1
#define FAUX 0
#define NBC 30

int main (void) {

int nb_lettres; // nb de lettres du mot a trouver


char mot [NBC]; // mot a trouver
char masque [NBC]; // masque pour affichage
char lettre ; // lettre proposee
int nbcoups,j; // indices pour boucles
int trouve; // booleen

// saisie du mot
printf("Entrez un mot : ");
scanf("%s", mot);

// calcul du nb de lettres du mot


nb_lettres = strlen(mot);

// initialisation du masque avec des etoiles


j = 0;
while (j < nb_lettres){
masque[j] = '*';
j++;
}
masque[j] = '\0';

// effacer l'ecran avec un appel systeme a clear


system("clear");

// affichage du nombre d'etoiles representant le mot a trouver


printf("%s", masque);

// ********* DEBUT DU JEU POUR LE JOUEUR 2 **********

trouve = FAUX;
nbcoups = 0; // compteur d'essais
while ((nbcoups < 10) && !trouve){ // on autorise 10 essais de 0 a 9

// demande d'un caractere


printf ("\ncaractere ? ");
scanf (" %c", &lettre);

//recherche du caractere dans le mot


j = 0; // indice du caractere teste dans le mot a trouver
while ((j < nb_lettres) && !trouve) //recherche dans tout le mot
{
if (mot[j] == lettre) // comparaison jeme car. mot/lettre
{
//si lettre trouvee on met a jour le masque
masque[j]=lettre;
if (strchr(masque,'*') == NULL) // si mot complet...
trouve = VRAI;
}
j++;
}

// affichage du masque
printf("%s", masque);

nbcoups++; // indice pour boucle "nombre d'essais"


}
if (!trouve) // on est sorti parce que nb coups > 10
printf("\nVOUS AVEZ PERDU\n");
else
printf("\nVOUS AVEZ GAGNE\n");
return 0;
}

5. Écrivez un programme qui permet à deux joueurs de joueur au jeu du morpion à neuf cases.
Le principe est le suivant, dès que le joueur 1 a réussi à aligner 3 croix (3 * pour le joueur
2), il a gagné. S'il n'y a plus de cases de libre et qu'aucun joueur n'a gagné il y a match nul.

// morpion

#include <stdio.h>

int main(void)
{
/* Déclarations des variables */
char tab[4][4];
char lettre;
int nbre_cases, i, j, valeur_ascii;
int numero_joueur, ligne, colonne;
int nbre_gagnant, nbre_croix, nbre_asterisques;

/* initialisation du tableau */
nbre_cases = 0;
tab[0][0] = ' ';
for (i=1; i<4; i++){
tab[0][i] = (48+i);
}
for (i=1; i<4; i++){
valeur_ascii = i+64;
tab[i][0] = valeur_ascii;
}
for (i=1; i<4; i++){
for (j=1; j<4; j++)
tab[i][j] = '.';
}

/* Affichage de la matrice du jeu */


fflush(stdout);
i=0, j=0;
while (i<4){
printf("\n");
while (j<4){
printf("%c", tab[i][j]);
j++;
}
j=0;
i++;
}
printf("\n");

/* Debut du jeu */
numero_joueur = 1;
nbre_gagnant = 0;
while ((nbre_cases < 9) && (nbre_gagnant == 0)){
printf("\n\n");
printf("Joueur %d: ", numero_joueur);
scanf(" %c%d", &lettre, &colonne);
ligne = (int)lettre - 64;

/* Controle de saisie: lettre majuscule A,B ou C et chiffres


1,2 ou 3. */
while (((lettre<65) || (lettre>67)) || ((colonne<1) ||
(colonne>3)) || (tab[ligne][colonne] != '.')){
if ((lettre < 65) || (lettre > 67)){
printf("La lettre doit etre en majuscule et comprise entre A
et C !\n");
}
if ((colonne < 1) || (colonne > 3)){
printf("Le chiffre doit etre compris entre 1 et 3 !\n");
}
if (((lettre>64) && ( lettre<68)) && ((colonne>0) &&
(colonne<4)) && (tab[ligne][colonne] != '.')){
printf(" Ce choix a déjà ete effectue !\n");
}
printf("Veuillez retaper votre choix: ");
scanf(" %c%d", &lettre, &colonne);
ligne = (int)lettre - 64;
}
/* Affectation du 'x' ou de '*' dans le tableau */
if (numero_joueur == 1){
tab[ligne][colonne] = 'x';
}
else{
tab[ligne][colonne] = '*';
}

/* Affichage de la matrice */
ligne = 0, colonne = 0;
while (ligne < 4){
while (colonne < 4){
printf("%c", tab[ligne][colonne]);
colonne++;
}
printf("\n");
colonne = 0;
ligne++;
}

/* Contrôle de 3 symboles consecutifs sur une ligne */


ligne = 1, colonne = 1;
while (ligne < 4){
nbre_asterisques = 0;
nbre_croix = 0;
while (colonne < 4){
if (tab[ligne][colonne] == 'x'){
nbre_croix = nbre_croix + 1;
}
if (tab[ligne][colonne] == '*'){
nbre_asterisques = nbre_asterisques + 1;
}
colonne++;
}

if ((nbre_croix == 3) || (nbre_asterisques == 3)){


printf("Vous avez gagné !!!\n\n");
nbre_gagnant = 1;
}

colonne = 1;
ligne++;
}

/* Contrôle de 3 symboles consecutifs sur une colonne */


if ( nbre_gagnant == 0){
ligne = 1, colonne = 1;
while (colonne < 4){
nbre_asterisques = 0;
nbre_croix = 0;
while (ligne < 4){
if (tab[ligne][colonne] == 'x'){
nbre_croix = nbre_croix + 1;
}
if (tab[ligne][colonne] == '*'){
nbre_asterisques = nbre_asterisques + 1;
}
ligne++;
}
if ((nbre_croix == 3) || (nbre_asterisques == 3)){
printf("Vous avez gagné !!!\n\n");
nbre_gagnant = 1;
}
ligne = 1;
colonne++;
}
}

/* Contrôle 1ere diagonale */


if (nbre_gagnant == 0) {
ligne = 1, colonne =1;
nbre_asterisques = 0, nbre_croix = 0;
while (ligne < 4){
colonne = ligne;
if (tab[ligne][colonne] == 'x'){
nbre_croix++;
}
if (tab[ligne][colonne] == '*'){
nbre_asterisques++;
}
ligne++;
}
if ((nbre_croix == 3) || (nbre_asterisques == 3)){
printf("Vous avez gagné !!! \n\n");
nbre_gagnant = 1;
}
}

/* Contrôle 2eme diagonale */


if (nbre_gagnant == 0){
ligne = 1, colonne = 3;
nbre_asterisques = 0, nbre_croix = 0;
while (colonne > 0){
if (tab[ligne][colonne] == 'x'){
nbre_croix++;
}
if (tab[ligne][colonne] == '*'){
nbre_asterisques++;
}
colonne--;
ligne++;
}

if ((nbre_croix == 3) || (nbre_asterisques == 3)){


printf("Vous avez gagne !!!\n\n");
nbre_gagnant = 1;
}
}

/* permutation joueur 1 et joueur 2 */


if (numero_joueur == 1) numero_joueur = 2;
else numero_joueur = 1;
nbre_cases = nbre_cases + 1;
}

if (nbre_gagnant == 0){
printf("Aucun joueur n'a gagne. Il y a match null !\n");
}

return 0;
}
Série d’exercices 4
1. Écrivez une fonction int somme(int x, int y) qui retourne l'addition de x et y.

#include <stdio.h>
#include <stdlib.h>

int somme(int x, int y)


{
return (x + y);
}

int main(void)
{
int nb1, nb2;

printf("entrez 2 nombres : ");


if(scanf("%d %d", &nb1, &nb2) != 2){
printf("erreur de saisie\n");
exit(1);
}

printf("la somme de %d et %d est %d\n", nb1, nb2, somme(nb1, nb2));

return 0;
}

2. Écrivez une fonction void somme(int *resultat, int x, int y) qui additionne x
et y et place le résultat de cette addition dans la variable resultat.

#include <stdio.h>
#include <stdlib.h>

void somme(int *resultat, int x, int y)


{
*resultat = x + y;
}

int main(void)
{
int nb1, nb2, res;

printf("entrez 2 nombres : ");


if(scanf("%d %d", &nb1, &nb2) != 2){
printf("erreur de saisie\n");
exit(1);
}

somme(&res, nb1, nb2);


printf("la somme de %d et %d est %d\n", nb1, nb2, res);
return 0;
}

3. Écrivez une fonction minuscule char minuscule(char car) qui retourne le caractère
en minuscule (sinon elle retourne le caractère car sans le modifier).

#include <stdio.h>

// a -> z code ascii 97 -> 122


// A -> Z code ascii 65 -> 90
char minuscule(char car)
{
if( (car >= 65) && (car <= 90) )
return (car + 32) ;

return car;
}

int main(void)
{
int indice;
char mot[255];

printf("entrez un mot : ");


scanf("%s", mot);

indice = 0;
while(mot[indice] != '\0'){
mot[indice] = minuscule(mot[indice]);
indice++;
}

printf("le mot en minuscules : %s\n", mot);

return 0;
}

4. Écrivez une fonction minuscule void minuscule(char *car) qui modifie le caractère
passé par adresse, elle le transforme en minuscule s'il est en majuscule.

#include <stdio.h>

// a -> z code ascii 97 -> 122


// A -> Z code ascii 65 -> 90
void minuscule(char *car)
{
if( (*car >= 65) && (*car <= 90) )
*car += 32 ;
}

int main(void)
{
int indice;
char mot[255];

printf("entrez un mot : ");


scanf("%s", mot);

indice = 0;
while(mot[indice] != '\0'){
minuscule(&mot[indice]);
indice++;
}

printf("le mot en minuscules : %s\n", mot);

return 0;
}

5. Écrivez une fonction int compter_occurrences(char car, int taille, char


*mot) qui retourne le nombre d'occurrences d'un caractère car dans une chaîne mot de
taille taille. Utilisez cette fonction dans le main en lisant le mot avec un scanf

// VERSION 1
// compte les occurrences d'un caractere dans un mot.
//
// Les tests pourraient etre realises en demandant le caractere
// dont on veut connaitre l'occurrence et le mot.
// Le test realise ici parcourt le mot et donne pour chaque
// lettre du mot le nombre de fois ou elle apparait sans tenir
// compte des repetitions :
// ./compter zoo
// z apparait 1 fois
// o apparait 2 fois
// o apparait 2 fois

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int compter_occurrences(char car, int taille, char *mot)


{
int compteur = 0, indice;

for(indice=0; indice < taille; indice++)


if(mot[indice] == car)
compteur++;

return compteur;
}

int main(void)
{
int taille; // taille du mot
int i;
int nboccur; // nb d'occurrences de la lettre
char texte[125];

printf("entrez un mot : ");


scanf("%s", texte);

taille = strlen(texte);

for(i = 0; i < taille; i++){


nboccur = compter_occurrences(texte[i], taille, texte);
printf("%c apparait %d fois\n", texte[i], nboccur);
}

return 0;
}

puis essayez de l'utiliser lorsque le mot est entré sur la ligne de commandes.

// idem avec la ligne de commande

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int compter_occurrences(char car, int taille, char *mot)


{
int compteur = 0, indice;

for(indice=0; indice < taille; indice++)


if(mot[indice] == car)
compteur++;

return compteur;
}

// version qui utilise la ligne de commande


int main(int argc, char *argv[])
{
int taille; // taille du mot
int i;
int nboccur; // nb d'occurrences de la lettre

if(argc != 2){
printf("usage compter mot\n");
exit(1);
}

taille = strlen(argv[1]);

for(i = 0; i < taille; i++){


nboccur = compter_occurrences(argv[1][i], taille, argv[1]);
printf("%c apparait %d fois\n",argv[1][i], nboccur);
}

return 0;
}

6. Écrivez une fonction int compter_voyelles(int taille, char *mot) qui


retourne le nombre de voyelles dans la chaîne mot de taille taille.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int compter_occurrences(char car, int taille, char *mot)


{
int compteur = 0, indice;

for(indice=0; indice < taille; indice++)


if(mot[indice] == car)
compteur++;

return compteur;
}

int compter_voyelles(int taille, char *texte)


{
int i;
int compteur = 0;
char voyelles[14] = "aeiouyAEIOUY";

for(i = 0; i < 14 ; i++){


compteur += compter_occurrences(voyelles[i], taille, texte);
}

return compteur;
}

int main(void)
{
int taille; // taille du mot
char txt[125];

printf("entrez un mot : ");


scanf("%s", txt);

taille = strlen(txt);

printf("%d voyelles\n", compter_voyelles(taille, txt));

return 0;
}
7. Réécrivez la fonction compter_occurrences avec la taille de la chaîne et le mot qui sont
des variables globales.

// compte les occurrences d'un caractere dans un mot.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char texte[125]; // mot


int taille; // taille du mot

int compter_occurrences(char car)


{
int compteur = 0, indice;

for(indice=0; indice < taille; indice++)


if(texte[indice] == car)
compteur++;

return compteur;
}

int main(void)
{
int i;
int nboccur; // nb d'occurrences de la lettre

printf("entrez un mot : ");


scanf("%s", texte);

taille = strlen(texte);

for(i = 0; i < taille; i++){


nboccur = compter_occurrences(texte[i]);
printf("%c apparait %d fois\n", texte[i], nboccur);
}

return 0;
}
Série d’exercices 5
1. Modifiez le programme qui affiche un rectangle en fonction d'une largeur et une longueur
donnée afin qu'il affiche des rectangles pour le fichier de test suivant :

5 8
8 5
0 3
1 3
2 3
3 3
4 0
15 1
1 9
1 1

Vous écrirez une fonction void afficher_rectangle(int longueur, int


hauteur)qui fait appel à la fonction void afficher_ligne(char car_cadre,
char car_interieur, int nb)vue dans le cours sur les fonctions. La fonction
afficher_rectangle sera appelée pour chaque ligne du fichier avec les données lues sur la
ligne (1er nombre = largeur, 2ème nombre = hauteur).

#include <stdio.h>
#include <stdlib.h>

// fonction qui affiche une ligne d'un rectangle.


// car_cadre est le caractere du cadre a afficher
// car_interieur est le caractere de remplissage
// nb est le nombre de caracteres interieurs a afficher
void afficher_ligne(char car_cadre, char car_interieur, int nb)
{
int i;

printf("%c", car_cadre);
for(i=0; i<nb; i++)
printf("%c", car_interieur);
printf("%c\n", car_cadre);
}

// fonction qui affiche un rectangle en fonction de la hauteur h et


// la longueur l
void afficher_rectangle(int l, int h){
int i;

printf("rectangle de %d lignes par %d colonnes :\n", h, l);

for(i=1; i<=h; i++){


if((i == 1) || (i == h))
afficher_ligne('+', '-', l-2);
else
afficher_ligne('|', ' ', l-2);
}
}
int main(int argc, char *argv[]){

FILE *fic;
int largeur, hauteur, i;

// recuperation du nom du fichier a la ligne de commande


if(argc != 2){
printf("rect nom_fichier_test\n");
exit(1);
}

// ouverture du fichier de test


fic = fopen(argv[1], "r"); // ouvrir en lecture
if(fic == NULL){
printf("Impossible d'ouvrir le fichier %s\n", argv[1]);
exit(1);
}
printf(".............. Ouverture du fichier %s\n", argv[1]);

// lire les lignes du fichier et afficher le rectangle


i = 0;
while(fscanf(fic, "%d %d", &largeur, &hauteur) != EOF){
afficher_rectangle(largeur, hauteur);
i++;
}

// fermeture du fichier
if(fclose(fic) == EOF){
printf("Probleme de fermeture du fichier %s", argv[1]);
exit(1);
}
printf(".............. Fermeture du fichier %s\n", argv[1]);

return 0;
}

2. Écrivez un programme qui prend en entrée le nom du fichier contenant l'annuaire, ainsi que
le nom, prénom, numéro de téléphone et l'e-mail d'une personne et qui génère un autre
fichier annuaire en classant alphabétiquement la personne. NB : on suppose que les entrées
de l'annuaire sont classées alphabétiquement.
> more annuaire.txt
Alessandra Denis 04 91 11 36 13 alessand@club-internet.fr
Contensin Magali 04 91 11 36 13 contensin@cmi.univ-mrs.fr
Ifrah Sandrine 04 91 11 35 21 ifrah@cmi.univ-mrs.fr
> ./ajouter annuaire.txt Dupont Georges 04 91 22 43 44
dupont@bidule.fr
> more annuaire2.txt
Alessandra Denis 04 91 11 36 13 alessand@club-internet.fr
Contensin Magali 04 91 11 36 13 contensin@cmi.univ-mrs.fr
Dupont Georges 04 91 22 43 44 dupont@bidule.fr
Ifrah Sandrine 04 91 11 35 21 ifrah@cmi.univ-mrs.fr
>
// supposition : le fichier annuaire est trie
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 40

/***********************************************************
void ouvrir_fichier(FILE **fic, char *nom_fic, char *mode)

ARGUMENTS
fic : pointeur sur un flux
nom_fic : nom du fichier a ouvrir
mode : mode d'ouverture (lecture, ecriture, ajout)

ACTION
ouvre le fichier nom_fic dans le mode precise et teste
si l'ouverture a reussi ou non.
************************************************************/
void ouvrir_fichier(FILE **fic, char *nom_fic, char *mode)
{
*fic = fopen(nom_fic, mode);
if(*fic == NULL){
printf("Impossible d'ouvrir le fichier %s\n", nom_fic);
exit(1);
}
printf(".............. Ouverture du fichier %s\n", nom_fic);
}

/***********************************************************
void fermer_fichier(FILE **fic, char *nom_fic)

ARGUMENTS
fic : pointeur sur un flux
nom_fic : nom du fichier

ACTION
ferme le fichier et teste si la fermeture a reussi.
************************************************************/
void fermer_fichier(FILE **fic, char *nom_fic)
{
if(fclose(*fic) == EOF){
printf("Probleme de fermeture du fichier %s", nom_fic);
exit(1);
}
printf(".............. Fermeture du fichier %s\n", nom_fic);
}

int main(int argc, char *argv[])


{
FILE *fic;
char nom_fic[50], nom[50], prenom[50], mail[50];
int t1, t2, t3, t4, t5; // numero de tel
int taille; // nombre de lignes (nb de cases du tableau de stockage
utilisees)
int i;
char entree[255]; // donnees a inserer
char ligne[MAX][255]; // on suppose que l'annuaire n'aura pas plus
de 40 lignes

// stockage des donnees issues de la ligne de commandes


if(argc != 10){ //10 car num. tel. = 5 blocs d'entiers
printf("Usage : annuaire nom_fichier nom prenom tel mail\n");
exit(1);
}
strcpy(nom_fic, argv[1]);
strcpy(nom, argv[2]);
strcpy(prenom, argv[3]);
strcpy(mail, argv[9]);
t1 = atoi(argv[4]);
t2 = atoi(argv[5]);
t3 = atoi(argv[6]);
t4 = atoi(argv[7]);
t5 = atoi(argv[8]);

// stocker les donnees de la ligne de commande


sprintf(entree, "%s %s %.2d %.2d %.2d %.2d %.2d %s\n", nom, prenom,
t1, t2, t3, t4, t5, mail);

ouvrir_fichier(&fic, nom_fic, "r"); // ouverture du fichier en


lecture
// recuperer les donnees du fichier
taille = 0;
while((fgets(ligne[taille], 512, fic) != NULL) && taille < MAX){ //
fichier < 40 lignes
taille++;
}
fermer_fichier(&fic, nom_fic); // fermeture du fichier

// stocker dans le fichier


ouvrir_fichier(&fic, nom_fic, "w");
i = 0;
// copier toutes les lignes < entree
while((strcmp(ligne[i], entree) < 0) && i <= taille){
fprintf(fic, "%s", ligne[i]);
i++;
}
// copier entree
fprintf(fic, "%s", entree);
// copier les lignes restantes
while(i <= taille){
fprintf(fic, "%s", ligne[i]);
i++;
}
fermer_fichier(&fic, nom_fic);

printf("Les informations ont ete stockees dans l'annuaire\n");

return 0;
}

3. Modifiez le programme qui affiche toutes les lignes de l'annuaire afin qu'il affiche le numéro
de téléphone du nom d'une personne passé sur la ligne de commande. Si ce nom n'existe pas
dans l'annuaire, il affichera un message d'erreur.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void verif_et_recup_arg(int nb, char *arguments[], int nb_souhaite,


char *chaine, char * nomch)
{
if(nb != nb_souhaite){
printf("Usage : annuaire nom_fichier nom_cherche\n");
exit(1);
}

strcpy(chaine, arguments[1]);
strcpy(nomch, arguments[2]);
}

int main(int argc, char *argv[])


{
FILE *fic;
int trouve, t1, t2, t3, t4, t5;
char nom_fic[255], nom[255], prenom[255], mail[255],
nom_cherche[255];

verif_et_recup_arg(argc, argv, 3, nom_fic, nom_cherche);

// ouverture du fichier
fic = fopen(nom_fic, "r"); // ouvrir en lecture
if(fic == NULL){
printf("Impossible d'ouvrir le fichier %s\n", nom_fic);
exit(1);
}

// recuperer les donnees de l'annuaire


trouve = 0;
while((fscanf(fic, "%s %s %2d %2d %2d %2d %2d %s", nom, prenom,\
&t1, &t2, &t3, &t4, &t5, mail) != EOF) && !trouve){
if(strcmp(nom, nom_cherche) == 0){
printf("%.2d %.2d %.2d %.2d %.2d\n", t1, t2, t3, t4, t5);
trouve = 1;
}
}

if(!trouve)
printf("%s n'est pas dans %s\n", nom_cherche, nom_fic);

// fermeture du fichier
if(fclose(fic) == EOF){
printf("Probleme de fermeture du fichier %s", nom_fic);
exit(1);
}

return 0;
}

4. Écrivez un programme qui classe les entrées d'un annuaire alphabétiquement (par rapport
uniquement au nom) et stocke l'annuaire trié dans un fichier annuaire_trie.txt

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 40

/***********************************************************
void ouvrir_fichier(FILE **fic, char *nom_fic, char *mode)

ARGUMENTS
fic : pointeur sur un flux
nom_fic : nom du fichier a ouvrir
mode : mode d'ouverture (lecture, ecriture, ajout)

ACTION
ouvre le fichier nom_fic dans le mode precise et teste
si l'ouverture a reussi ou non.
************************************************************/
void ouvrir_fichier(FILE **fic, char *nom_fic, char *mode)
{
*fic = fopen(nom_fic, mode);
if(*fic == NULL){
printf("Impossible d'ouvrir le fichier %s\n", nom_fic);
exit(1);
}
printf(".............. Ouverture du fichier %s\n", nom_fic);
}

/***********************************************************
void fermer_fichier(FILE **fic, char *nom_fic)

ARGUMENTS
fic : pointeur sur un flux
nom_fic : nom du fichier

ACTION
ferme le fichier et teste si la fermeture a reussi.
************************************************************/
void fermer_fichier(FILE **fic, char *nom_fic)
{
if(fclose(*fic) == EOF){
printf("Probleme de fermeture du fichier %s", nom_fic);
exit(1);
}
printf(".............. Fermeture du fichier %s\n", nom_fic);
}

int main(int argc, char *argv[])


{
FILE *fic;
char nom_fic[50], pren[50], mail[50];
int t1, t2, t3, t4, t5;
int taille; // nombre de lignes (nb de cases du tableau de stockage
utilisees)
int i, j;
char inter[255]; // tampon pour la permutation
char nom[MAX][50]; // stocker tous les noms
char reste[MAX][200]; // stocker tout le reste

if(argc != 2){
printf("Usage : trier nom_fichier\n");
exit(1);
}
strcpy(nom_fic, argv[1]);

// ouverture du fichier en lecture


ouvrir_fichier(&fic, nom_fic, "r");

// recuperer les donnees du fichier (nom + tout le reste)


taille = 0;
while( (fscanf(fic, "%s %s %d %d %d %d %d %s", nom[taille], pren,
&t1, &t2, &t3, &t4, &t5, mail) != EOF)
&& (taille < MAX) ){ // fichier < 40 lignes
sprintf(reste[taille], "%s %.2d %.2d %.2d %.2d %.2d %s", pren, t1,
t2, t3, t4, t5, mail);
taille++;
}

// fermeture du fichier
fermer_fichier(&fic, nom_fic);

// tri du tableau (par permutation)


for(i=0; i < taille; i++){
for(j=i; j < taille; j++){
if(strcmp(nom[i], nom[j]) > 0){
strcpy(inter, nom[j]);
strcpy(nom[j], nom[i]);
strcpy(nom[i], inter);
strcpy(inter, reste[j]);
strcpy(reste[j], reste[i]);
strcpy(reste[i], inter);
}
}
}

// stocker dans le fichier destination


ouvrir_fichier(&fic, "annuaire_trie.txt", "w");
for(i=0; i< taille;i++)
fprintf(fic, "%s %s\n", nom[i], reste[i]);
fermer_fichier(&fic, nom_fic);

printf("Les informations ont ete stockees dans annuaire_trie.txt\n");

return 0;
}

---------------------------------