Explorați Cărți electronice
Categorii
Explorați Cărți audio
Categorii
Explorați Reviste
Categorii
Explorați Documente
Categorii
Modelul fundamental pentru construcia bibliotecii IOSTREAM este cel de stream, vzut ca un flux de date de la o anumit surs la o anumit destinaie. Aceast bibliotec const din mai multe clase, organizate n dou ierarhii paralele.
a)
O ierarhie de clase streambuf, care realizeaz gestionarea bufferelor utilizate de fluxuri, n efectuarea operaiilor de intrare/ieire. Obiecte ale clasei filebuf, care este o clas derivat a clasei streambuf, sunt folosite la prelucrarea fiierelor. Aceste obiecte sunt folosite de clase specifice pentru operaii cu fiiere, care sunt cuprinse n ierarhia care pornete de la clasa de baz ios. O ierarhie de clase ios, care gestioneaz toate operaiile de intrare/ieire, i pune la dispoziie o interfa la nivel nalt pentru programator. Aceast ierarhie folosete motenirea multipl n obinerea clasei derivate iostream, pentru c ea motenete att clasa istream, pentru realizarea operaiilor de intrare, ct i clasa ostream, pentru realizarea operaiilor de ieire. #n aceast ierarhie, sunt definite clasele derivate fstreambase, istream i ostream, avnd clasa de baz ios.
b)
Avnd n vedere faptul, c cele mai uzuale fiiere sunt cele de pe disc, ne vom ocupa de operaii de prelucrare a fiierelor nregistrate pe discuri. Pentru a efectua operaii de intrare/ieire cu fiiere, trebuie inclus n program fiierul antet FSTREAM.H. n acest fiier sunt definite: 1) clasa ifstream, pentru operaii de intrare (citire), care este o clas derivat de la clasele fstreambase i istream; 2) clasa ofstream, pentru operaii de ieire (scriere), care este o clas derivat de la clasele fstreambase i ostream; 3) clasa fstream, pentru operaii de intrare/ieire (citire/scriere), care este o clas derivat de la clasele fstreambase i iostream; n ierarhia de clase ios, se afl definite i clasele: 1) istream_withassign, derivat de la clasa istream; 2) ostream_withassign, derivat de la clasa ostream; 3) iostream_withassign, derivat de la clasa iostream; n construcia acestor clase derivate se adug definiia operatorului de atribuire (=) i sunt utile n redirecionarea operaiilor de intrare/ieire prin atribuirea unui flux, unui alt flux. Prelucrarea unui fiier de pe disc ncepe cu operaia de deschidere a sa. Deschiderea unui fiier se poate realiza: a) folosind funcia membr open ca un obiect al uneia din clasele ifstream, ofstream sau fstream instaniat fr parametri. b) crearea unei instane a clasei ifstream (pentru citire), ofstream (pentru scriere), sau fstream (pentru citire/scriere);
#n situaia a), dup ce s-a creat streamul, el este asociat unui fiier cu ajutorul funciei open( ). void open(const char*id_fiier, int mod, int acces=filebuf::openprot); unde: - id_fiier este numele fiierului care poate include i calea de acces; - mod precizeaz modul de deschidere al fiierului. El poate fi: ios::app // valoare util fiierului ce accept ieiri. Se adaug nregistrri la sfritul fiierului. ios::ate
145
// la deschiderea pentru prima dat a fiierului, poziionare la sfritul su. Operaiile de // intrare/ieire pot avea loc oriunde n interiorul fiierului. ios::binary // deschiderea unui fiier cu scopul de a fi prelucrat n binar (nu se accept modificri de // caractere). #n mod implicit fiierele se deschid n mod text (prelucrare pe caractere). ios::in // deschide fiier pentru citire (fiierul accept intrri). ios::out // deschide fiier pentru scriere (fiierul accept ieiri). ios::nocreate // deschiderea unui fiier existent (nu se deschide fiier n creare). ios::noreplace // nu se poate deschide un fiier existent pentru ieire, cu excepia situaiei n care sunt // operate ios::ate sau ios::app. ios::trunc // dac exist un fiier cu numele specificat este distrus i se creeaz un fiier nou.
Crearea unui stream folosind ifstream implic intrri i nu mai este necesar introducerea valorii ios::in. Crearea unui stream folosind ofstream implic ieiri i nu mai este necesar introducerea valorii ios::out. Majoritatea implementrilor indic tipul parametrului mod ca fiind int. Se pot combina dou sau mai multe valori ale lui mod, folosind operatorul logic OR ( | ).
-
parametrul acces are valoarea implicit filebuf::openprot, care indic acces la un fiier normal. n mod implicit, valoarea acestui parametru de protecie este 0.
Exemple: // deschideri de fiiere 1. ifstream fis; fis.open(f.dat, ios::nocreate); // se deschide fiierul existent f.dat, pentru citire. Opiunea ios::in este implicit. if(!fis) { cerr<<Deschidere eronat ! \n; exit(1); } else {....} 2. ofstream fis; fis.open(fisa.dat); // deschiderea unui fiier normal de ieire. Opiunea ios::out este implicit. if(!fis) { cerr<<Deschidere eronat ! \n; exit(1); } else {....} 3. ofstream fis; fis.open(pers.dat, ios::app | ios::binary); // se deschide fiierul binar pers.dat, pentru adugare de nregistrri la sfrit. if(!fis) {
146
n situaia b) , instanierea obiectelor claselor ifstream, ofstream, fstream, produc apelul constructorilor necesari instanierilor, care apeleaz n mod automat, funcia de deschidere open( ). Aceti constructori au aceiai parametri ca i funcia de deschidere. Se procedeaz astfel: 1) # include <fstream.h> 2) se definesc clasele ifstream/ofstream; 3) se deschide fiierul cu numele id_in_fis / id_out_fis pentru operaii de intrare / ieire; 4) conectez fiierul la instana ifstream inf/ ofstream outf; ifstream inf(id_in_fis); ofstream outf(id_out_fis); 5) se verific corectitudinea operaiei de creare a fluxului, prin suprancrcarea operatorului logic de negare (!) pentru clasele de fluxuri; if(!inf) { cerr<<Eroare n operaia de deschidere a fiierului !\n; exit(1); }
Aadar, se poate deschide un fiier i conecta la un flux, n momentul crerii fluxului. Conectarea unui fiier la o instan ifstream (flux pentru intrare), este echivalent n ANSI C, cu apelul funciei fopen cu modul r. Conectarea unui fiier la o instan ofstream (flux pentru ieire), este echivalent n ANSI C, cu apelul funciei fopen cu modul w. Exemple: // deschideri de fiiere. Se rescriu, n aceast ipotez, exemplele anterioare.
1. ifstream fis (f.dat, ios::nocreate); if(!fis) { cerr<<Deschidere eronat ! \n; exit(1); } else {....} 2. ofstream fis(fisa.dat); if(!fis) { cerr<<Deschidere eronat ! \n; exit(1); } else {....} 3. ofstream fis(pers.dat, ios::app | ios::binary); if(!fis) { cerr<<Deschidere eronat ! \n; exit(1); } else {....}
147
Dup ncheierea procesului de prelucrare a fiierului, care a fost deschis, el trebuie nchis. nchiderea unui fiier se realizeaz cu ajutorul funciei membr close( ). obiect.close( ); sau ptr_obiect->close( ); unde obiect este o instaniere a uneia din clasele ifstream, ofstream sau fstream, iar ptr_obiect este un pointer spre unul din tipurile implementate prin aceste clase. Exemplu: fis.close( ); // funcia close( ) nu are parametri i nu returneaz nici o valoare.
n prelucrarea fiierelor tip text existente pe disc, se pot folosi funciile membre ale claselor istream, ostream i iostream, pentru c ele sunt clase de baz pentru clasele specifice prelucrrii fiierelor pe disc. Ca atare, se pot folosi operatorii de inserare/extragere (<< , >>), pentru operaii de scriere/citire cu format, ntr-un/ dintr-un fiier de pe disc. Se vor nlocui cin i cout cu un stream conectat cu fiierul respectiv. Exemplu: // se creeaz un fiier de eviden a unor persoane, care conine numele i vrsta. # include<iostream.h> # include<fstream.h> main( ){ ofstream fis_o(FISA); if(! fis_o){ cout<<Eroare la deschidere ! \n; return 1; } fis_o<<Popescu<<25<<ani<<endl; fis_o<<Georgescu<<40<<ani<<endl; fis_o<<Marinescu<<56<<ani<<endl; fis_o.close( ); return 0; }
// program prin care se citete i se afieaz coninutul fiierului precedent. # include<iostream.h> # include<fstream.h> main( ){ ifstream fis_i(FISA); if (! fis_i){ cout<<Eroare la deschiderea lui fis_i\n; return 1; } char nume25]; int varsta; fis_i>>nume>>varsta; cout<< nume<<:<<varsta<<\n; fis_i>>nume>>varsta; cout<< nume<<:<<varsta<<\n; fis_i>>nume>>varsta; cout<< nume<<:<<varsta<<\n; fis_i.close( ); return 0; }
n prelucrarea fiierelor de tip binar, exist dou posibiliti de citire/scriere a datelor. a) utilizarea funciilor membre de:
148
- intrare (citire) istream &get(char &ch); (citete un caracter din streamul asociat i memoreaz valoarea n ch, apoi returneaz o referin ctre stream). Funcia get( ) poate fi suprancrcat sub una din formele urmtoare: 1) istream&get(char*bf, int nr, char dl=\n); (citete nr caractere dintr-un tablou bidimensional indicat de bf. n cazul n care se ntlnete caracterul precizat prin dl (delimitator), funcia va ncheia cu null tabloul respectiv. Un astfel de caracter, n mod implicit, este caracterul de linie nou. Dac delimitatorul este ntlnit n streamul de intrare, el nu este extras i rmne n stream pn la urmtoarea operaie de citire.) 2) int get( ); (returneaz urmtorul caracter din stream sau EOF dac se ntlnete sfritul de fiier). Spre deosebire de funcia istream&get(char*bf, int nr, char dl=\n); funcia istream&getline(char*bf, int nr, char dl=\n); n plus, citete i extrage delimitatorul din streamul de intrare. - ieire (scriere) ostream &put(char ch); ( scrie ch n stream i returneaz o referin ctre stream). b) utilizarea funciilor de citire/scriere, n C++, a unor blocuri de date n binar: - intrare (citire) istream&read(unsigned char*bf, int nr); (citete nr octei din streamul asociat i i plaseaz n bufferul indicat de bf. Dac se ajunge la sfritul fiierului dup un numr nr_1<nr de octei (caractere) citii, operaia de citire se ncheie, iar n buffer se vor gsi caracterele citite.). Evidena numeric a octeilor existeni n buffer se poate stabili cu ajutorul funciei membre: int gcount( ); - ieire (scriere) ostream&write(const unsigned char*bf, int nr); (scrie n streamul asociat nr octei pe care i citete din bufferul indicat de bf). Exemplu: //program utilitar de copiere a unui fiier surs ntr-un fiier destinaie #include<fstream.h> #include <iostream.h> #include<string.h> main(int argc, char*argv[]){ fstream infis,outfis; if (argc>1){ // se specifica fisierul de intrare infis.open(argv[1],ios::in|ios::binary); if(!infis) { cerr<<"Eroare la deschiderea fis_intrare"<<argv[1]<<"\n"; return (1); } } if(argc>2){ // se specifica fisierul de iesire outfis.open(argv[2],ios::out); if(!outfis) {
149
cerr<<"Eroare la deschiderea fis_iesire"<<argv[2]<<"\n"; return (1); } } const dimbuf=255; char buf[dimbuf]; while(infis.get(buf,dimbuf,'\n')&&outfis) outfis.write(buf,strlen(buf)); return 0; } Exemplu: //utilizarea funciilor read( ) ]i write( ) # include<iostream.h> # include<fstream.h> # include<string.h> typedef struct { int zi; int luna; int an; }data_c; main( ){ data_c dt; dt.an=1999; dt.luna=12; dt.zi=25; ofstream outfis("termen",ios::out|ios::binary); if(!outfis) { cout<<"Eroare la deschidere.\n"; return (1); } outfis.write((unsigned char*)&dt, sizeof(data_c)); outfis.close(); ifstream infis("termen",ios::in|ios::binary); if(!infis) { cerr<<"Eroare la deschderea fis infis\n"; return (1); } infis.read((unsigned char*)&dt, sizeof(data_c)); cout<<dt.an<<endl; cout<<dt.luna<<endl; cout<<dt.zi<<endl; infis.close( ); return 0; } Alte funcii utile n prelucrarea unui fiier: 1) int eof( ); (returneaz valoarea 0, dac s-a ntlnit sfritul de fiier, sau diferit de zero, n caz contrar). 2) istream&ignore(int nr(=1), int dl=EOF); (citete i elimin, din streamul de intrare, un numr de nr caractere sau pe cele ntlnite pn la delimitatorul dl. Nu extrage delimitatorul din streamul de intrare.) 3) int peek( );
150
(returneaz urmtorul caracter din streamul de intrare sau EOF dac s-a ntlnit sfritul de fiier) 4) istream&putback(char ch); (returneaz, n acelei stream, ultimul caracter citit ch) 5) ostream&flush( ); (solicit scrierea efectiv a datelor pe disc, nainte de umplerea bufferului) Specificarea poziiei relative, ntr-un fiier, n raport cu un anumit punct de referin (acces aleator): a) istream&seekg(streamoff offset, seek_dir orig); b) ostream&seekp(streamoff offset, seek_dir orig); unde streamoff este un tip definit n iostream.h, apt de a reine cea mai mare valoare valid a lui offset, iar seek_dir const ntr-o enumerare cu urmtoarele valori: ios::beg // nceput de fiier ios::cur //poziia curent ios::end// sfrit de fiier Sistemul de intrare/ieire din C++ opereaz cu un pointer get, care precizeaz poziia urmtoarei operaii de intrare n fiier, i un pointer put, care precizeaz poziia urmtoarei operaii de ieire n fiier. Dup fiecare operaie, pointerul respectiv avanseaz, n mod secvenial. Funciile menionate permit un acces nesecvenial la fiierul care urmeaz a fi prelucrat. Funcia seekg( ) deplaseaz pointerul get al fiierului asociat cu un numr de octei dat de valoarea offset n raport cu originea menionat prin orig. Funcia seekp( ) deplaseaz pointerul put al fiierului asociat cu un numr de octei dat de valoarea offset n raport cu originea menionat prin orig. Utilizarea funciilor anterioare sub forma a) istream&seekg(streampos p); c) ostream&seekp(streampos p); permit salvarea poziiei curente a fiierului, efectund alte operaii pe fiier, i revenind la poziia salvat anterior. Tipul definit n iostream.h, streampos, este apt de a reine cea mai mare valoare pe care o poate returna una din cele dou funcii. Starea curent a sistemului de intrare/ieire este reinut ntr-un ntreg n care se afl codificai urmtorii indicatori ( enumerai n clasa ios): a) eofbit // 1 pentru sfrit de fiier i 0 n caz contrar Funcia int eof( ); // returneaz o valoare nenul (adevrat) dac este activat eofbit b) badbit // 1 cnd apare o eroare fatal i 0 n caz contrar Funcia int bad( ); // returneaz o valoare nenul (adevrat) dac este activat badbit c) failbit // 1 cnd apare o eroare de intrare/ieire i 0 n caz contrar Funcia int fail( ): // returneaz o valoare nenul (adevrat) dac este activat failbit d) goodbit // valoarea 0 (fr eroare) Funcia int good( ); // returneaz adevrat dac nu exist erori i 0 n caz contrar.
151
Starea curent a sistemului de intrare/iere se poate stabili prin apelarea funciilor menionate anterior, sau prin funcia: int rdstate( );// returneaz 0 dac nu exist erori.
Aplicaie: S se scrie un program care s citeasc de la intrarea standard date cu urmtorul format: cod_acces den_tren nr_tren viteza nr_vag. S se scrie, prin programul respectiv, datele din directorul curent n fiierul tren.dat. #include<iomanip.h> #include<stdlib.h> #include<fstream.h> typedef struct { char cod_acces; char den_tren[15]; int nr_tren; int viteza; int nr_vag; }tren; union{ tren p[3]; char pt[3*sizeof(tren)]; }tamp; int citinf(tren*ptr) { char tab[255]; int v,nr; for(;;) { cout<<"cod_acces den_tren nr_tren viteza nr_vag"; if((cin>>setw(4)>>ptr->cod_acces)&&(cin>>setw(15)>>ptr->den_tren)&& (cin>>setw(4)>>ptr->nr_tren)&&(cin>>v>>nr)) { ptr->viteza=v; ptr->nr_vag=nr; return 1; } if(cin.eof( )) return 0; //EOF cin.clear( ); // anuleaza eroarea cin.getline(tab,255,'\n'); } } main( ){ // se creeaza fisierul binar "tren.dat" ofstream trafic("tren.dat",ios::binary); int k; if(!trafic){ cout<<"Eroare la deschiderea fisierului in creare\n"; exit(1); } for(; ; ){ for(int j=0;j<3;j++) if((k=citinf(&tamp.p[j]))==0)break; //EOF if(j){ // zona tampon este nevida
152
trafic.write(tamp.pt,j*sizeof(tren)); if(!trafic){ cout<<"Eroare la scriere in fisier"; exit(1); } } if(k==0)break; // EOF } trafic.close( ); } S se scrie un program care s afieze datele din fiierul creat tren.dat, conform cod_acces solicitat. #include<iomanip.h> #include<stdlib.h> #include<fstream.h> typedef struct { char cod_acces; char den_tren[15]; int nr_tren; int viteza; int nr_vag; }tren; union{ tren p[3]; char pt[3*sizeof(tren)]; }tamp; main( ){ // se creeaza fisierul binar "tren.dat" ifstream trafic("tren.dat",ios::binary); int k; if(!trafic){ cout<<"Eroare la deschiderea fisierului in creare\n"; exit(1); } cout<<"\n\n"<<setw(19)<<"INSTANTA"<<"\n\n"; do{ trafic.read(tamp.pt,3*sizeof(tren)); k=trafic.gcount()/sizeof(tren); for(int j=0;j<k;j++) { if((tamp.p[j].cod_acces=='2')|(tamp.p[j].cod_acces=='0')) { cout<<"\n"; cout.setf(ios::right,ios::adjustfield); cout<<setw(1)<<tamp.p[j].cod_acces; cout.setf(ios::left,ios::adjustfield); cout<<' '<<setw(15)<<tamp.p[j].den_tren; cout.setf(ios::left,ios::adjustfield); cout<<setw(4)<<tamp.p[j].nr_tren; cout<<tamp.p[j].viteza; cout<<' '<<setw(3)<<tamp.p[j].nr_vag; }}
153
}while(trafic); if(!trafic.eof( )) cout<<"Citire eronata!\n"; trafic.close( ); } Tematic propus 1. S se realizeze un program de copiere a unui fiier de tip text de pe disc sau pe disc. 2. S se scrie un program prin care s se afieze coninutul unui fiier cunoscut. 3. S se scrie un program care s citeasc iruri de caractere de la intrarea standard i s le transfere ntr-un fiier pe disc. 4. S se realizeze concatenarea a dou fiiere surs ntr-un al treilea fiier destinaie. 5. S se realizeze programe prin care s se pun n eviden modul de utilizare a funciilor de poziionare ntr-un fiier.
154