|
|
səhifə | 7/18 | tarix | 12.09.2018 | ölçüsü | 1,36 Mb. | | #81721 |
| #include
main()
{ FILE *fila1;
char buf[180];
fila1=fopen("TEXTC.txt","r");
rewind(fila1);
while ( ! feof(fila1) )
{ fread(buf,180,1,fila1);
printf("%s \n",buf);
}
fclose(fila1);
getch();
return 0;
}
In exemplul de mai sus,fila TEXYC.txt este o fila oarecare in care am
introdus un text exemplificativ si pe care am arhivat-o in acelasi direc-
tor cu aplicatia.Pentru a citi o fila situata in alt director,se va uti-
liza calea completa de acces (gen "C:\\calea de acces\numele filei" ).
Am utilizat stream-ul FILE si un tampon de memorie de tip char.
-41-
Solutia este simpla si eficienta pentru filele de tip text care nu
contin decat date de tip text si nu necesita nici un fel de prelucrare.
In C stream-ul este un tampon de memorie simplu,in care datele vor fi
preluate caracter cu caracter.
Solutia prezinta si o serie de inconveniente.Astfel,daca fila preluata
contine si date de tip numeric sau de tip data calendaristica,functia
printf() nu va putea prelua aceste date.Astfel,o simpla scrisoare datata
poate bulversa "programul de citire".Se pot adauga o serie intreaga de
IF -uri in care sa se trateze toate variantele posibile,dar aplicatia va
contine un numar mare de coduri inutile si va fi destul de laborioasa.
C++ spre deosebire de C utilizeaza stream-uri organizate sub forma
de obiecte.Pe langa tamponul de memorie utilizat pentru preluarea datelor,
streamu-urile din C++ contin si o serie de metode proprii,operatori de
preluare sau postare a datelor etc.Ca rezultat,stream-urile I/O din C++
pot accepta toate tipurile standard de date din C++,fara nici o alta
operatie de conversie si contin constructorul,destructorul si functiile
necesare pentru alocare si dealocarea memoriei.Astfel,pentru operatiile
de intrare/iesire(I/O),C++ contine o biblioteca specializata denumita
"iostrem" in care sunt definite stream-uri specializate pentru fiecare
tip de operatie.Pentru operatiile de preluare a datelor sunt definite
clasele istream,ifstream si istrstream din care se pot deriva sub forma
de obiecte streamu-urile cu care se va lucra in program.
Istream este destinat pentru operatii de intrare secventiale sau aleatorii
si contine constructorul istream(),destructorul ~istream() si metodele:
ipfx(),isfx(),get(),getline(),read(),ignore(),peek(),gcount(),eatwhite(),
putback(),sync(),seekg(),tellg() precum si operatorul >>.
Ifstream este o varianta asemenatoare si este specializat pentru operatii-
le de preluare a filelor de pe unitatea de disc (C:).Contine constructorul
ifstream(),destructorul ~ifstream(),metodele: open(),close(),setbuf(),
setmode(),attach(),rdbuf(),fd() si is_open().
Istrstream este specializat pentru operatii cu date structurate sub forma
de arii de caractere.Pentru a construi un astfel de obiect(stream) trebuie
alocata o arie de date de tip caracter ce va fi utilizata pe post de
tampon pentru preluarea datelor (trebuiesc specificate coordonatele ariei)
Contine constructorul istrstream(),destructorul ~istrstream,metodele:
rdbuf() si str().
Toate cele trei tipuri de stream-uri se utilizeaza pentru acelasi scop,
dar contin un grup diferit de metode proprii prin care pot sa actioneze
specializat asupra datelor din filele preluate.In functie de necesitati,
se va utiliza obiectul care are metodele cele mai adecvate.
In mod similar,pentru operatiile de iesire a datelor exista trei tipuri
de clase specializate: ostream,ofstream si ostrstream,din care se pot de-
riva obiecte specializate:
Ostream este obiectul standardizat pentru operatii succesive sau aleatorii
de iesire a datelor.Are atasat un obiect derivat din clasa streambuf cu
care lucreaza sincron.Obiectul derivat din ostrem realizeaza formatul iar
cel derivat din streambuf realizeaza operatiile de nivel inferior (bit cu
bit).Contine constructorul ostrem(),destructorul ~ostream() si metodele:
opfx(),osfx(),put(),write(),flush(),seekp(),tellp() precum si operatorul
de export a datelor <<.Operatorul "<<" este supraincarcat astfel incat
este similar cu cel utilizat impreuna cu "cout".
-42-
Ofstream este specializat pentru a scrie file pe disc.Contine constructo-
rul ofstream(),destructorul ~ofstream(),metodele: open(),close(),setbuf(),
setmode(),attach(),rdbuf(),fd() si is_open().
Ostrstream scrie datele sub forma de arii de caractere.Pentru a preciza
formatul se va aloca o arie de caractere utilizata ca sablon la scrierea
datelor.Obiectul lucreaza sincron cu un obiect de tip strstreambuf,care
utilizeaza un pointer pentru a avansa pas cu pas dupa scrierea fiecarei
arii.Contine constructorul ostrstream(),destructorul ~ostrstream() si
metodele: pcount(),rdbuf() si str().
Exista si stream-uri specializate atat pentru operatii de intrare cat
si pentru operatii de iesire.Aceste stream-uri acumuleaza toate metodele,
de la ambele tipuri de stream-uri si pot fi utilizate pentru ambele tipuri
de operatii.Sunt cele mai practice si cele mai frecvent utilizate (chiar
daca ocupa putin mai multa memorie).Cele doua tipuri de stream-uri care
executa atat intrari cat si iesiri sunt: fstream si strstream.
Fstream executa orice operatie de intrare iesire.Utilizeaza pe post
de tampon un obiect de tip filebuf. Contine: constructor,destructor si
metodele: open(),close(),setmode(),attach(),fd() si is_open().Este cel
mai prectic si cel mai usor de utilizat.
EXEMPLU: (vezi si cplus33.cpp )
#include
#include
main()
{ fstream fila1("TEXTC.txt",ios::in);
char buf[180];
while ( ! fila1.eof() )
{ fila1.getline(buf,200);
cout << "\n" << buf;
}
fila1.close();
getch();
return 0;
}
Observati ca este la fel de usor de editat ca si exemplul scris in C.In
plus,prezinta o serie de avantaje.Metoda cout si operatrorul << vor
prelua din fila orice tip de date (inclusiv float,double,long,date etc.).
Nu mai este necesara fila header "stdio.h".Obiectul derivat contine si
toate metodele necesare pentru preluarea datelor.Daca nu se vor mai
executa nici un fel de operatii asupra filei,corect este sa apelam si
destructorul ~fila1() pentru a elibera complet memoria de operare.
Pentru declararea obiectului de tip fstream am utilizat numele filei
ce urmeaza sa fie alocata in tamponul de memorie si modul in care urmeaza
sa fie utilizata fila respectiva.Pentru formarea obiectului am apelat
direct constructorul (odata cu declararea obiectului).
Constructorul fstream() are urmatoarea forma generala:
fstream ( const char* szName,int nMode,int nProt=filebuf::openprot); unde
szName -contine calea de acces la fisier si numele filei care urmeaza
sa fie deschisa.Daca fila este in acelasi director,se poate
utiliza doar numele fieli si extensia (ca in exemplu).
nMode -sunt enumeratori ai obiectului ios.Se pot combina prin opera-
torul binar OR.Ios este ancestorul tuturor stream-urilor I/O.
-43-
Parametrul nMode accepta urmatoarele valori:
ios::app -fiecare byte nou scris in fila va fi adaugat la sfarsitul
filei (append) chiar daca pozitia cursorului a fost mo-
dificata cu o alta functie
ios::ate -primul byte nou va fi scris la sfarsitul filei,dar urmatorii
se vor scrie la pozitia curenta.Daca se deplaseaza cursorul
cu ostream::seekp fila poate fi suprascrisa
ios::in -este operatorul pentru input.Suprascrie toate datele
ios::out -este operatorul pentru output.Permite citirea datelor
ios::trunc -sterge toate datele dar pastreaza fila (o trunchiaza)
ios::nocreate -returneaza eroare daca fila precizata nu exista
ios::noreplace -returneaza eroare daca exista fila precizata
ios::binary -deschide fila in modul binar (citeste biti in loc de
caractere ASCII -implicit fila este deschisa in mod text)
nProt -este specificatorul pentru modul de protectie.Accepta valorile:
filebuf::openprot -este valoarea implicita a sistemului de operare
filebuf::sh_none -nu permite partajarea filei (no sharing)
filebuf::sh_read -permite partajarea doar pentru citirea datelor
filebuf::write -permite partajarea filei pentru scriere
-daca nu se specifica se utilizeaza valoarea implicita
Obiectul de tip fstream contine inca doi constructori supraincarcati,care
pot fi utilizati optional,in anumite conditii.Primul astfel de constructor
are formula generala: fstream (filedesc fd);
unde: -fd este un descriptor al filei ce urmeaza sa fie returnat de catre
o functie de genul _open() sau _sopen()
Al doilea constructor optional are formula generala:
fstream(filedesc fd,char*pch,int nLength);
unde: -fd este ca mai sus
-pch este pointerul spre o arie de date de lungimea nLength alocata
anterior (va fi utilizata pe post de tampon,daca are valoarea NULL
stream-ul rezultat va fi netamponat)
-nLength este lungimea in bytes a ariei rezervate pentru tampon
Dupa cum se observa,nu exista o singura solutie ci un numar oarecare
de solutii alternative.La prima vedere pare destul de complicat si confuz,
dar de fapt este foarte simplu.Stream-ul pentru operatiile I/O se utili-
zeaza la fel ca orice alt obiect.Se declara tipul de data,se apeleaza
constructorul,apoi se apeleaza metodele obiectului.Nu mai sunt necesare
alte functii auxiliare sau alte file header si biblioteci.Obictul contine
toate functiile necesare.
Pentru a intelege mecanismul de mostenire a metodelor fiecarui stream,
este utila urmatoarea schema:
|- istream -------| |-fstream
ios- -iostream---|-strstream
|-ostream---------| |-stdiostream
Se observa clasa ios care este ancestorul comun.Din istream deriva toate
stream-urile de intrare a datelor iar din ostream deriva cele de iesire a
datelor.Stream-urile mixte,mostenesc atat clasa istream cat si clasa
ostream,precum si clasa ancestoare ios.Ca rezultat,stream-urile mixte
sunt cele mai complexe si pot utiliza toate metodele ancestorilor.
In exemplul urmator,fstream mediaza toate operatiile I/O:
-44-
EXEMPLU: ( vezi si cplus34.cpp )
#include
#include
main()
{ float numar=345.6789;
fstream scrie1("TEXTS.txt",ios::out);
scrie1 << "Text introdus in fila specificata: ";
scrie1 << "\n";
scrie1 << "\n Primul rand din textul introdus...";
scrie1 << "\n numarul este: " << numar <<" etc. ";
scrie1.close();
fstream fila1("TEXTS.txt",ios::in);
char buf[180];
while ( ! fila1.eof() )
{ fila1.getline(buf,200);
cout << "\n" << buf; }
getch();
return 0;
}
Din exemplul de mai sus se observa ca am utilizat clasa fstream atat
pentru obiectul scrie1,care este stream-ul de output,cat si pentru obiect-
ul file1,care este stram-ul de input.Dupa ce am deschis fila pentru scriere
datele se pot introduce pur si simplu cu operatorul << care va transfera
datele in stream.Este foarte important ca dupa epuizarea trensferului sa
se inchida fila cu functia close().In caz contrar,toate operatiile urma-
toare se vor desfasura tot in interiorul stream-ului de output.Apoi am
derivat un obiect pentru iesirea datelor si am transferat datele preluate
din fila spre ecran.Observati ca fila scrisa contine atat date de tip
text cat si valoarea numarica de tip float (numar).Operatiile cu text si
valori numrice se efectueaza extrem de usor,cu aceleasi functii si cu
ajutorul acelorasi operatori.Pentru unele operatii matematice se utili-
zeaza si o serie de manipulatori.In acest caz,va trebui incarcata in
etapa de precompilare si fila iomanip.h ( cu #include ).
Pentru practica curenta si pentru incepatori,se recomanda clasa fstream
si un numar cat mai limitat de operatii de intrare/iesire,pentru a evita
eventualele erori si/sau exceptii,care pot deranja organizarea datelor
de pe disc.Daca nu a-ti inteles perfect sistemul de apelare a metodelor
si a functiilor,este mai bine sa utilizati doar solutii standardizate si
verificate anterior.Nu toate versiunile de program contin si descrierea
claselor I/O.In rezumat,metodele acestor clase sunt:
ipfx ( int need = 0 ); verifica conditia de eroare inainte de extractie
isfx () ; -este apelata dupa operatia de extractie (input suffix)
get() -are urmatoarele variante supraincarcate:
int get(); &
istream& get (char *pch,int nCount,char delim= '\n');
istream& get (unsigned char* puch,int nCount,char delim='\n');
istream& get (signed char* psch,int nCount,char delim='\n');
istream& get (char& rch);
istream& get (unsigned char& ruch);
istream& get (signed char& rsch);
istream& get (streambuf& rsb,char delim='\n');
-45-
unde: pch,puch,psch sunt pointeri spre arii de caractere
nCount este numarul maxim de caractere
delim este caracterul utilizat ca delimitator (capatul de rand)
rch,ruch,rsch este un pointer spre un caracter (referinta)
rsb este un pointer spre un obiect de tip streambuf
-in toate variantele,get() extrage caractere din stream pana ce intalne-
ste delimitatorul specificat prin delim.
getline() - are urmatoarele variante supraincarcate
istream& getline(char *pch,int nCount,char delim='\n');
istream& getline( unsigned char* puch,int nCount,char delim='\n');
istream& getline( signed char* psch,int nCount,char delim= '\n');
-la fel ca si get() extrage caractere din stream
read() -are urmatoarele variante supraincarcate
istream& read(char* pch,int nCount);
istream& read(unsigned char* puch,int nCount);
istream& read(signed char* psch,int nCount);
-functia read() extrage nCount date din stream
ignore( int nCount = 1,int delim = EOF); extrage si sterge caractere
peek() -returneaza caracterul imediat urmator,fara sa-l extraga din stream
int gcount() const -numara caracterele extrase la ultima operatie
eatwhite() -sterge spatiul gol de la inceputul streamu-ului
putback (char ch) -repune in stream ultimul caracter extras
int sync() -sincronizeaza tamponul intern cu sursa externa de caractere
seekg() -are urmatoarele variante supraincarcate:
istream& seekg( streampos pos);
istream& seekg( streamoff off,ios::seek_dir dir);
unde : pos si off sunt de tip long
dir specifica directia de deplasare si poate fi:
ios::beg -cauta de la inceputul stream-ului
ios::cur -cauta de la pozitia cursorului
ios::end -cauta de la sfarsitul stream=ului
-modifica pozitia pointer-ului pentru functia get()
tellg() -citeste valoarea pointerului get.
Operatorul >> este supraincarcat pentru toate tipurile char,numerice si
respectiv streambuf*,istream& si ios&.
open(const char* szName,int nMode=ios::in,int nProt=filebuf::openprot);
-a fost descrisa impreuna cu constructorul pentru fstream,la exemplul
dela pagina 42.Metoda deschide o fila si ataseaza continutul in tamponul
intern al stream-ului.
close() -inchide stream-ul deschis anterior.
streambuf* setbuf( char* pch,int nLength); -ataseaza aria de memorie
specificata in tamponul intern de memorie al stream-ului
int setmode(int nMode = filebuf::text); seteaza modul text sau modul
binar pentru tamponul stream-ului.Accepta valorile : filebuf::text si
respectiv filebuf::binary.Se poate apela numai dupa ce fila a fost
deschisa
attach(filedesc fd) -ataseaza fila specificata in tamponul streamului
filebuf* rdbuf() const; returneaza un pointer spre tamponul intern
filedesc fd() const -returneaza descriptorul filei
int is_open() const -returneaza nonzero daca streamul este asociat la o
fila identificata prin descriptorul fd.In caz contrar returneaza 0.
-46-
char* str() -returneaza un pointer catre aria de caractere din stream
opfx() - verifica conditiile de eroare inainte de insertia datelor
osfx() - este apelat dupa insertie pentru a elibera tamponul intern
put(char ch) - insera un singur caracter in stream
write() -are supraincarcate urmatoarele variante:
ostream& write(const char* pch,int nCount);
ostream& write(const unsigned char* puch,int nCount);
ostream& write(const signed char* psch,int nCount);
unde : pch,puch,psch sunt pointeri spre arii de caractere
nCount este numarul de caractere ce vor fi scrise
-insera in stream o serie de bytes (nCount bytes)
flush() - elibereaza tamponul intern (sterge toate datele)
seekp( stream pos); sau seekp( stream off,ios::seek_dir dir)
-este la fel ca seekg() (vezi pagina anterioara),adica deplaseaza
pointerul de insertie pentru functia put()
streampos tellp() -citeste valoarea pointerului pentru functia put()
operatorul << este operatorul de insertie si este supraincarcat la fel
ca si cel de extractie pentru tipurile char,numerice...etc.
pcount() - returneaza numarul de bytes arhivati in tamponul intern
CONSTRUCTORII SI DESTRUCTORII
Unele stream-uri au supraincarcati mai multi constructori.Expresiile
generale sunt:
ISTREAM
istream( streambuf* psb) si respectiv destructorul ~istream()
IFSTREAM
ifstream();
ifstream( const char* szName,int nMode = ios::in,
int nProt=filebuf::openprot);
ifstream( filedesc fd);
ifstream( filedesc fd,char* pch,int nLength);
si respectiv destructorul implicit ~ifstream();
ISTRSTREAM
istrstream (char* psz);
istrstream (char* pch,int nLength);
si destructorul ~istrstream();
OSTREAM
ostream (streambuf* psb); si destructorul ~ostream();
OFSTREAM
ofsteam();
ofstream(const char* szName,int nMode=ios::out,
int nProt=filebuf::openprot);
ofstream( filedesc fd);
ofstream( filedesc fd,char* pch,int nLength);
si respectiv destructorul ~ofstream();
OSTRSTREAM
ostrstream();
ostrstream (char* pch,int nLength,int nMode= ios::out);
si destructorul ~ostrstream();
Pentru stream-urile mixte,constructorul este identic cu ifstream sau
ofstream,respectiv cu istrstream/ostrestream (in functie obiectul care
va fi derivat din clasa de baza).
-47-
In cazul in care urmeaza sa utilizati frecvent in programare aceste
clase de obiecte,este bine sa desenati fiecare clasa,impreuna cu membrii
si metodele sale,pe cate o plansa mare,afisata pe perete:
EXEMPLU: class istrstream
{ istrstream( char* pch,int nLength);
~istrstream();
public:
strstreambuf* rdbuf() const;
char* str();
}
Se observa constructorul,destructorul si cele doua metode.In momentul
in care declarati un stream,sau depanati o aplicatie,puteti utiliza
plansa pentru a va orienta rapid asupra metodelor sau asupra tipului de
Dostları ilə paylaş: |
|
|