Sunteți pe pagina 1din 77

PC-A : 1 ELTC –B

Modul 2, partea 4
Cuprins
1. Sistemul de intrări-ieşiri din C++
• Introducere
• Clasa ios
• Operaţii de I/E cu format
• Utilizarea funcţiilor width(), precision() şi fill()
• Verificarea stării sistemului de I/E
• Funcţiile de I/E de tip “manipulator”
• Funcţiile de I/E de tip “manipulator”
• Crearea propriilor funcţii de tip manipulator
• Clasa ostream
• Clasa istream
• Funcţiile de tip inserter şi extractor
• Redefinirea operatorului de ieşire
• Redefinirea operatorului de intrare
• Operaţii de intrare-ieşire pe fişiere
• Operaţii de intrare-ieşire pe şiruri de caractere
2
1. Sistemul de intrări-ieşiri din C++

Introducere

• Limbajul C++ conţine toate funcţiile din biblioteca de I/E a


limbajului C, dar ne pune la dispoziţie şi un sistem propriu
de I/E orientat pe obiecte, care ne permite să citim/scriem
obiecte de diferite tipuri

• Sistemul de I/E din C++ poate fi redefinit în cadrul


propriilor clase
• Sistemul de I/E din C++ este implementat prin aşa numita
bibliotecă iostream

3
• Sistemul de I/E din C++ operează prin conceptul de flux
(stream)
• Un stream (flux) este un dispozitiv logic, care fie
produce, fie consumă informaţie şi este cuplat la un
dispozitiv fizic prin intermediul sistemului de I/E din C++
• Altfel spus, reprezintă totalitatea modalităţilor de
realizare a unor operaţii de citire sau scriere

• Un flux poate fi de intrare, de ieşire sau bidirecţional


• Citirea datelor de la un flux de intrare se numeşte
extracţie şi este realizată prin operatorul de extracţie >>
sau cu o metodă membră a clasei iostream
• Scrierea datelor la un flux de ieşire se numeşte inserţie
şi este realizată prin operatorul de inserţie << sau cu o
metodă membră a clasei iostream

4
• La execuţia unui program în C++ se deschid în mod
automat următoarele fluxuri predefinite (ca urmare nu
trebuie declarate) :
– cin Intrarea standard Tastatura
– cout Ieşirea standard Ecranul
– cerr Eroarea standard Ecranul
– clog Versiunea “tampon” a lui cerr Ecranul

• Unica diferenţă dintre obiectele cerr şi clog constă în


modul în care se execută golirea lor :
– în cazul lui cerr după fiecare inserare, la clog doar la umplerea
bufferului

• La terminarea execuţiei unui program în C++ aceste


fluxuri sunt automat închise

5
• C++ defineşte sistemul său de I/E în mai multe fişiere
antet (atenție la extensie !):
– iostream.h: conţine o ierarhie de clase, pentru operaţii de nivel
scăzut (fluxuri de caractere) sau de nivel înalt (obiecte specifice,
predefinite sau definite de utilizator);
• aici sunt definite clasele ios, istream, ostream, iostream;

– fstream.h: conţine clase derivate din cele definite în iostream.h,


pentru operaţii de I/E pe fişiere;
• aici sunt definite clasele ifstream, ofstream, iofstream;

– sstream.h (strstream.h): conţine clase derivate din cele definite


în iostream.h, pentru operaţii de I/E pe şiruri de caractere;
• aici sunt definite clasele istrstream, ostrstream, iostrstream;

– iomanip.h: conţine definiţia unui set de manipulatori ce operează


pe fluxuri pentru a produce un anumit efect;

6
7
• Operaţiile de I/E se bazează pe un model pe două nivele:
– nivelul superior asigură operaţii de I/E formatate pentru obiecte
specifice (predefinite sau definite de utilizator)
– nivelul inferior se ocupă cu operaţii de I/E neformatate, pentru
fluxuri de octeți:
• acest nivel se bazează pe obiecte de tipul streambuf (flux cu zonă
tampon) şi permite ascunderea detaliilor fizice de operare a DP

• Utilizatorul nu lucrează direct cu aceste obiecte ci indirect


prin intermediul fluxurilor:
– la crearea unui obiect stream, acestuia i se asociază automat un
obiect de tipul streambuf

8
Clasa ios

• Această clasă precizează facilităţi comune operaţiilor de


intrare şi de ieşire
• Pentru aceasta utilizează un obiect de tipul streambuf
pentru transferul datelor, menţine informaţii despre
starea acestuia şi permite specificarea informaţiilor de
formatare pentru obiectele din clasele derivate istream şi
ostream
• Clasa ios este clasă de bază pentru clasele istream,
ostream, fstreambase, strstreambase
• Clasa ios conţine mai multe date membre publice statice,
de tipul enumerare sau măști de biți :
– fmtflags: pentru formatarea operaţiilor de I/E
– io_state: pentru informaţii de stare
– open_mode: conţine modurile de deschidere a fluxurilor
– seek_dir: pentru căutarea relativă în fluxuri 9
Operaţii de I/E cu format

• Sistemul de I/E din C++ ne permite să formatăm datele


într-un mod similar celui folosit de funcţia printf( )
• Fiecare stream din C++ are asociat un număr de
“indicatori de format” (flags/flag-uri), care determină
modul de afişare
• Când se poziţionează un flag de format este activată
caracteristica respectivă, iar când acesta este şters se
utilizează formatul implicit

10
skipws determină citirea/ignorarea caracterele de tip
whitespace (spaţiu, tab, newline) la citire
left determină alinierea rezultatului la stânga
right determină alinierea rezultatului la dreapta (implicit)
internal o valoare numerică se va extinde astfel încât
să se completeze câmpul, prin inserarea de
spaţii între caracterele de bază; pentru valoare
nenumerică este echivalent cu flagul right
dec (implicit) afişare în zecimal
oct trebuie poziţionat când se doreşte afişarea
rezultatului în octal
hex se afişează rezultatul în hexazecimal
boolalpha citește/scrie elementele booleene ca șiruri de
caractere (true și false)

11
showbase determină afişarea ieşirii în baza de numeraţie
corespunzătoare
showpoint determină afişarea tuturor zerourilor şi a
punctului zecimal ale unei valori în format de
virgulă mobilă
showpos determină afişarea semnului înaintea valorilor
zecimale pozitive
scientific generează afişarea numerelor în format de virgulă
mobilă, folosindu-se notaţia ştiinţifică (1.23e+003)
fixed când este poziţionat, valorile în format de virgulă
mobilă sunt afişate folosind notaţia normală
(123.456789)
unitbuf fiecare stream este eliberat după o operaţie de
ieşire, ceea ce determină scrierea în dispozitivul
fizic cuplat la stream

12
uppercase determină afișarea cu majusculă a caracterelor
generate de stream ( de ex. 0X pentru afișarea
unei valori în hexazecimal)

Măști de biți adiționale, pe baza compunerii unor flag-uri


existente:

adjustfield left | right | internal


basefield dec | oct | hex
floatfield scientific | fixed

13
• Pentru a seta un flag de format, se pot utiliza metodele
setf( ), membre ale clasei ios:

fmtflags setf (fmtflags flags);

– metoda activează flagurile specificate de argumentul flags


– toţi ceilalţi indicatori rămân neschimbaţi
– returnează starea anterioară a flagurilor
– prin aplicarea unui operator de tip OR pe bit, putem poziţiona
mai mulţi indicatori de stare

• Exemplu:
cout.setf( ios::showbase | ios::hex);

14
fmtflags setf (fmtflags flags, fmtflags mask);

– metoda activează flagurile setate atât în flags cât și în mask dar


și șterge flagurile ce sunt setate în mask dar nu sunt setate în
flags
– returnează starea anterioară a flagurilor

• Exemplu:
cout.setf(ios::hex, ios::basefield);
cout << 27 << endl;

15
• Metoda unsetf( ), membră a clasei ios, şterge unul sau
mai mulţi indicatori de format:
void unsetf (fmtflags flags);

– şterge indicatorii specificaţi de parametrul flags


– toţi ceilalţi indicatori rămân neschimbaţi

Exemplu:
cout.setf ( ios::hex, ios::basefield );
cout.setf ( ios::showbase );
cout << 200 << '\n';
cout.unsetf ( ios::showbase );
cout << 200 << '\n';

16
• Metoda flags( ), membră a clasei ios înapoiază starea
curentă a fiecărui indicator de format, codificat într-o
variabilă de tip fmtflags
• Prototipuri :
fmtflags flags( );
fmtflags flags( fmtflags f);

– în a doua variantă, metoda flags( ) ne permite să poziţionăm toţi


indicatorii asociaţi unui stream, la valorile specificate de
argument dar și ștergerea indicatorilor ce nu sunt setați în
parametrul f

17
#include <iostream>
using namespace std;

void main( )
{
// afişarea valorilor folosind poziţionările implicite
cout<< 123.33 << " salut! " << 100 <<'\n';
cout<< 10 << ' ' << -10 <<'\n';
cout << 100.0 <<'\n';
// schimbăm formatul
cout.unsetf(ios::dec);
cout.setf ( ios::hex | ios::scientific);
cout << 123.33 << " salut! " << 100 <<'\n';
cout.setf(ios::dec);
cout.setf (ios::showpos);
cout <<10 << ' ' << -10 << '\n';
cout.setf (ios::showpoint);
cout << 100.0 << '\n';
cin.get( ); 18
}
Utilizarea metodelor width( ), precision( ) şi fill( )

• Stabilesc lăţimea câmpului pentru operații de I/E,


precizia şi caracterul de inserat

• Prototipurile metodei width( ) sunt:


int width( ); // returneaza valoarea curenta
int width(int w); // stabileste latimea minima
// returneaza valoarea anterioara

• Dacă o valoare utilizează un spaţiu mai mic decât cel


specificat, câmpul este completat cu caracterul curent
de inserat (implicit “spaţiu”)
• Dacă o valoare depăşeşte dimensiunea minimă a
câmpului, câmpul va fi extins până la dimensiunea
necesară
• Laţimea (dimensiunea) câmpului trebuie stabilită pentru
fiecare operaţie de intrare sau ieşire altfel se foloseşte
valoarea implicită (0) 19
• Precizia se referă la numărul de cifre zecimale folosite
la afişarea numerelor cu parte fracționară:
– poate avea semnificaţii diferite după cum flagurile de format
indică un format implicit (nesetat) sau unul specific (fixed sau
scientific)
– pentru formatul implicit, precizia înseamnă numărul total de
cifre zecimale folosite la afişare (atât partea întreagă cât şi cea
fracţionară)
– pentru formatul specific, precizia înseamnă numărul total de
cifre zecimale folosite la afişare numai pentru partea fracţionară
(după punctul zecimal)
• la afişarea unei valori în virgulă mobilă, se folosesc în mod implicit
6 cifre după punctul zecimal

• Aceasta valoare poate fi modificată cu metoda


precision():
int precision( ); // returneaza valoarea curenta
int precision(int p); // stabileste o noua valoare
// returneaza vechea valoare

• Şi în acest caz, precizia trebuie stabilită pentru fiecare


operaţie de intrare sau ieşire altfel se foloseşte 20
valoarea implicită
• Când un câmp trebuie completat, se foloseşte în mod
implicit caracterul “spaţiu”
• Se poate specifica un caracter alternativ cu ajutorul
metodei fill( ):

char fill( ); // returneaza caracterul folosit pentru completare


char fill(char ch); // stabileste noul caracter pentru completare
// returneaza vechiul caracter folosit pentru
// completare

21
#include <iostream>
using namespace std;

void main(void)
{
cout.width(10); // lătimea minima a campului
cout<<“salut”<<“\n”; // implicit, alinierea se face la dreapta
cout.fill(‘%’); // stabilirea caracterului de completare
cout.width(10);
cout<<”salut”<<“\n”; // alinierea la dreapta
cout.setf(ios::left); // alinierea la stanga
cout.width(10);
cout<<”salut”<<“\n”; // alinierea se face la stanga
cout.width(10);
cout<<123.234567<< “\n”; // se utilizeaza formatul implicit
cout.width(10); // se stabileste latimea
cout.precision(3); // se stabileste precizia (nr. total de cifre)
cout<<123.234567<<“\n”;
cin.get( );
22
}
Verificarea stării sistemului de I/E

• Sistemul de I/E al limbajului C++ conţine informaţii de


stare cu privire la operaţiile de I/E
• Starea curentă a sistemului de I/E este codificată în
următorii indicatori, introduşi în enumerarea io_state

Nume Semnificaţie
goodbit Are valoare 0, dacă nu există erori
Are valoare 1, dacă se semnalează o eroare
eofbit Are valoare 1 când se întâlneşte EOF
Are valoare 0 în caz contrar
failbit Are valoare 1, când s-a produs o eroare nefatală; în caz
contrar are valoare 0
badbit Are valoare 1, în caz de eroare fatală şi 0 în caz contrar
23
• Există două moduri prin care putem obţine informaţii
despre starea sistemului de I/E:
– în primul caz, se poate apela metoda membră iostate
rdstate( );
• returnează starea curentă a indicatorilor de eroare

– în al doilea caz putem utiliza una din metodele


specializate bad(), fail(), eof(), good()
• bool bad( ) returnează true dacă bitul badbit este activat
• bool fail( ) returnează true dacă bitul failbit și/sau bitul
badbit este activat
• bool eof( ) returnează true dacă s-a atins sfârşitul de fişier
• bool good( ) returnează true dacă nu se produce nicio
eroare (niciunul din indicatorii eofbit, failbit sau badbit nu
este setat)

24
void clear (iostate state = goodbit);
– permite stabilirea unor noi valori pentru indicatorii de eroare
– pentru valoarea implicită, se șterg toți indicatorii de eroare
Functii
Val.
indica
iostate good() eof() fail() bad() rdstate()

goodbit Fara erori true false false false goodbit

S-a atins
eofbit false true false false eofbit
EOF

failbit Eroare logica false false true false failbit

Eroare de
badbit false false true true badbit
citire/scriere 25
while (!IN.eof( ))
{
IN.get (car) ;
// verifică eroarea
if ((! IN.good()) && (! IN.eof( ) ))
{
cout << ”Eroare de I/E …..se termina programul\n” ;
return 1;
}
}

26
Funcţiile de I/E de tip “manipulator”

• Manipulatorii permit formatarea operaţiilor de I/E


• Un manipulator este un identificator ce poate fi inserat
într-un flux de ieşire sau poate fi extras dintr-un flux de
intrare pentru a obţine un anumit efect (de exemplu
inserarea unei linii noi, etc.)
• Pentru a avea acces la manipulatorii care au parametri
trebuie să includem în programul nostru fişierul antet
iomanip.h
• Majoritatea manipulatorilor (cu excepția setw()) sunt
persistenți, adică efectele lor rămân valabile până la o
nouă modificare

27
• Manipulatorii pot să apară în lanţul de operaţii de I/E şi
afectează doar fluxul (stream) asociat, nu şi alte fluxuri
deschise în mod curent
• Principalul avantaj al manipulatorilor constă în faptul că
sunt mai uşor de utilizat şi permit scrierea mai
compactă a codului
• Mulţi manipulatori se aseamănă cu metodele membre
ale clasei ios

28
Manipulator Scop Intrare/ Ieşire

dec Formatează datele numerice în zecimal Ieşire


endl Afişează un caracter de tip “newline” şi eliberează Ieşire
stream-ul
ends Afişează un caracter null Ieşire
flush Eliberează un flux (stream) Ieşire
hex Formatează datele numerice în hexazecimal Ieşire

oct Formatează datele numerice în octal Ieşire


resetiosflags (long f) Dezactivează indicatorii specificaţi în variabila f Intrare şi ieşire

setbase (int base) Stabileşte baza de numeraţie la “base” Ieşire

setfill (int ch) Stabileşte caracterul de completat dat de parametrul ch Ieşire

setioflags (long f) Activează indicatorii specificaţi în variabila f Intrare şi ieşire

setprecision (int p) Stabileşte precizia pentru numere reale Ieşire

ws Ignoră caracterele de tip “whitespace” Ieşire


setw (int w) Stabileşte lăţimea câmpului (valoarea minimaș valoarea Ieşire
implicita este 0) la valoarea parametrului w 29
Afecteaza numai urmatoarea operatie de iesire
Exemplu:
# include <iostream>
#include <iomanip>

using namespace std;

void main(void)
{
cout << hex << 100 << endl;
cout << oct << 100 << endl;
cout << setfill( ‘X’) << setw (10);
cout << 10 << endl << endl;
cin.get( );
}

30
Crearea propriilor funcţii de tip manipulator

• Manipulatorii sunt importanţi din două puncte de vedere:


– un manipulator poate grupa o secvenţă de mai multe operaţii de I/E
într-una singură
– un manipulator ajustat poate fi util când trebuie să realizăm operaţii
de I/E pe dispozitive care nu sunt standard

• Manipulatorii sunt de două tipuri:


– cei care operează cu fluxuri (stream-uri) de intrare
– cei care sunt asociaţi fluxurilor (stream-urilor) de ieşire

31
• Forma generală a manipulatorilor de ieşire, fără
parametri, este:
ostream& nume-manipulator (ostream& stream)
{
// cod
return stream;
}

• Deşi manipulatorul are ca şi parametru o referinţă a


stream-ului cu care operează, nu se utilizează nici un
argument când acesta este inserat într-o operaţie de
ieşire

32
• Sintaxa funcţiilor manipulator de intrare, fără parametri,
este dată mai jos:
istream& nume manipulator (istream& stream)
{
// cod
return stream;
}

• Este foarte important ca funcţiile proprii de tip


manipulator să returneze o referință la un stream:
– dacă nu se respectă această condiţie, ele nu pot fi utilizate în
operaţii de intrare şi ieşire înlănţuite

33
Exemplu:
# include <iostream>
#include <iomanip>

using namespace std;

ostream& init(ostream& stream)


{
stream.width(10);
stream.precision(4);
stream.fill(‘*’);
return stream;
}

void main(void)
{
cout<< init << 123.123456 << endl << endl;
cin.get( );
}
34
Clasa ostream

• Această clasă asigură ieşiri formatate către un obiect


de tipul streambuf
• O instanţă a acestei clase nu realizează direct ieşirea
ci prin intermediul unor metode se apelează metode
membre ale claselor de bază ce realizează efectiv
transferul datelor
• Clasa ostream furnizează codul generic pentru
formatarea datelor înainte de a fi inserate în fluxul de
ieşire prin supraîncărcarea operatorului de inserţie

35
• Metode membre:
– ostream& put (char);
– ostream& write (const char *s, int n);
– ostream& flush ( ); // goleste zona tampon asociata
– long tellp ( ); // returneaza pozitia curenta in flux
– ostream& seekp (long, seek_dir = ios::beg);
– enum seek_dir {beg, cur, end};

36
• Supraîncărcări ale operatorului de inserție:
– ostream& operator<< (bool val);
– ostream& operator<< (short val);
– ostream& operator<< (unsigned short val);
– ostream& operator<< (int val);
– ostream& operator<< (unsigned int val);
– ostream& operator<< (long val);
– ostream& operator<< (unsigned long val);
– ostream& operator<< (float val);
– ostream& operator<< (double val);
– ostream& operator<< (long double val);
– ostream& operator<< (void* val);

37
Clasa istream

• Această clasă permite realizarea intrărilor formatate prin


intermediul clasei de bază ios
• Clasa istream furnizează codul generic pentru formatarea
datelor după extragerea din fluxul de intrare prin
supraîncărcarea operatorului de extracţie

38
• Metode membre :
– int get ( );
• extrage următorul caracter (inclusiv EOF)
– istream& get (char &c );
• extrage următorul caracter și îl depune la adresa dată
– istream& get (char *s, streamsize n, char delim = '\n');
• extrage și depune la adresa dată cel mult (n-1) caractere, până la
întâlnirea caracterului delimitator (implicit ‘\n’);
• caracterul delimitator nu este extras;
• dacă n>0, se adaugă automat caracterul null (‘\n’) la sfârșitul lui
s (chiar dacă nu se extrag caractere din flux)
– int peek ( );
• returnează următorul caracter din flux fără a-l extrage
• caracterul respectiv rămâne în flux pentru următoarea operație de
extracție

39
– istream& putback (char);
• pune înapoi în flux un caracter extras anterior
– istream& read (char *s, int n);
• extrage până la n caractere dar se oprește la întâlnirea EOF
• nu se adaugă caracterul null (‘\n’) la sfârșitul lui s
– istream& getline (char *s, int n, char = '\n’);
• extrage și depune la adresa dată cel mult n-1 caractere;
• extragerea se oprește la întâlnirea caracterului specificat sau la
întâlnirea EOF; caracterul delimitator este extras dar este neglijat
(nu este depus în s);
• se pune automat delimitatorul de șir (‘\0’) la coada lui s;
– int gcount ( );
• returnează numărul de caractere extrase la ultima operație de
intrare (cu metodele get, getline, ignore, read)

40
– istream& ignore (int n = 1, int delimi = EOF);
• extrage și ignoră caractere până când au fost extrase n caractere
sau a fost întâlnit caracterul delimitator specificat; extragerea se
oprește la întalnirea EOF (cu setarea bitului eofbit);
– long tellg ( );
• returnează poziția curentă în fluxul de intrare
– istream& seekg (long, seek_dir = ios::cur);
• mută poziția curentă în fluxul de intrare, în raport cu poziția de
început, de sfârșit sau în raport cu poziția curentă

41
Supraîncărcări ale operatorului de extracție:
– istream& operator>> (bool& val);
– istream& operator>> (short& val);
– istream& operator>> (unsigned short& val);
– istream& operator>> (int& val);
– istream& operator>> (unsigned int& val);
– istream& operator>> (long& val);
– istream& operator>> (unsigned long& val);
– istream& operator>> (float& val);
– istream& operator>> (double& val);
– istream& operator>> (long double& val);
– istream& operator>> (void*& val);

42
Funcţiile de tip “inserter” şi “extractor”

• Sistemul de I/E din C++ permite redefinirea operatorilor de


I/E
• Operaţia de ieşire se numeşte inserţie (insertion), iar
operatorul (<<) este denumit operator de inserţie (insertion
operator):
– această denumire provine de la faptul că un operator de ieşire
inserează informaţia în flux(stream)

• Operaţia de intrare se numeşte extracţie (extraction), iar


operatorul (>>) este denumit operator de extracţie
(extraction operator):
– această denumire provine de la faptul că un operator de intrare
extrage informaţia din flux(stream)

43
Redefinirea operatorului de ieşire

• Forma generală a funcţiilor inserter:


ostream& operator << (ostream& STREAM, Tip Ob sau Tip &Ob)
{
// corp inserter
return STREAM;
}

• Primul parametru este o referinţă a unui obiect de tip


ostream pentru a putea face operaţii de inserţie
înlănţuite
• Al doilea parametru primeşte obiectul care trebuie afişat
• Inserter-ul înapoiază o referinţă de tip ostream:
– acest lucru este cerut în utilizarea inserter-ului în expresii
complexe:
cout << OB1 << OB2 << OB3 ;
• Un inserter nu poate fi o metodă membră a clasei în
care operează (deoarece primul parametru este o
referinţă), dar poate fi o funcţie friend 44
Redefinirea operatorului de intrare
• Forma generală a funcţiilor extractor:
istream& operator>> (istream& STREAM, Tip &Ob)
{
// corp extractor
return STREAM;
}

• Extractorii înapoiază o referinţă a unui istream, care


este un stream de intrare
• Primul parametru trebuie să fie o referinţă a unui stream
de intrare
• Al doilea parametru este o referinţă a obiectului care
primeşte datele de intrare deoarece modifică obiectul
primit ca parametru
• Un extractor nu poate fi metodă membră a unei clase, ci
numai funcţie friend

45
Exemplu:
# include <iostream>
#include <iomanip>

using namespace std;

class COORD {
int x, y;
public:
COORD( ) {
x=0; y=0;
}
COORD(int i, int j) {
x=i; y=j;
}
friend ostream &operator<< (ostream& , COORD OB);
friend istream &operator>> (istream& , COORD &OB);
};
46
// inserter pentru clasa COORD
ostream& operator<<(ostream& STREAM, COORD OB)
{
STREAM << "abscisa: " << OB.x << ", ordonata: " << OB.y << '\n';
return STREAM;
}

// extractor pentru clasa COORD


istream& operator>>(istream& STREAM, COORD& OB)
{
cout<< endl << "\tIntroduceti coordonatele: "<< endl;
cout<< "\t abscisa : ";
STREAM >> OB.x;
cout<< "\t ordonata : ";
STREAM >> OB.y;
return STREAM;
}

47
// functia main
void main (void)
{
COORD A(1,1), B(10,24);
cout << "Obiecte cu coordonate predefinite: " <<endl;
cout<< "\tObiect1: “ <<A << "\tObiect2: “ <<B;
cout<< "\nCoordonate noi: ";
cin >> A;
cout << "Afisare coordonate noi:"<<endl<<'\t';
cout << A;
cin.get( );
}

48
• In C++ toate stream-urile sunt identice, de aceea un
operator redefinit de tip inserter (de exemplu), poate fi
folosit pentru a trimite rezultatele pe ecran sau într-un
fişier
• Supraîncărcarea operatorilor de I/E oferă simplitate şi
elimină necesitatea memorării denumirilor unor funcţii
de I/E supraîncărcate pentru fiecare tip de date

49
Operaţii de I/E cu fişiere
• Pentru a realiza operaţii de I/E cu fişiere, trebuie să
includem în program fişierul antet fstream.h, care
defineşte mai multe clase:
– ifstream, ofstream şi fstream

• Aceste clase sunt derivate din clasele istream şi ostream

50
• In C++, un fişier este deschis prin cuplarea lui la un flux
(stream)
• Inainte de deschiderea fişierului trebuie să declarăm
mai întâi un flux (stream)
• Pentru a crea un flux (stream) de intrare, el trebuie
declarat ca fiind de tip ifstream, iar pentru a crea unul
de ieşire, streamul trebuie declarat de tip ofstream
• Fluxurile care realizează ambele tipuri de operaţii
trebuie declarate de tip iofstream
• Exemple:
ifstream in;
ofstream out;
iofstream io;

51
Deschiderea/închiderea unui fişier

• Metoda open( ) este folosită pentru a cupla un fişier


unui stream
• Această metodă este membră a tuturor celor trei clase
(ifstream, ofstream, fstream) şi are prototipul:

void open(const char *nume_fişier, ios::openmode mod);

– primul parametru reprezintă un pointer la numele fişierului


– parametrul mod este o valoare care specifică modul de
deschidere a fişierului

52
• Lista valorilor posibile pentru al doilea parametru este
definită în clasa “ios” astfel:
in (input) fişier de intrare
out (iutput) fişier de ieşire
ate (at end) după deschidere, poziţia curentă va fi
chiar sfârşitul fişierului
app (append) deschis pentru adăugare (scriere la
sfârşit de fişier)
trunc (trucate) dacă fişierul există îi şterge conţinutul
(opţiune implicită în caz că e vorba de un fişier de
ieşire şi nu apare una dintre opţiunile “ios::app”
sau “ios::ate”)
binary deschidere în mod binar

53
• Sunt permise înlănţuiri ale specificatorilor modului de
deschidere prin “SAU LOGIC” la nivel de bit
• Majoritatea modurilor de deschidere corespund modului
text de lucru cu fișierele; modul binar trebuie precizat
explicit
• Parametrul mod are valori implicite:
– pentru un obiect de tip ifstream : ios::in
– pentru un obiect de tip ofstream : ios::out
– pentru un obiect de tip fstream : ios::in | ios::out
• Metoda open() poate fi apelată explicit (după declararea
obiectului flux) sau implicit (în momentul declarării):
ifstream in;
in.open(“Text.txt”);
sau
ifstream f1(“Text.txt”);
54
• Dacă operaţia de deschidere a fişierului eşuează fluxul
va avea valoarea zero
• Inainte de utilizarea unui fişier trebuie să verificăm dacă
operaţia de deschidere a reuşit, folosind o secvenţă de
genul:
if (!stream_propriu)
{
cout<< “Nu se poate deschide fişierul…\n”;
// trateaza eroarea
}

55
– Cuplarea unui flux la un fisier (sau deschiderea unui
fisier) poate fi verificată și cu metoda:
bool is_open();

ifstream f1(“Test.txt”);
if (! f1.is_open())
{
cout<< “Nu se poate deschide fişierul…\n”;
// trateaza eroarea
}

56
• Pentru a închide un fişier cuplat la un stream se
foloseşte metoda:
stream_propriu.close( );

• După ce am deschis un fişier, este foarte uşor să


citim/scriem date din/în acesta
• Se pot utiliza operatorii (<<) şi (>>) într-un mod similar
cu cel utilizat la operaţiile de I/E cu consola, cu excepţia
faptului că în loc de cin şi cout se foloseşte fluxul cuplat
la fişier

57
Fișiere text vs Fișiere binare
• Un fișier text conține caractere ce pot fi vizualizate și
interpretate, fiecare caracter având asociat un cod
reprezentat (uzual) pe 1 octet. Un fișier binar conține
octeți cu conținut binar (biți cu valori 0 și 1), mai mulți
octeți pot corespunde unei valori într-un anumit format
• Pentru fișiere binare, caracterul newline sau LF (\n) este
convertit automat în secvența de două caractere CR-LF.
Pentru fișiere binare acest lucru nu este valabil
• Intr-un fișier text, sfărșitul de fișier este marcat de fiecare
dată cu un caracter special având codul ASCII 26. Un
astfel de caracter nu este prezent într-un fișier binar

58
#include <iostream>
#include <fstream>
using namespace std;

void main(void)
{
ofstream FOUT (“test”); // creaza un fisier de iesire
if (!FOUT) {
cout<<”Nu se poate deschide fisierul de iesire\n”;
exit(0);
}
FOUT<< ”Salut!\n”;
FOUT<< 100 << ’ ‘ << hex << 100 << endl;
FOUT.close( );

59
ifstream FIN(“test”); // deschide un fisier de intrare
if (!FIN) {
cout<<”Nu se poate deschide fisierul de intrare\n”;
exit(0);
}
char sir[80];
int i;
FIN>>sir>>i;
cout << sir << ’ ‘ << i << endl;
FIN.close( );
}

60
Citirea/scrierea datelor în fişiere

• Aceste operaţii se fac cu operatorii de inserție/extracție


și/sau cu metodele membre ale claselor istream şi
ostream

61
Exemplul 1:
#include <iostream>
using namespace std;

#include <fstream>

void main(void)
{
int numar=12;

ofstream OUT ("test.txt"); // creaza un fisier text de iesire


if (!OUT) {
cout<<"Nu se poate deschide fisierul de iesire\n";
return;
}

OUT.write("Salut !\n", 8);


OUT.write((char *)&numar, sizeof(int));
OUT.close( );
62
ifstream IN ("test.txt");
if ( !IN ) {
cout<< "Nu poate deschide fişierul de intrare\n" ;
return;
}

char sir[20];
IN.getline(sir, 19);
IN.read ((char*) &numar, sizeof(int));
cout << sir << ' ' << numar << endl;
IN.close( ) ;
}

63
Exemplul 2:
#include <iostream>
using namespace std;

#include <fstream>
void main( )
{
char infname[101];
char outfname[101];
char buffer[101];
cout << ”File to copy from: ";
cin >> infname;
ifstream in(infname);
if (!in) {
cout << "Unable to open " << infname << endl;
exit(0);
} 64
cout << "File to copy to: ";
cin >> outfname;
ofstream out(outfname);
if (!out) {
cout << "Unable to open " << outfname << " -- already exists!" <<
endl;
exit(0);
}

in.getline(buffer,100);
while (!in.eof( )) {
out << buffer << endl;
in.getline(buffer,100);
}
in.close( );
out.close( );
}

65
Exemplul 3:
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

class Student
{
int marca;
string nume;
double media;

void display()
{
cout << "\n\tMarca\tNume\tMedia";
cout << "\n\t" << marca << "\t" << nume << "\t" << media << "\n";
}
66
public:
Student()
{
marca = 0;
nume = "";
media = 0;
}

Student(int m, string n, double med)


{
marca = m;
nume = n;
media = med;
}

67
static void AddRecord(string fis, Student Stu)
{
fstream f;
f.open(fis, ios::app | ios::binary);
if (f) {
f.write((char *)&Stu, sizeof(Stu));
f.close();
}
}

68
static void Display(string fis)
{
Student Stu;
fstream f(fis, ios::in | ios::binary);
if (f) {
while ((f.read((char*)&Stu, sizeof(Stu)))) {
Stu.display();
}
f.close();
}
}
};

69
void main()
{
int n = 4;
Student tab[4];

tab[0] = Student(1, "N1", 8.55);


tab[1] = Student(2, "N2", 7.50);
tab[2] = Student(3, "N3", 9.55);
tab[3] = Student(4, "N4", 6.45);

for (int i = 0; i < n; i++)


Student::AddRecord("Student.dat", tab[i]);

Student::Display("Student.dat");

cin.get();
}

70
Operaţii de I/E pe şiruri de caractere

• Fişierul antet strstream.h (deprecated) conţine definiţiile


claselor ostrstream, istrstream, strstream ce
implementează operaţii de I/E pe tablouri de caractere
• Inserarea sau extracţia pe aceste fluxuri se face prin
tablouri de caractere (dinamice sau statice)
– Dezavantaj: tipul returnat char *

• Clasele stringstream, istringstream, ostringstream


(fisierul antet sstream): permit operații de I/E pe șiruri
– Avantaj: tipul returnat string

71
• Clasele specificate sunt similare cu cele destinate
lucrului pe fişiere, fiind derivate din clasele iostream
corespondente şi ca urmare moştenesc metodele
membre ale acestora
• De exemplu pentru operaţii de intrare se pot folosi
metodele membre ale clasei istream (get( ), read( ),
getline( )) iar pentru operaţii de ieşire se pot folosi
metodele clasei ostream (put( ), write( )) dar și operatorii
de inserție și extracție
• Un obiect ostringstream poate fi folosit pentru a scrie
într-un șir de caractere (similar cu funcția sprintf())
• Un obiect istringstream poate fi folosit pentru a citi dintr-
un șir de caractere (similar cu funcția sscanf())
• Un obiect stringstream poate fi folosit atât pentru a citi
cât și pentru a scrie din/într-un șir de caractere
72
Constructori de tipul StringStream
• stringstream( )
• stringstream( openmode mode )
• stringstream( string s, openmode mode )

• ostringstream( )
• ostringstream( openmode mode )
• ostringstream( string s, openmode mode )

• istringstream( )
• istringstream( openmode mode )
• istringstream( string s, openmode mode )

Supraîncărcări
• operator<<
• operator>>
73
Alte metode:
• void str( string s );
– Permite obținerea unei copii a șirului asociat unui obiect
cout << stream1.str();

• string str();
– Permite copierea unui șir într-un obiect
stream1.str(string1);

74
Exemple:
ostringstream s1;
int i = 22;
s1 << “i = " << i << endl;
string s2 = s1.str();
cout << s2;

istringstream stream1;
string string1 = "25";
stream1.str(string1); // istringstream stream1 (string1);
int i;
stream1 >> i;
cout << i << endl;
75
// conversii intre un tip predefinit si tipul string

double d = 123.45;
ostringstream os;
os << d;
string s = “d = " + os.str();
cout << s << endl;

76
// conversii intre baze de numeratie
int decimal = 61;
stringstream sstr;
sstr << hex << decimal;
cout << “Valoarea in baza 16: " << sstr.str();

string hex_str = "0x2b";


stringstream sstr;
sstr << hex << hex_str;
unsigned int decimal;
sstr >> decimal;
cout << "Valoarea in baza 10: " << decimal;

77

S-ar putea să vă placă și