Fichires en Langage C
Fichires en Langage C
Fichires en Langage C
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
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:
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 ?
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é.
Pour pouvoir travailler avec un fichier, un programme a besoin d'un certain nombre
d'informations au sujet du fichier:
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.
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
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
Fermer (NOM_FICHIER)
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:
#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;
}
#include <stdio.h>
#include <stdlib.h>
main()
{
FILE *P_FICHIER; /* pointeur sur FILE */
char NOM_FICHIER[30]; /* nom du fichier */
. . .
. . .
fclose(P_FICHIER);
return 0;
}
fclose( <PFichier> );
<PFichier> est un pointeur du type FILE* relié au nom du fichier que l'on désire fermer.
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!
ou bien
<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:
* <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.
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:
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.
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.
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.
ou bien
* < 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.
fscanf
ou bien
* <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
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.
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.
Remarque
L'instruction
fputc('a', stdout);
est identique à
putchar('a');
<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
#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 >);
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:
L'ancien fichier est entièrement copié dans le nouveau fichier, suivi du nouvel enregistrement.
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
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;
/* 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;
}
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;
}
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);
Lorsque vous voulez obtenir des informations sur le fichier, vous pouvez utiliser la
commande file.
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 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);
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>
strcpy(chaine, arguments[1]);
}
// 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 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
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.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
strcpy(chaine, arguments[1]);
}
// 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);
// 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
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 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);
}
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.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 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);
}
// fermeture du fichier
if(fclose(fic) == EOF){
printf("Probleme de fermeture du fichier %s", nom_fic);
exit(1);
}
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:
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
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
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.
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
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 mots,
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:
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.
Exemple:
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;
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;
#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);
}
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;
Exercice 5
#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;
#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 */
. . .
}
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;
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];
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 */
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é */
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 */
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 */
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:
#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 */
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. */
int SEPA(char C)
{
/* Tableau contenant tous les séparateurs de mots */
char SEP[12] = { '\n', ' ', ',', ';', '.', ':',
'?', '!', '(', ')', '"', '\'' };
int I;
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 */
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 */
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 */
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 *)
#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
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
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 ?
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
*******
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 8
8 5
0 3
1 3
2 3
3 3
4 0
15 1
1 9
1 1
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
#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
#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);
}
//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
#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;
}
#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
#include <stdio.h>
#include <stdlib.h>
//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
#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))
#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);
}
// 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
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
float note;
//saisie
printf("Entrez une note : ");
if(scanf("%f", ¬e) != 1){
printf("erreur de saisie\n");
exit(1);
}
return 0;
}
Autre version :
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
float note;
//saisie
printf("Entrez une note : ");
if(scanf("%f", ¬e) != 1){
printf("erreur de saisie\n");
exit(1);
}
#include <stdio.h>
int main(void){
int nb_marches = 0;
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
#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
#include <stdio.h>
#include <stdlib.h>
short indice;
long factorielle = 1; // pour stocker le resultat
return factorielle;
}
int main(void)
{
int 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>
short indice;
long factorielle = 1; // pour stocker le resultat
return factorielle;
}
int main(void)
{
int nombre_lu;
return 0;
}
#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
int main(void){
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
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;
#include <stdio.h>
#include <stdlib.h>
short indice;
long factorielle = 1; // pour stocker le resultat
return factorielle;
}
int main(void)
{
int lig, col;
// precision.c
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
double precision = 1.0;
return 0;
}
// pyramide.c
#include <stdio.h>
#include <stdlib.h>
return 0;
}
// fact_commande.c
#include <stdio.h>
#include <stdlib.h>
short indice;
long factorielle = 1; // pour stocker le resultat
return factorielle;
}
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
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define VRAI 1
#define FAUX 0
#define NBC 30
// saisie du mot
printf("Entrez un mot : ");
scanf("%s", mot);
trouve = FAUX;
nbcoups = 0; // compteur d'essais
while ((nbcoups < 10) && !trouve){ // on autorise 10 essais de 0 a 9
// affichage du masque
printf("%s", masque);
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] = '.';
}
/* 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;
/* 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++;
}
colonne = 1;
ligne++;
}
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 main(void)
{
int 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>
int main(void)
{
int nb1, nb2, res;
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>
return car;
}
int main(void)
{
int indice;
char mot[255];
indice = 0;
while(mot[indice] != '\0'){
mot[indice] = minuscule(mot[indice]);
indice++;
}
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>
int main(void)
{
int indice;
char mot[255];
indice = 0;
while(mot[indice] != '\0'){
minuscule(&mot[indice]);
indice++;
}
return 0;
}
// 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>
return compteur;
}
int main(void)
{
int taille; // taille du mot
int i;
int nboccur; // nb d'occurrences de la lettre
char texte[125];
taille = strlen(texte);
return 0;
}
puis essayez de l'utiliser lorsque le mot est entré sur la ligne de commandes.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
return compteur;
}
if(argc != 2){
printf("usage compter mot\n");
exit(1);
}
taille = strlen(argv[1]);
return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
return compteur;
}
return compteur;
}
int main(void)
{
int taille; // taille du mot
char txt[125];
taille = strlen(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.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
return compteur;
}
int main(void)
{
int i;
int nboccur; // nb d'occurrences de la lettre
taille = strlen(texte);
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
#include <stdio.h>
#include <stdlib.h>
printf("%c", car_cadre);
for(i=0; i<nb; i++)
printf("%c", car_interieur);
printf("%c\n", car_cadre);
}
FILE *fic;
int 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);
}
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>
strcpy(chaine, arguments[1]);
strcpy(nomch, arguments[2]);
}
// 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);
}
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);
}
if(argc != 2){
printf("Usage : trier nom_fichier\n");
exit(1);
}
strcpy(nom_fic, argv[1]);
// fermeture du fichier
fermer_fichier(&fic, nom_fic);
return 0;
}
---------------------------------