Vous êtes sur la page 1sur 18

Lyce technique Saint Michel : BTS IRIS

15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

Exercices algorithme
Mise en oeuvre des chanes des structures et des
fichiers

Pour tous les algorithmes crits, on prsente l'entte, la dclaration et


l'initialisation des variables et constantes. La programmation est de type
fonctionnelle.
Exercice
Le programme raliser permet de grer un annuaire tlphonique, c'est
dire :
de saisir un enregistrement
de stocker cet enregistrement
de relire l'ensemble de l'annuaire tlphonique.
De consulter un enregistrement

Chaque enregistrement contient les champs ci-dessous :


Le nom (maximum 20 caractres)
L'age (toujours positif et infrieur 1000)
Le numro de tlphone(maximum 14 caractres)

Contraintes gnrales:
On cr et on utilise une structure Annuaire qui contient les champs d'un
enregistrement.
On veille faire une fonction lorsque l'on retourne un seul paramtre
Le chemin et le nom du fichier et dfini dans le programme principal.
Aucune variable globale n'est admise sauf la structure Annuaire.
Le programme principal contient un minimum de code, il gre les appels de
fonctions.
Les enregistrements sont fait la suite du denier enregistrement du fichier.
L''ouverture de flux de fichiers est donc fait en mode ajout (append).
On respecte la structure de l'application prsente dans l'algorithme de
premier niveau.

Attention dans un chemin de fichier mettre deux \ (caractre d 'chappement)


pour qu'un \ soit pris en compte

Partie 1 : Accs squentiel


Contraintes spcifiques :
Le numro de tlphone (maximum 14 caractres) au format xx-xx-xx-xx-

1
Lyce technique Saint Michel : BTS IRIS
15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

xx
On ne peut pas consulter un enregistrement
Pour la saisie des champs, on passe en paramtre les lments de la
structure
L'age peut tre transform en chane de caractres

Dans cette partie on saisit une structure. La structure est transforme en


chane de caractres pour tre enregistre (chaque champ de la structure est
ajout dans une chane).
On n'oublie pas d'ajouter un retour la ligne \n pour que le fichier texte soit
correctement lisible.
Lors de la lecture du fichier on lit les chanes que l'on transforme en structure
avant l'affichage. Il faut retrouver chaque champ dans la chane grce au
sparateur le caractre ';'.

Pour l'accs squentiel, on peut utiliser les fonctions fprintf, fscanf, fputs,
fgets
Application :
Ecrire l'algorithme.
Ecrire le code C correspondant l'algorithme ci-dessus.

Question 2 : Accs direct


Contraintes spcifiques :
Le numro de tlphone (maximum 14 caractres) au format xx xx xx xx
xx
Pour les passages d'argument d'une structure, on passe en paramtre la
structure.
Il faut faire des enregistrements de taille fixe.
Il est prfrable de transformer l'ge en chane de caractres de taille
fixe (4caractres).
On lit un enregistrement spcifique.

Application :
Ecrire l'algorithme.
Ecrire le code C correspondant l'algorithme ci-dessus.

Pour l'accs direct :


On peut utiliser les fonctions d'enregistrement formates fprintf et
de lecture fputs.
Lors de l'enregistrement format avec fprintf, il faut utiliser le
nombre minimum de caractres dfinis avec justification gauche.
On ne peut plus utiliser fscanf pour la lecture d'un enregistrement.
Les espaces demand dans la chane Numro de tlphone pose
un problme. La lecture est stopp au premier blanc rencontr.
Voir la documentation.

2
Lyce technique Saint Michel : BTS IRIS
15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

On utilise fseek pour positionner la lecture d'un enregistrement


spcifique.

La transformation d'un nombre entier en chane de caractres est donne par


la fonction itoa ( int to alphanumrique).
La transformation d'une chane de caractres en nombre entier en est donne
par la fonction atoi (alphanumrique to int).

Partie 3 : Accs direct enregistrement et lecture de structures


Contraintes spcifiques :
Les contraintes spcifiques reprennent celles de la partie2.
Ici les saisies, les enregistrements et les lectures sont faits avec la structure
Annuaire. Cela vite les traitements de chanes fait dans les parties
prcdentes.
On lit le fichier entier.

Application :
Ecrire l'algorithme.
Ecrire le code C correspondant l'algorithme ci-dessus.

3
Lyce technique Saint Michel : BTS IRIS
15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

Maquette de l'application
Menu choix

Partie 1 : fichier squentiel


Saisie d'un enregistrement

Fichier squentiel enregistr

On remarque le retour chariot. Le dernier enregistrement est vide, il faudra


en tenir compte lors de la lecture et ne pas afficher cet enregistrement.

Lecture du fichier squentiel

Partie 2 fichier accs direct

4
Lyce technique Saint Michel : BTS IRIS
15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

Saisie d'un enregistrement

Fichier accs direct enregistr

Les enregistrements sont inscrit les uns la suite des autres

Lecture d'un enregistrement dans le fichier

Partie 2 fichier accs direct on enregistre et on lit directement la


structure
Saisie d'un enregistrement

5
Lyce technique Saint Michel : BTS IRIS
15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

Fichier accs direct enregistr avec des structures

6
Lyce technique Saint Michel : BTS IRIS
15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

Lecture du fichier

Algorithme de premier niveau

Annuaire : struture
Annuaire.Nom : chaine 20 caractres
Annuaire.Age : Entier
Annuaire.NumeroTel : chaine 14 caractres

UnAnnuaire : Structure Annuaire

Effacer l'cran

Partie 1
//On passe en rfrence les champs de la structure Annuaire
saisirUnAgendaSeq(UnAnnuaire.Nom, UnAnnuaire.Age,
UnAnnuaire.NumeroTel)
//On passe en rfrence la structure Annuaire
EnregistrerAgendaDansFichierSeq(CheminFichierSeq,UnAnnuaire)

//Lit le fichier complet


LectureFichierSeq()
//Transforme la chane lu en structure et l'affiche l'cran
traiterChaine()

Partie 2
saisirUnAgendaDirect(UnAnnuaire)
EnregistrerAgendaDansFichierDirect(UnAnnuaire)

//Lit l'enregistrement choisi et l'affiche


LectureFichierPosition()

Partie 3
saisirUnAgendaDirect(UnAnnuaire)
EnregistrerAgendaDansFichierDirectStructure(UnAnnuaire)

//Lit le fichier complet


LectureFichierPositionStructure()

7
Lyce technique Saint Michel : BTS IRIS
15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

Rponse
//---------------------------------------------------------------------------
// Travaux pratiques :
// Mise en oeuvre des structures de donnes
// criture et lecture d'un fichier
//
// En accs squentiel
// En accs direct
//P. TREBOSC Novembre 2007
//Version 1
//---------------------------------------------------------------------------
#pragma hdrstop

//---------------------------------------------------------------------------

#include <string.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <sys\stat.h>
#include <dos.h>
//Variables globales
struct agenda{
char Nom[20]; //Le nom max 19 caractres
int Age;
char NumeroTel[14];
};

void EnteteFeuille(char * MonEntete){


clrscr();
printf(MonEntete);
printf("\n");
printf("------------------------------------------------------------\n");
}
//Saisi d'un enregistrement pour accs sequentiel
void saisirUnAgendaSeq(char *nom, int *age, char *numerotel){

EnteteFeuille("Saisir un enregistrement : ");

printf("Saisir le nom (max 20 caractres): ");


do{
scanf("%s", nom);
}while(strlen(nom) > 20);

8
Lyce technique Saint Michel : BTS IRIS
15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

printf("Saisir l'age de l'abonn: ");


do{
scanf("%d", age);
}while((*age <0) || (*age >999));

printf("Saisir le numro de telphone format xx-xx-xx-xx-xx : ");


do{
scanf("%s", numerotel);
}while(strlen(numerotel) > 14);
}

//Saisi d'un enregistrement pour accs direct


void saisirUnAgendaDirect(struct agenda *MonAgenda)
{
EnteteFeuille("Saisir un enregistrement : ");
printf("Saisir le nom (max 20 caractres): ");
//Pour modifier les membre d'une structure, le programme passe la
//fonction un pointeur vers la structure.
//Dans la fonction, les commandes drfrencent les membres du pointeur
//en utilisant l'oprateur d'indirection *
//Pour modifier un membre de structure, le C commence dans les
parenthses,
//obtenant ainsi la position de la structure.
//Ensuite le C ajoute cette adresse le dcalage du membre donne
//Le c permet aussi d'utiliser le format quivalent suivant
do{
scanf("%s", (*MonAgenda).Nom);
}while(strlen(MonAgenda->Nom) > 20);

printf("Saisir l'age de l'abonn max (999) : ");


do{
scanf("%d", &(*MonAgenda).Age);
}while(((*MonAgenda).Age <0) || ((*MonAgenda).Age >999));

//Le fait qu'il y ait un espace propose une difficult


printf("Saisir le numro de telphone format xx xx xx xx xx: ");
fflush(stdin);
do{
gets( MonAgenda->NumeroTel);
}while(strlen(MonAgenda->NumeroTel) > 14);
}

//Enregistrement des chaines sans tenir compte de la longueur


//pour un enregistrement fichier texte squentiel
void EnregistrerAgendaDansFichierSeq(char *CheminFichier, struct agenda

9
Lyce technique Saint Michel : BTS IRIS
15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

*MonAgenda)
{
//Dclaration du fichier
FILE *fichier;
char UnEnregistrement[52]="";
char tempAge[4];

//Pour enregistrer un structure qui est une suite de chanes


//Il faut concatner les chanes dans une autre chane
//On peut ajouter un dlimitateur ou un sparateur
//ici un ;
strcat(UnEnregistrement,MonAgenda->Nom);
strcat(UnEnregistrement,";");
strcat(UnEnregistrement,itoa(MonAgenda->Age,tempAge,10));
strcat(UnEnregistrement,";");
strcat(UnEnregistrement,MonAgenda->NumeroTel);
//On peut mettre le retour chariot ici ou dans le printf
//strcat(UnEnregistrement,"\0");
strcat(UnEnregistrement,"\n");

//Enregistrement
//Ouverture du fichier texte en criture ajout
if((fichier = fopen(CheminFichier,"at"))== NULL)
printf("erreur l'ouverture du fichier %s en criture\n",CheminFichier);

//Ecriture de l'enregistrement
//Ecriture d'une chaine formate pas de pb pour crire une chaine
//contenant des espaces
//Test ok avec fscanf sauf la ligne si un blanc dans la chaine
fprintf(fichier,"%s",UnEnregistrement);

//Ecriture d'une chaine non formate


//fputs(UnEnregistrement,fichier);

//fwrite(&UnEnregistrement, sizeof(UnEnregistrement),1,fichier);

//Fermeture du fichier
fclose(fichier);
}

//transforme l'enregistrement lu dans le fichier en accs squentiel


//en structure agenda
//Le dlimiteur est le caractre ';'
void traiterChaine(char *MonEnregistrement)
{ int i=0,j=0,k=0;
struct agenda UnAgenda;

10
Lyce technique Saint Michel : BTS IRIS
15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

char MonAge[4];
//Initialisation des variables locales
//Indispensable pour ne pas avoir de caractres parasites
strcpy(MonAge," ");
strcpy(UnAgenda.Nom," ");
UnAgenda.Age=0;
strcpy(UnAgenda.NumeroTel," ");

//Traitement de la chaine UnEnregistrement pour mise en structure agenda


//Recherche du nom
//Recherche de la premire occurence du caractre ;
while(MonEnregistrement[i] != ';'){
UnAgenda.Nom[i] = MonEnregistrement[i];
i++ ;
}
printf("%-20s",UnAgenda.Nom);

//Recherche de l'age
while(MonEnregistrement[j+i+1] != ';'){
MonAge[j] = MonEnregistrement[j+i+1];
j++;
}
printf("%-4s",MonAge);
UnAgenda.Age = atoi(MonAge);

//Recherche du numro de tlphone


//on ne lit pas le dernier retour chariot
//cela pose un pb car il y a criture des caractres vides suivants
//et c'est mieux pour transformer en structure
while((k+j+i+2) < (strlen(MonEnregistrement)-1) ){
UnAgenda.NumeroTel[k] = MonEnregistrement[k+j+i+2];
k++;
}
printf("%s",UnAgenda.NumeroTel);

//Il y a dj un \n dans la lecture du dernier champ UnAgenda.NumeroTel


//Il est mis automatiquement l'enregistrement
//Mais on ne l'a pas lu
printf("\n");
}

void LectureFichierSeq(char *CheminFichier)


{
int i;
//Dclaration du fichier
FILE *fichier;

11
Lyce technique Saint Michel : BTS IRIS
15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

//struct agenda MonAgenda;


char UnEnregistrement[39]="";
//ou
//char *UnEnregistrement;
//Ouverture du fichier en lecture

clrscr();
if((fichier = fopen(CheminFichier,"r"))==NULL){
printf("Erreur l'ouverture du fichier %s ",CheminFichier);
exit(1);
}

//Ecriture entte
EnteteFeuille("Lecture d'un fichier sequentiel\nAvec traitement de
structure\n ");

printf("Nom Age Numero telephone\n");


//Lecture du fichier
//On lit ligne par ligne
while(!feof(fichier)){
//
for(i=0;i<strlen(UnEnregistrement);i++)
UnEnregistrement[i]=NULL;
//Lecture du fichier
//Attention : avec fscanf dans le cas d'une chane qui contient un
//espace, on passe l'enregistrement suivant
//fscanf(fichier,"%s",UnEnregistrement);
//Si une chaine contient des espaces il vaut mieux utiliser fgets
fgets(UnEnregistrement,39,fichier);

//Ne peut tre utilis que lorsque l'on connait la taile prcise
//de l'enregistrement. Ici on lit 52 octets, si, il y a des retours
// la ligne on passe la ligne grace au printf
//Ne pas utiliser dans notre cas :
//fread(UnEnregistrement,39,1, fichier);
//On traite chaque ligne pour la mettre en structure si ncessaire
//Affichage l'cran sans mise en forme
//printf("%s",UnEnregistrement);
//Le dernier champ enregistr est NULL du fait du retour chariot
// l'enregistrement

//Affichage l'cran avec mise en forme


if(UnEnregistrement[0] != NULL)
traiterChaine(UnEnregistrement);
}
//Fermeture du fichier

12
Lyce technique Saint Michel : BTS IRIS
15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

fclose(fichier);
}

//Enregistrement des chaines de longueur fixe


//pour une lecture fichier texte accs direct
void EnregistrerAgendaDansFichierDirect(char *CheminFichier, struct agenda
*MonAgenda)
{
int i;
//Dclaration du fichier
FILE *fichier;
char MonNom[20]="";
char MonAge[4]="";
char NumeroTelephone[14]="";
char tempAge[4];

//Pour enregistrer un structure qui est une suite de chanes


//Il faut concatner les chanes dans une autre chane
//On peut ajouter un dlimitateur ou un sparateur
//ici un ;
strcat(MonNom,MonAgenda->Nom);
//On est en base 10
strcat(MonAge,itoa(MonAgenda->Age,tempAge,10));
strcat(NumeroTelephone,MonAgenda->NumeroTel);

//Enregistrement
//Ouverture du fichier texte en criture ajout
if((fichier = fopen(CheminFichier,"at"))== NULL)
printf("erreur l'ouverture du fichier %s en criture\n",CheminFichier);

//Ecriture de l'enregistrement
//Nombre minimum de caractres dfinis avec justification gauche
//Si le \n est mis, cela positionne un retour chariot donc un enregistrement
//vide est enregistr
//Par contre on a automatiquement un retour chariot lors de la lecture du
//fichier texte l'cran (c'est un choix)
fprintf(fichier,"%-19s %-3s %-14s",MonNom,MonAge,NumeroTelephone);

//Fermeture du fichier
fclose(fichier);
}
//Lecture d'un fichier en accs direct
void LectureFichierPosition(char *CheminFichier)
{
//Dclaration du fichier
FILE *fichier;

13
Lyce technique Saint Michel : BTS IRIS
15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

//Dfinition de l'indice
int positionIndice = 0;
char MonNom[20]="", MonAge[4]="",NumeroTelephone[14]="";

EnteteFeuille("Lecture d'un enregistrement dans un fichier a acces


direct\n : ");

//Choix de l'indice
printf("Choisir le numro d'enregistrement de lecture du fichier : ");
scanf("%d", &positionIndice);
//Attention : On commence 0 donc dcaler de 1 pour avoir la bonne
//correspondance numro d"'enregistrement indice de lecture du fichier
//Il faut tenir compte du caractre retour chariot ajout \n
//Pour une chane de 38 +1
//puis encore +1 pour le caractre suivant
positionIndice = (positionIndice-1) * 38;

//Ouverture du fichier en lecture fichier texte


fichier = fopen(CheminFichier,"rt");

//Positionne le pointeur de flux sur l'indice


//Lit l'enregistrement partir de l'indice
//On dmarre partir du dbut du fichier
fseek(fichier,positionIndice,1);

//Utiliser fgets pour lecture fichier accs direct


//Attention fgets stoppe la lecture n-1 caractres
//Si on veut lire une chane de 20 caractres, il faut indiquer le
//nombre de caractres lire 21
//Il faut rajouter le caractre \0 pour avoir un bon affichage
//On ne peut pas les mettre l'enregistrement
fgets(MonNom,21,fichier);
MonNom[19]='\0';
fgets(MonAge,5,fichier);
MonAge[3]='\0';
fgets(NumeroTelephone,15,fichier);
NumeroTelephone[14]='\0';
//Ecriture entte
printf("Nom Age Numero telephone\n");
printf("%s%s %s",MonNom,MonAge,NumeroTelephone);
printf("\n");
}

//Lecture du fichier complet en accs direct


EnregistrerAgendaDansFichierDirectStructure(char *CheminFichier, struct
agenda *MonAgenda)

14
Lyce technique Saint Michel : BTS IRIS
15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

{ //Dclaration du fichier
FILE *fichier;
int NbEnr;
//Ouverture du fichier en ecriture append
if((fichier = fopen(CheminFichier,"at"))==NULL){
printf("Erreur l'ouverture du fichier %s ",CheminFichier);
exit(1);
}
//NbEnr = fwrite(MonAgenda,sizeof(*MonAgenda),1,fichier);
//ou
NbEnr = fwrite(MonAgenda,sizeof(struct agenda),1,fichier);

//fputs(MonAgenda,fichier);
fclose(fichier);
}

void LectureFichierPositionStructure(char *CheminFichier)


{
int i;
long positionIndice;
//Dclaration du fichier
FILE *fichier;
//Dfinition de l'indice
struct agenda MonAgenda;;

if((fichier = fopen(CheminFichier,"r"))==NULL){
printf("Erreur l'ouverture du fichier %s ",CheminFichier);
exit(1);
}

//Ecriture entte
EnteteFeuille("Lecture par sturucture dans un fichier a acces direct\n");
printf("Nom Age Numero telephone\n");
//Lecture du fichier - On lit ligne par ligne

positionIndice=0;

while(!feof(fichier)){
strcpy(MonAgenda.Nom ," ");
//
for(i=0;i<strlen(MonAgenda.Nom);i++)
MonAgenda.Nom[i]=NULL;
for(i=0;i<strlen(MonAgenda.NumeroTel);i++)
MonAgenda.NumeroTel[i]=NULL;

//Positionnement sur l'enregistrement lire

15
Lyce technique Saint Michel : BTS IRIS
15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

fseek(fichier,positionIndice,0);

fread(&MonAgenda,sizeof(struct agenda),1,fichier);

//Affichage l'cran avec mise en forme


//On ne lit pas le dernier enregistrement qui est NULL
if(MonAgenda.Nom[0] != NULL){
printf("%-20s",MonAgenda.Nom);
printf("%-4d",MonAgenda.Age);
printf("%-13s\n",MonAgenda.NumeroTel);
}
positionIndice = positionIndice + 40;

//Fermeture du fichier
fclose(fichier);
}

char choixAcces(void)
{ char choix;
printf("Partie 1 - fichier sequentiel:\n");
printf(" Saisir et enregistrer -> 1\n");
printf(" Lire -> 2\n\n");
printf("Partie 2 - fichier accs direct :\n");
printf(" Saisir et enregistrer -> 3\n");
printf(" Lire -> 4\n\n");
printf("Partie 3 - fichier accs direct d'une structure :\n");
printf(" Saisir et enregistrer -> 5\n");
printf(" Lire -> 6\n\n");
printf("Votre choix : ");
fflush(stdin);
scanf("%c",&choix);
return choix;
}
#pragma argsused
void main(int argc, char* argv[])
{
struct agenda UnAgenda;
char *CheminFichierSeq;
char *CheminFichierDir;
char *CheminFichierDirStruc;
char choixAccesfichier;
char Continuer=NULL;

16
Lyce technique Saint Michel : BTS IRIS
15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

CheminFichierSeq =
"D:\\Prgm_Builder\\PrgmConsoleAlgo\\FichierPersonne\\agendaSeq.txt";
CheminFichierDir =
"D:\\Prgm_Builder\\PrgmConsoleAlgo\\FichierPersonne\\agendaDir.txt";
CheminFichierDirStruc =
"D:\\Prgm_Builder\\PrgmConsoleAlgo\\FichierPersonne\\agendaDirStruc.txt";

do{
clrscr();
choixAccesfichier = choixAcces();
switch (choixAccesfichier){
//Partie 1
//Pour enregistrement et lecture fichier squentiel
//--------------------------------------------------------------------------
case '1' :
//Passage de la structure par lment
saisirUnAgendaSeq(&UnAgenda.Nom, &UnAgenda.Age,
&UnAgenda.NumeroTel);
EnregistrerAgendaDansFichierSeq(CheminFichierSeq,&UnAgenda);
break;
case '2' :
LectureFichierSeq(CheminFichierSeq);
break;

//Partie 2
//Pour enregistrement et lecture fichier accs direct
//Pour l'accs direct : taille des enregistrements fixe
//--------------------------------------------------------------------------
case '3' :
//Passage de la structure en paramtre
//Comme la fonction doit modifier la structure, le programme passe la
//fonction un pointeur vers la structure
//variable structure par rfrence (ou par adresse)
saisirUnAgendaDirect(&UnAgenda);
EnregistrerAgendaDansFichierDirect(CheminFichierDir,&UnAgenda);
break;
case '4' :
LectureFichierPosition(CheminFichierDir);
break;

//Partie 3
//Pour enregistrement et lecture fichier accs direct
//Pour l'accs direct : taille des enregistrements fixe
//--------------------------------------------------------------------------
case '5' :
//Passage de la structure en paramtre

17
Lyce technique Saint Michel : BTS IRIS
15/03/17
Exercice ralgorithme : 348244614.odt P.
TREBOSC

//Comme la fonction doit modifier la structure, le programme passe la


//fonction un pointeur vers la structure
//variable structure par rfrence (ou par adresse)
saisirUnAgendaDirect(&UnAgenda);

EnregistrerAgendaDansFichierDirectStructure(CheminFichierDirStruc,&UnA
genda);
break;
case '6' :
LectureFichierPositionStructure(CheminFichierDirStruc);
break;
}
printf("Voulez vous continuer : \n");
printf(" Oui -> 1\n");
printf(" Non -> 0\n");
fflush(stdin);
scanf("%c",&Continuer);
}while(Continuer == '1');
getch();
}
//---------------------------------------------------------------------------

18