Documente Academic
Documente Profesional
Documente Cultură
INFORMATIC*I*
Un fiier text conine numai caractere ASCII, grupate n linii de lungimi diferite, fiecare linie
terminat cu unul sau dou caractere terminator de linie.
Caracter terminator de linie:
fiierele Unix/Linux: un singur caracter terminator de linie \n
fiierele Windows i MS-DOS: caracterele \r i \n (CR,LF) ca terminator de
linie
Un fiier text poate fi terminat printr-un caracter terminator de fiier (Ctrl-Z = EOF )
Valoarea efectiv este dependent de sistem, dar n general este -1.
Acest terminator nu este ns obligatoriu. Sfritul unui fiier disc poate fi detectat i pe baza
lungimii fiierului (numr de octei), memorat pe disc.
Funciile de citire sau de scriere cu format din/n fiiere text realizeaz conversia automat din
format extern (ir de caractere) n format intern (binar virgul fix sau virgul mobil) la citire i
conversia din format intern n format extern, la scriere pentru numere ntregi sau reale.
Fiierele binare pot conine:
numere n reprezentare intern (binar)
articole (structuri de date)
fiiere cu imagini grafice, n diverse formate, etc
Citirea i scrierea se fac fr conversie de format.
Pentru fiecare tip de fiier binar este necesar un program care s cunoasc i s interpreteze corect
datele din fiier (structura articolelor). Este posibil ca un fiier binar s conin numai caractere, dar
funciile de citire i de scriere pentru aceste fiiere nu cunosc noiunea de linie; ele specific
numrul de octei care se citesc sau se scriu.
Consola i imprimanta sunt considerate fiiere text.
Fiierele disc trebuie deschise i nchise, dar fiierele consol i imprimanta nu trebuie
deschise i nchise.
IB.11.3. Operarea cu fiiere
Pentru operarea cu un fiier (text sau binar) se definete o variabil de tip FILE * pentru accesarea
fiierului:
FILE * - tip structur definit n stdio.h
Conine informaii referitoare la fiier i la tamponul de transfer de date ntre memoria central i
fiier:
adresa
lungimea tamponului
modul de utilizare a fiierului
indicator de sfrit de fiier
indicator de poziie n fiier
-2-
INFORMATIC*I*
INFORMATIC*I*
La deschiderea unui fiier se iniializeaz variabila pointer asociat, iar celelalte funcii se refer la
fiier numai prin intermediul variabilei pointer.
Funcia fopen are rezultat NULL (0) dac fiierul specificat nu este gsit dup cutare n directorul
curent sau pe calea specificat.
Exemplu:
//exemplu 1
char *numef = "C:\\WORK\\T.TXT"; // sau c:/work/t.txt
FILE * f;
// pentru referire la fiier
if ( (f=fopen(numef,"r")) == NULL) {
printf("Eroare la deschidere fiier %s \n", numef);
return;
}
//exemplu 2
#include <stdio.h>
int main ( ) {
FILE * f; // pentru referire la fiier
// deschide un fiier binar ptr citire
f = fopen ( c:\\t.txt", "rb );
printf ( f == NULL ? "Fiier negasit" : " Fiier gasit");
...
if (f)
// dac fiier existent
fclose(f); // nchide fiier
return 0;
}
Diferena dintre b i t este aceea c la citirea dintr-un fiier binar toi octeii sunt considerai ca date
i sunt transferai n memorie, iar la citirea dintr-un fiier text anumii octei sunt interpretai ca
terminator de linie (\0x0a) sau ca terminator de fiier (\0x1a). Nu este obligatoriu ca orice fiier text
s se termine cu un caracter special cu semnificaia sfrit de fiier (CTRL-Z , de exemplu) .
Pentru fiierele text sunt folosite modurile:
w pentru crearea unui nou fiier
r pentru citirea dintr-un fiier
a pentru adugare la sfritul unui fiier existent
Modul w+ poate fi folosit pentru citire dup creare fiier.
Deschiderea n modul w terge orice fiier existent cu acelai nume, fr avertizare, dar
programatorul poate verifica existena unui fiier n acelai director nainte de a crea unul nou.
Pentru fiierele binare se practic actualizarea pe loc a fiierelor, fr inserarea de date ntre cele
existente, deci modurile r+, a+, w+. (literele r i w nu pot fi folosite simultan).
-4-
INFORMATIC*I*
Fiierele standard de intrare-ieire (tastatura i ecranul consolei) au asociate variabile de tip pointer
cu nume predefinit (stdin i stdout); care pot fi folosite n funciile destinate tuturor fisierelor, cum
ar fi fflush.
Pentru nchiderea unui fiier disc se folosete funcia fclose:
int fclose(FILE *fp);
nchide fiierul i elibereaz zona tampon
n caz de succes ntoarce 0, altfel, ntoarce EOF.
nchiderea este absolut necesar pentru fiierele n care s-a scris ceva, dar poate lipsi dac s-au fcut
doar citiri din fiier.
IB.11.4. Operaii uzuale cu fiiere text
Accesul la fiiere text se poate face
fie la nivel de linie
fie la nivel de caracter
dar numai secvenial.
Deci nu se pot citi/scrie linii sau caractere dect n ordinea memorrii lor n fiier i nu pe srite
(aleator)!
Nu se pot face modificri ntr-un fiier text fr a crea un alt fiier, deoarece nu sunt de conceput
deplasri de text n fiier!
Pentru citire/scriere din/n fiierele standard stdin/stdout se folosesc funcii cu nume puin diferit i
cu mai puine argumente, dar se pot folosi i funciile generale destinate fiierelor disc. Urmeaz
cteva perechi de funcii:
Sintaxa
Descriere
Citete un caracter din f i l ntoarce ca un
int fgetc (FILE * f);
unsigned char convertit la int,
// sau getc (FILE*)
Returneaz EOF dac s-a ntlnit sfritul de
fiier sau n caz de eroare.
char * fgets( char * line, int max, FILE Citete maxim n-1 caractere sau pn la \n
inclusiv, i le depune n s, adaug la sfrit \0 dar
*f);
nu elimin terminatorul de linie \n. Returneaz
adresa irului.
La eroare ntoarce valoarea NULL.
Detectarea sfritului de fiier se poate face i cu ajutorul funciei feof (Find End of File):
int feof ( FILE *fp);
-5-
INFORMATIC*I*
Exemplu:
// citire i afiare linii dintr-un fiier
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE *fp;
char s[80];
if ( (fp=fopen("c:\\test.c","r")) == NULL ) {
printf ( "Nu se poate deschide la citire fiierul!\n );
exit (1);
}
while ( fgets(s,80,fp) != NULL )
printf ( "%s", s);
fclose (fp);
return 0;
}
/*
Scriere sub form de litere mici caracterele dintr-un fiier n alt fiier
numele sursei i destinaiei transmise n linia de comand.
Lansarea n execuie a programului:
copiere fiier_sursa.dat fiier_dest.dat
*/
#include<stdio.h>
#include<ctype.h>
int main(int argc, char** argv){
FILE * f1, * f2; int ch;
f1= fopen (argv[1], "r");
f2= fopen (argv[2], "w");
if ( f1==0 || f2==0) {
puts (" Eroare la deschidere fiiere \n");
-6-
INFORMATIC*I*
return 1;
}
while ( (ch=fgetc(f1)) != EOF)
fputc ( tolower(ch),f2);
fclose(f1);
fclose(f2);
return 0;
// citeste din f1
// scrie n f2
n principiu se poate citi integral un fiier text n memorie, dar n practic se citete o singur linie
sau un numr de linii succesive, ntr-un ciclu repetat pn se termin fiierul (pentru a se putea
prelucra fiiere orict de mari).
Pentru actualizarea unui fiier text prin modificarea lungimii unor linii, tergerea sau inseria de
linii se va scrie un alt fiier i nu se vor opera modificrile direct pe fiierul existent.
IB.11.5. Intrri/ieiri cu conversie de format
Datele numerice pot fi scrise n fiiere disc fie n format intern (mai compact), fie transformate n
iruri de caractere (cifre zecimale, semn .a).
Un fiier text ocup mai mult spaiu deoarece formatul ir de caractere necesit i caractere
separator ntre numere. Avantajul este c un fiier text poate fi citit cu programe scrise n orice
limbaj sau cu orice editor de texte sau cu alt program utilitar de vizualizare fiiere!
Funciile de citire-scriere cu conversie de format i editare sunt:
int fscanf (FILE * f, char * fmt, ...)
realizeaz citirea cu format dintr-un fiier; analog scanf
int fprintf (FILE * f, char * fmt, ...)
identic cu printf cu deosebirea c scrie ntr-un fiier
// f = pointer la fiier
// deschide fiier
// scrie un numar
// inchidere fiier
-7-
INFORMATIC*I*
while (fscanf(f,"%d", &x) == 1)
printf("%4d", x);
Exemplu:
ntr-un fiier de tip text sunt pstrate valorile reale ale unei msuratori sub forma:
nr_msuratori
val1
val2
val3 ...
S se scrie programul care afieaz numrul de msurtori i valorile respective.
Se vor aduga la fiier noi msuratori pn la introducerea valorii 0.
Rezolvare:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX 100
void afiseaza(double *mas,int nrm){
int i;
for (i=0; i<nrm; i++)
printf ("Masuratoarea %d = %6.2e\n", i+1, mas[i]);
}
void loadmas (FILE *fp, int *nrm, double *mas){
int i=0;
fscanf (fp,"%d", nrm);
if (*nrm>MAX) *nrm = MAX;
for ( ; i<*nrm; i++)
fscanf (fp, "%lf", &mas[i]);
}
int main(){
FILE *fp;
double masur[MAX], mas_noua=1;
char nume_fis[12];
int nr_mas;
printf ("nume fisier:");
gets (nume_fis);
if ( (fp = fopen(nume_fis, "r+") ) == 0 ){
printf ("nu exista fisierul\n");
exit (1);
}
loadmas (fp,&nr_mas,masur);
afiseaza (masur,nr_mas);
fclose(fp);
if ( (fp = fopen(nume_fis, a") ) == 0 ){
printf ("nu exista fisierul\n");
exit (1);
-8-
INFORMATIC*I*
}
printf ("\nmasuratori noi:\n);
while( nr_mas++<MAX-1){
scanf(%lf,&mas_noua);
if(mas_noua) fprintf (fp, "%lf\n", mas_noua);
else break;
}
fclose(fp);
if ( (fp = fopen(nume_fis, "r+") ) == 0 ){
printf ("nu exista fisierul\n");
exit (1);
}
fprintf (fp, "%d", --nr_mas);
fclose (fp);
return 0;
}
Exemple:
int a[10];
fread (a, sizeof(int), 10, fp);
fwrite(a, sizeof(int),10,fp);
De remarcat c primul argument al funciilor fread i fwrite este o adres de memorie (un pointer):
adresa unde se citesc date din fiier sau de unde se iau datele scrise n fiier.
Al doilea argument este numrul de octei pentru un articol, iar al treilea argument este numrul de
articole citite sau scrise. Numrul de octei citii sau scrii este egal cu produsul dintre lungimea
unui articol i numrul de articole.
-9-
INFORMATIC*I*
Rezultatul funciilor este numrul de articole efectiv citite sau scrise i este diferit de argumentul 3
numai la sfrit de fiier (la citire) sau n caz de eroare de citire/scriere!
Dac tim lungimea unui fiier i dac este loc n memoria RAM atunci putem citi un ntreg fiier
printr-un singur apel al funciei fread sau putem scrie integral un fiier cu un singur apel al funciei
fwrite. Citirea mai multor date dintr-un fiier disc poate conduce la un timp mai bun fa de
repetarea unor citiri urmate de prelucrri, deoarece se pot elimina timpii de ateptare pentru
poziionarea capetelor de citire scriere pe sectorul ce trebuie citit (rotaie disc plus comand
capete).
Programul urmtor scrie mai multe numere ntregi ntr-un fiier disc (unul cte unul) i apoi citete
coninutul fiierului i afieaz pe ecran numerele citite.
int main () {
FILE * f; int x; char * numef =num.bin;
// creare fiier
f=fopen(numef,"wb"));
// fisier in directorul curent
for (x=1; x<=100; x++)
fwrite (&x,sizeof(float),1,f);
fclose(f);
// citire fiier pentru verificare
if ( (f=fopen(numef,"rb")) == NULL ) { // fisier in directorul curent
printf ( "Nu se poate deschide la citire fiierul!\n );
exit (1);
}
printf("\n");
while (fread (&x,sizeof(float),1,f)==1)
printf ("%4d ",x);
fclose(f);
return 0;
}
Lungimea fiierului num.bin este de 200 de octei, cte 2 octei pentru fiecare numr ntreg, n timp
ce lungimea fiierului num.txt creat anterior cu funcia fprintf este de 400 de octei (cte 4 caractere
ptr fiecare numr). Pentru alte tipuri de numere diferena poate fi mult mai mare.
De obicei articolele unui fiier au o anumit structur, n sensul c fiecare articol conine mai multe
cmpuri de lungimi i tipuri diferite. Pentru citirea sau scrierea unor astfel de articole n program
trebuie s existe (cel puin) o variabil structur care s reflecte structura articolelor.
Exemplu de definire a structurii articolelor unui fiier simplu cu date despre elevi i a funciilor ce
scriu sau citesc articole ce corespund unor variabile structur:
typedef struct {
char nume[25];
float medie;
} Elev;
// creare fiier cu nume dat
void creare(char * numef) {
FILE * f; Elev s;
f=fopen(numef,"wb");
printf ("Nume i medie ptr. fiecare student: \n");
while (scanf ("%s %f ", s.nume, &s.medie) != EOF)
fwrite(&s,sizeof(s),1,f);
fclose (f);
}
- 10 -
INFORMATIC*I*
INFORMATIC*I*
Memorarea poziiei curente sau poziionarea se pot realiza utiliznd urmtoarele funcii:
int fgetpos (FILE *fp, fpos_t *poziie)
memoreaz starea curent a indicatorului de poziie al fluxului referit de fp n poziie;
ntoarce 0 dac operaia s-a realizat cu succes!
int fsetpos (FILE *fp, const fpos_t *poziie)
seteaz indicatorul de poziie al fluxului referit de fp la valoarea data de poziie
void rewind (FILE *fp)
seteaz indicatorul de poziie al fluxului referit de fp la nceputul fiierului
- 12 -
INFORMATIC*I*
Exemplu:
Funcie care modific coninutul mai multor articole din fiierul de elevi creat anterior.
// modificare coninut articole, dupa cautarea lor
void modificare (char * numef) {
FILE * f;
Elev e;
char nume[25];
long pos;
int ef;
if ( (f=fopen(numef,"rb+")) == NULL ) {// fisier in directorul curent
printf ( "Nu se poate deschide la citire fiierul!\n );
exit (1);
}
do {
printf ("Nume cautat: ");
scanf ("%s",nume);
if (strcmp(nume, .) == 0)
- 13 -
INFORMATIC*I*
// sau scanf(%s,s);
// pentru corectare
c = getchar();
printf (%d \n,c);
return 0;
}
/* va afia 10 care este codul numeric al caracterului terminator de
linie \n, n loc s
afieze codul caracterului c, deoarece dup o
citire cu scanf n zona tampon rmn unul sau cteva caractere
separator de cmpuri (\n, \t, ), care trebuie scoase de acolo
prin fflush(stdin) sau prin alte apeluri scanf. */
- 14 -
INFORMATIC*I*
Funcia scanf oprete citirea unei valori din zona tampon ce conine o linie la primul caracter
separator de cmpuri sau la un caracter ilegal n cmp (de ex. liter ntr-un cmp numeric)!
In cazul repetrii unei operatii de citire (cu scanf) dup o eroare de introducere n linia
anterioar (caracter ilegal pentru un anumit format de citire) n zona tampon rmn caracterele
din linie care urmau dup cel care a produs eroarea!
do {
printf ("x, y = ");
err = scanf ("%d%d", &x, &y);
if ( err == 2 ) break;
fflush (stdin);
} while (err != 2);
Observaie: Dup citirea unei linii cu funciile gets sau fgets nu rmne nici un caracter n
zona tampon i nu este necesar apelul lui fflush!
Se va folosi periodic fflush n cazul actualizrii unui fiier mare, pentru a evita pierderi de date
la producerea unor incidente (toate datele din zona tampon vor fi scrise efectiv pe disc):
int main () {
FILE * f;
int c;
char numef[]="TEST.DAT";
char x[ ] = "0123456789";
f=fopen (numef,"w");
for (c=0;c<10;c++)
fputc (x[c], f);
fflush (f);
// sau fclose(f);
f=fopen (numef,"r");
while ( (c=fgetc(f)) != EOF)
printf ("%c", c);
return 0;
}
> fiier_2
n acest caz, preluarea informaiilor se face din fiier_1, iar afiarea informaiilor de ieire se face n
fiier_2.
Exemple:
- 15 -
INFORMATIC*I*
/*
* Copierea coninutului unui fiier n alt fiier utilizand redirectarea
* Folosind redirectarea fiierelor standard, se va lansa printr-o linie de
* comand de forma:
*
copiere1 <fiier_sursa.dat >fiier_dest.dat
* i atunci urmtorul program va avea acelai rezultat ca si cnd s-ar citi
* din fisier_sursa.dat
* i s-ar scrie n fiier_dest.dat
*/
#include <stdio.h>
int main(void){
char c;
while ( (c=getchar()) != EOF )
putchar(c);
return 0;
}
/*
* Exemplu de program filter:
* filter este numele unui program (fiier executabil) care aplic un filtru
* oarecare pe un text pentru a produce un alt text
* Folosind redirectarea fiierelor standard, se va lansa printr-o linie de
* comand de forma:
* filter <input - citire din input i scriere pe ecran
* filter >output - citire de la consola i scriere n output
* filter <input >output - citire din input i scriere n output
*/
#include <stdio.h>
// pentru funciile gets,puts
int main () {
char line[256];
while ( gets(line) != NULL)
if ( line[0]==/ && line[1]==/)
puts (line);
return 0;
}
//
//
//
//
Utilizarea comenzii filter fr argumente citete i afieaz la consol; utilizarea unui argument de
forma <input redirecteaz intrrile ctre fiierul input, iar un argument de forma >output
redirecteaz ieirile ctre fiierul output.
Redirectarea se poate aplica numai programelor care lucreaz cu fiiere text.
- 16 -
INFORMATIC*I*
// while ( ! ifile.eof()) {
// poate lipsi
- 17 -