langages de programmation langages de

publicité
IUT FV Bandjoun // Département d’Informatique (IG1 2008)
LANGAGES DE PROGRAMMATION
« Structures de Stockage : Les FICHIERS - LANGAGE C »
1. LA STRUCTURE DE « SUITE »
Une structure de suite peut être déclarée comme suit:
File
*f ;
Tous les éléments de la suite sont du même type (To) appelé
type de base de la suite, To pouvant être de type simple (char,
int, foat, ...) ou structuré (struct, typedef, ...)
une suite de n éléments sera notée f = < fo, f1, f2, f3, ......, fn-1
>
Cette suite ressemble à la structure de tableau à la différence
que la dimension du tableau est fxée à la création alors que
dans la structure de suite la dimension est ouverte et varie au
cours de l’exécution du programme .
la conséquence est qu’un schéma d’allocation dynamique doit
être employé comme pour toutes les structures dont la
cardinalité est « infnie ». On place la suite dans les structures
fondamentales
car le mécanisme d’allocation d’un
emplacement mémoire (stockage) peut être effectué
simplement, pour autant que l’on se restreigne à certaines
contraintes lors de l’utilisation des suites.
La contrainte se résume à l’usage restrictif des seuls accès
séquentiels pour les suites. Cela veut dire que les suites seront
utilisées en procédant d’un élément à son suivant immédiat et
en construisant les suites par ajout répété d’un élément à son
extrémité. Cela signife que les éléments ne sont pas
directement accessibles à priori, ce qui constitue la différence
fondamentale avec les tableaux.
On utilisera le terme « fchier séquentiel » pour les suites, et
en général, le terme séquentiel sera implicite.
2. OPERATEUR S SUR LES « SUITES »
(Fichiers en Turbo C)
La simplicité de l’accès séquentiel peut être renforcée
par l’usage d’un ensemble exclusif d’opérateurs bien défnis,
commun à tout les types de fchiers.
■ FILE = fopen(const char *flename, const char *mode);
//… ouvre un fux.
On associe un fchier réel constant (sur disquette par exemple)
qui est le fchier physique (flename) à un nom variable dans le
programme qui est le fchier logique (FILE). Mode
est le
mode d’accès au fchier ouvert (r, w, a, r+, w+, a+, etc.)
- w défnit FILE comme la suite vide de longueur 0, ouvre
-
// … écrit n éléments ayant chacun une taille de size octets à la
fn (suite) du fchier.
■ int feof(FILE *stream); //…teste l'arrivée en fn de fchier
fux.
feof est une macro qui scrute un fux à la recherche du
marqueur de fn de fchier.
■ int fclose(FILE *stream); //ferme un fchier fux nommé
stream
Le concept de fchier joue un rôle essentiel et constitue une
abstraction de données rangées sur un dispositif:
• bandes, disques, lecteurs de cartes ... (lecture et écriture).
• imprimantes (écriture).
• clavier (lecture).
ceci permettant d’exprimer d’une manière générale les
caractéristiques et opérations qui leur sont communes.
3. FICHIERS D’ENTIERS
(et générateur de nombres aléatoires)
Il est de grande importance pour la simulation de
phénomènes physiques de disposer d’un générateur de nombres
aléatoires. Mais il n’existe pas de moyens de produire de vrais
nombres aléatoires à partir d’un ordinateur ni d’ailleurs de
n’importe quel système déterministe.
Il est pourtant possible de construire des générateurs de
nombres pseudo-aléatoires distribués de façon uniforme .
C’est la propriété de la fonction random du TURBO C qui crée
un nombre compris dans [0..1[, et random(n) qui crée un entier
compris dans [0..n-1].
Les nombres pseudo-aléatoires distribués selon une loi non
uniforme seront déterminés à partir de la distribution uniforme.
Exercice 1:
•Ecrire le programme qui crée un fchier de 1000
entiers uniformément répartis entre 0 et 20, dénommé
Notes.data et placé dans le sous-répertoire IG
•Ecrire le programme qui comptera le nombre
d’apparitions de chaque Note (on rangera ces fréquences dans
un tableau). On affchera le résultat et on dessinera ensuite
l’histogramme des fréquences. Conclusion ?
•Ecrire le programme qui déterminera pour chaque
valeur la plus longue suite de valeurs identiques.
le fchier en écriture.
Exercice 2:
a ouvre le fchier
Void création (char* str1, str2);
File *fc1, *fc2 ; int i ;
{
en lecture-écriture (mise à jour) et
place la position courante au début de FILE.
- r ouvre le fchier en lecture et place la position courante
au début de FILE.
■ int creat(const char *path, int amode);
// Crée un nouveau fchier ou vide son contenu si le fchier
existe.
Path désigne le nom du fchier sur le support extérieur (ex:
lecteur de disquette). Sa présentation dépendra de « l’Operating
System » ( ″″a:\ig1\monfchier.doc ″″pour le cas de MS DOS).
Amode désigne le mode d’ouverture : S_IREAD
|
S_IWRITE
■ size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
// … lit un nombre d'éléments de données de taille identique
depuis un fux en entrée vers un bloc mémoire.
Les éléments sont placés à la position courante et le pointeur
avance sur l’élément (position) suivant.
■ size_t fwrite(const void *ptr, size_t size, size_t n,
FILE*stream);
Dr. NKENLIFACK Marcellin
fc1=fopen(str1,"w+");
fc2=fopen(str2,"w+");
for (i=1; i<=100; i++)
{
if (random ( 2)==0) fwrite(&i,sizeof(i),1,fc1);
else
fwrite(&i,sizeof(i),1,fc2);
}
fclose(fc1) ;
fclose(fc2) ;
}
Soient les fchiers F.num et G.num qui contiennent des suites
ordonnées d’entiers F1, F2, ..., Fm et G1, G2, ..., Gn tels que:
Fi+1 ≤≤Fi et Gj+1 ≤≤Gj pour tout i, j .
* Ecrire le programme commenté qui fusionne ces deux
fchiers en un fchier ordonné H.num tel que
Hk+1 ≤≤Hk pour k=1, 2, ..., m+n-1;
Page 1 / 5
IUT FV Bandjoun // Département d’Informatique (IG1 2008)
LANGAGES DE PROGRAMMATION
« Structures de Stockage : Les FICHIERS - LANGAGE C »
4. FICHIERS DE CARACTERES
Exercice 3:
* Ecrire le programme qui lit un fchier de caractères, par
exemple
votre plus long programme, qui compte la fréquence
d’apparition des lettres
de l’alphabet
et
dessine
l’histogramme des fréquences.
* Ecrire le programme qui lit un fchier de caractères, par
exemple votre plus long programme, qui restitue ce fchier
à l’écran et l’imprime en même temps.
Nota Bene: l’écran de votre micro-ordinateur est un fchier
particulier considéré comme une « valeur » par défaut (stdout
= fux sortie); il en est de même pour le clavier (stdin = fux
des entrées par défaut).
L’imprimante est un fchier particulier et la variable fchier
qui désigne l’imprimante est prédéfnie: stdprn.
On peut également utiliser la variable PRN prédéfnie en
défnissant son propre fchier d’impression :
#include <stdio.h>
void main(void)
{
FILE *imprimante;
char mot1[24]="test impression numero 1";
char mot2[24]="test impression numero 2";
imprimante = fopen ("prn", "w");
fprintf(imprimante, "%s\n",mot1);
fprintf(imprimante, "%s\n",mot2);
fprintf(imprimante,"\nFIN IMPRESSION: Merci ... ");
}
Exercice 4:
L’éditeur du TURBO C constituerait un traitement
de texte convenable, pour autant que l’on puisse imprimer à sa
convenance des mots en gras, en souligné, ou les deux
conjointement (la liste n’est pas exhaustive et l’on pourrait par
exemple imprimer les indices et les exposants, ...).
•Ecrire le programme qui lit un fchier de caractères,
qui l’imprime (d’abord à l’écran, puis directement à
l’imprimante) et qui en particulier commence l’écriture en gras
à la lecture du caractère ‘&’ (mais qui ne l’imprime pas) et
termine l’écriture en gras au prochain ‘&’ (sans l’imprimer).
Idem pour le soulignage en utilisant le caractère ‘$’.
Nota Bene:
L’imprimante passe en caractère gras par la commande
suivante:
fprintf(stdprn,"%c%c%",27,69);
et supprime le mode gras par la commande suivante:
fprintf(stdprn,"%c%c%",27,70);
L’imprimante passe en mode souligné par la commande
suivante:
fprintf(stdprn,"%c%c%d",27,45,1);
et supprime le mode souligné par la commande suivante :
fprintf(stdprn,"%c%c%d",27,45,0);
Exercice 5:
Comparer deux fchiers, l’un ″″*.C″″ l’autre ″″*.bak″″, on
affchera chaque ligne l’une après l’autre, avec arrêt après la
première différence qui sera signalée par la sonnette.
5. OPERATEURS PERMETTANT UN ACCES
DIRECT SUR LES FICHIERS
Le TURBO C défnit des opérateurs supplémentaires qui
permettent un accès direct dans le cas de fchiers dont les
éléments sont identiques. Ce sont :
Dr. NKENLIFACK Marcellin
• int fseek (FILE *stream, long offset, int whence);
// fait pointer le pointeur de fchier associé au fux stream à la
position située offset octets au-delà de l'emplacement indiqué.
Whence permet de déterminer le point de départ de la
recherche dans le fchier : SEEK_SET Recherche depuis le
début du fchier, SEEK_CUR Recherche depuis la position
courante,
SEEK_END Recherche depuis la fn du fchier
■ void rewind(FILE *stream);
//… Repositionne le pointeur de fchier sur le début d'un
fux.
rewind(stream) équivaut à fseek(stream, 0L, SEEK_SET)
sauf que rewind remet à zéro les indicateurs de fn de fchier et
d'erreur, alors que fseek ne le fait que pour celui de fn de
fchier.
■ int fgetpos(FILE *stream, fpos_t *pos);
//… donne la valeur courante du pointeur d'un fchier fux
■ int fsetpos(FILE *stream, const fpos_t *pos);
//…modife la valeur courante du pointeur d'un fchier fux
fgetpos sauvegarde la position du pointeur de fchier associé au
fux stream dans l'emplacement *pos pointé par pos. La valeur
exacte ne vous est d'aucune utilité ;
fsetpos affecte une nouvelle valeur au pointeur de fchier
associé au fux stream. Le nouvel emplacement est une valeur
obtenue par un précédent appel à fgetpos sur ce fux.
fsetpos efface l'indicateur de fn de fchier du fchier pointé par
stream et annule les effets d'appels à ungetc sur ce fchier.
■ long ftell(FILE *stream);
// renvoie la position courante d'un pointeur de fchier du fux
stream
Exercice 6: écrire une fonction qui renvoie la taille (nombre
d’éléments de la suite) d’un fchier quelconque.
long flesize(FILE *stream)
{
long curpos, length;
curpos = ftell(stream);
fseek(stream, 0L, SEEK_END);
length = ftell(stream);
fseek(stream, curpos, SEEK_SET);
return length;
}
6. MANIPULATION DES FICHIERS
FICHIER D’ARTICLES (enregistrements)
Le langage C permet l’accès aux fchier structurés (de
n’importe quel type), aux fchiers binaires, …
Il se confrme indéniablement comme étant un bon langage de
« bas niveau », que ce soit en général ou en ce qui concerne les
manipulations de fchiers.
Nous commençons par manipuler les fchier structurés
simplement.
6.1. CREATION DE FICHIERS STRUCTURES
6.1.1. exemple global
/* FIALEA.C -- CREATION DE FICHIER STRUCTURE
D’ELEMENTS */
#include <stdio.h>
#include <stdlib.h>
#include "fonchar.c" //le fichier "fonchar.c"
contient le corps des fonctions gencaralea()
et genstralea()
#define N 10
Page 2 / 5
IUT FV Bandjoun // Département d’Informatique (IG1 2008)
LANGAGES DE PROGRAMMATION
« Structures de Stockage : Les FICHIERS - LANGAGE C »
#define LP 15
#define LN 25
typedef struct
{
char nom[LN], prenom[LP];
int ds1,ds2,ds3, ds4;
float moy;
}Tetud, *Tptretud;
int main()
{
FILE *f;
int i,j;
Tetud * ptretud;
Tetud etud;
clrscr();
ptretud=(Tptretud) calloc(1,sizeof(Tetud));
if (ptretud==NULL)
{
printf("erreur d'allocation memoire");
return(1);
}
f=fopen("e:\\sysnk\\tpetud\\tc30\\doc\\essai1.
doc","wb+");
if (f== NULL)
{
printf("erreur de creation de fichier");
return(1);
}
for (i=0;i<N;++i)
{
genstralea(etud.nom,LN);
genstralea(etud.prenom,LP);
etud.ds1=rand()%21; etud.ds2=rand()%21;
etud.ds3=rand()%21; etud.ds4=rand()%21;
etud.moy=(float)(etud.ds1+etud.ds2+etud.ds3+et
ud.ds4)/4;
ptretud[0]=etud; // *ptretud=etud;
printf("%-25s%15s%6d%6d%6d%6d%8.2f\n",(*ptretud).nom,(*ptretu
d).prenom,
ptretud->ds1,ptretud>ds2,ptretud[0].ds3,ptretud[0].ds4,ptretud[0].m
oy);
fwrite(ptretud, sizeof(Tetud), 1, f);
}
rewind(f);
printf("\n..Lecture et affichage des elements
du fichier...\n\n");
while (fread(ptretud, sizeof(Tetud), 1, f))
{
printf("%-25s%15s%6d%6d%6d%6d%8.2f\n",(*ptretud).nom,(*ptretu
d).prenom,
ptretud->ds1,ptretud>ds2,ptretud[0].ds3,ptretud[0].ds4,ptretud[0].m
oy);
}
fclose(f);
getch(); return(0);
}
6.1.2.
2ème exemple global
/* FIALE2.C -- CREATION DE FICHIER STRUCTURE
ET AFFICHAGE DES ELEMENTS LUS PAR BLOC */
#include <stdio.h>
Dr. NKENLIFACK Marcellin
#include <stdlib.h>
#include "fonchar.c" //le fichier "fonchar.c"
contient le corps des fonctions gencaralea()
et genstralea()
#define N 10
#define LP 15
#define LN 25
typedef struct
{
char nom[LN], prenom[LP];
int ds1,ds2,ds3, ds4;
float moy;
}Tetud, *Tptretud;
int main()
{
FILE *f;
int i,j;
Tptretud ptretud1,ptretud5;
Tetud etud;
clrscr();
ptretud1=(Tptretud) calloc(1,sizeof(Tetud));
ptretud5=(Tptretud) calloc(5,sizeof(Tetud));
if (ptretud1==NULL)
{
printf("erreur d'allocation memoire");
return(1);
}
f=fopen("e:\\sysnk\\tpetud\\tc30\\doc\\essai1.
doc","wb+");
if (f==NULL)
{
printf("erreur de creation de fichier");
return(1);
}
for (i=0;i<N;++i)
{
genstralea(etud.nom,LN);
genstralea(etud.prenom,LP);
etud.ds1=rand()%21; etud.ds2=rand()%21;
etud.ds3=rand()%21; etud.ds4=rand()%21;
etud.moy=(float)(etud.ds1+etud.ds2+etud.ds3+et
ud.ds4)/4;
*ptretud1=etud; /* ptretud1[0]=etud; */
printf("%-25s%15s%6d%6d%6d%6d%8.2f\n",(*ptretud1).nom,(*ptret
ud1).prenom,
ptretud1->ds1,ptretud1>ds2,ptretud1[0].ds3,ptretud1[0].ds4,ptretud1[0
].moy);
fwrite(ptretud1, sizeof(Tetud), 1, f);
}
rewind(f);
printf("\n..Lecture par bloc de 5 et affichage
des elements du fichier...\n\n");
while (fread(ptretud5, sizeof(Tetud), 5, f))
{ /*..lecture du fichier par bloc de 5
elements..*/
for (i=0;i<5;++i)
{
printf("%-25s%15s%6d%6d%6d%6d%8.2f\n",ptretud5[i].nom,ptretud
5[i].prenom,
ptretud5[i].ds1,ptretud5[i].ds2,ptretud5[i].ds
3,ptretud5[i].ds4,ptretud5[i].moy);
Page 3 / 5
IUT FV Bandjoun // Département d’Informatique (IG1 2008)
LANGAGES DE PROGRAMMATION
« Structures de Stockage : Les FICHIERS - LANGAGE C »
}
}
fclose(f);
getch(); return(0);
}
Exercice 7:
Ecrire un programme généralisé qui crée un fchier DUTIG
de 150 articles de type :
Tetudiant et contenant entre autres
{
nom : string[18] ;
classe : string[4] ;
note1 : 0..20 ;
note2 : 0..20 ;
moy : real ;
reussi : boolean ; /* déf. True=0,
False=1 */
classement : int ;
}
Le champ nom sera une chaîne de caractères construite de
façon aléatoire et de longueur [5..18]. Le champ classe aura
aléatoirement la valeur : IG1, IG2 , IG3. Les notes des valeurs
aléatoires [0..20], la moyenne initialisée à -l et le champ reussi
initialisé à False.
Exercice 8 (suite exercices précédents):
•
•
Ecrire le programme qui calcule la moyenne pour chaque
étudiant, et met le champ réussi à True si la moyenne est
≥≥
10.
Ecrire le programme qui affche les étudiants de DUTIG
ayant réussi. On vérifera que la moyenne a été calculée
correctement.
7. TRI D’UN FICHIER
/* FICETRI.C -- GESTION DE FICHIER STRUCTURE
ET TRI SUR SES ELEMENTS */
#include <stdio.h>
#include <sys\stat.h> // bibliotheque contenant
des informations au sujet de fichier ou de
r‚pertoire
#include <stdlib.h>
#include "fonchar.c" //le fichier "fonchar.c"
contient le corps des fonctions gencaralea()
et genstralea()
#define LP 10
#define LN 20
typedef struct
{
char nom[LN], prenom[LP];
int ds1,ds2,ds3, ds4;
float moy;
}Tetud, *Tptretud;
typedef struct
{
char nom[LN];
unsigned long cpos;
}Tnoeud, *Tptrnoeud;
void triselect(Tptrnoeud l, int taille)
{
int k,j,min;
Tnoeud s;
for(k=0;k<taille;++k)
{
min=k;
Dr. NKENLIFACK Marcellin
for(j=k+1;j<taille;++j)
{
if (strcmp(l[j].nom,l[min].nom)<0) min=j;
}
s=l[min];
l[min]=l[k];
l[k]=s;
}
}
main()
{
FILE *f;
int i;
unsigned long N;
Tptretud ptretud;
Tetud etud;
Tnoeud lnoeud;
Tptrnoeud ptrtab;
struct stat statrecord;
clrscr();
ptretud=(Tptretud) calloc(1,sizeof(Tetud));
if (ptretud==NULL)
{
printf("erreur d'allocation memoire");
return(1);
}
if
((f=fopen("e:\\sysnk\\tpetud\\tc30\\doc\\essai3
.doc","wb+"))==NULL)
//... utilisation du fichier cree par un
aiutre programme <FICLISTL.C>
{
printf("erreur d'ouverture de fichier");
return(1);
}
//... utilisation du fichier cree par un autre
programme:<FICLISTL.C>
stat("e:\\sysnk\\tpetud\\tc30\\doc\\essai3.doc
",&statrecord);
//... calcul du nombre d'elements du fichier a
partir de la taille du fichier et de la taille
d'element <Tetud>
N=(statrecord.st_size)/sizeof(Tetud);
printf("Nombre d'elements = %lu\n...\n", N);
getch();
ptrtab
=
(Tptrnoeud)
calloc
sizeof(Tnoeud));
if (ptrtab==NULL)
{
printf("erreur d'allocation memoire");
return(1);
}
i=0;
while (fread(ptretud, sizeof(Tetud), 1, f))
{
printf("%-20s%10s%6d%6d%6d%6d%8.2f",ptretud->nom,ptretud>prenom,
ptretud->ds1,ptretud->ds2,ptretud>ds3,ptretud->ds4,ptretud->moy);
strcpy(ptrtab[i].nom, ptretud->nom);
ptrtab[i].cpos=i;
++i;
}
printf("\n...FICHIER INITIAL...\n");
for (i=0;i<N;i++)
printf("%20s%10lu\n",ptrtab[i].nom,ptrtab[i].cpos);
triselect(ptrtab, N); // TRI du tableau...
printf("\n...FICHIER TRIE ...\n");
for (i=0;i<N;i++)
Page 4 / 5
(N,
IUT FV Bandjoun // Département d’Informatique (IG1 2008)
LANGAGES DE PROGRAMMATION
« Structures de Stockage : Les FICHIERS - LANGAGE C »
printf("%20s%10lu\n",ptrtab[i].nom,ptrtab[i].cpos);
printf("\n..BIEN SUCCES NON!!!");
getch(); return(0);
}
{
c = getc(fc1) ;
c = c - alea ;
putc(c, fc2) ;
}
fclose(fc1) ; fclose(fc2) ;
}
Exercice 9 (suite exercices précédents):
Ecrire le programme qui effectue le classement des étudiants
de DUTIG crées précédemment.
Exercice 10 (suite exercice précédents):
Ecrire le programme qui crée un fchier trié alphabétiquement
pour chaque classe (TRI par nom, prenom et classe), en
utilisant le fchier précédent.
8. CRYPTAGE DES FICHIERS
Le principe du cryptage d’un fchier « fc1 » pour obtenir
un fchier « fc2 » se résume en l’utilisation d’une
fonction bijective « C » qu’on applique sur fc1. C(fc1)
= fc2
L’opération inverse (décryptage) consiste à effectuer
C-1 (fc2) = fc1.
La fonction f(x) = x+a est bijective et f -1 (x) = x-a.
Problème :
On suppose que vous disposez d’une fonction génératrice
de nombres pseudo-aléatoire intitulée
int alea ( ) ; qui génère une suite pseudo-aléatoire de
nombres compris dans l’intervalle [0.. n]
on utilisera cette fonction pour coder les caractères d’un
fchier texte (ex. un de vos programmes C) afn de rendre
celui-ci incompréhensible.
On demande d’écrire 2 procédures :
Void Lisible ( char* ch1, ch2 ) ; créant à partir d’un
fchier de nom physique ch1, un fchier crypté de nom
physique ch2.
Void ILisible ( char* ch1, ch2 ) ; créant à partir d’un
fchier crypté de nom physique ch1, un fchier décrypté
de nom physique ch2.
On écrira un programme pour tester ces procédures
Void Lisible ( char* ch1, ch2 ) ;
{
File *fc1, *fc2 ;
Char c ;
fc1 = fopen(ch1,"r")
while ( !feof(fc1))
{
c = getc(fc1) ;
c = c + alea ;
putc(c, fc2) ;
}
fclose(fc1) ; fclose(fc2) ;
}
Void ILisible ( char* ch1, ch2 ) ;
{
File *fc1, *fc2 ;
Char c ;
fc1 = fopen(ch1,"r")
while ( !feof(fc1))
Dr. NKENLIFACK Marcellin
Page 5 / 5
Téléchargement