Sunteți pe pagina 1din 17

CAPITOLUL 13 Intrri/ieiri

INTRRI/IEIRI 13
13.1. Principiile de baz ale sistemului de 13.4. Metodele clasei istream
I/O din limbajul C++ 13.5. Metodele clasei ostream
13.2. Testarea i modificarea strii unui flux 13.6. Manipulatori creai de utilizator
13.3. Formatarea unui flux 13.7. Fluxuri pentru fiiere
13.3.1. Formatarea prin manipulatori 13.8. Fiiere binare
13.3.2. Formatarea prin metode

13.1. PRINCIPIILE DE BAZ ALE SISTEMULUI DE INTRRI/IERI


DIN LIMBAJUL C++

n limbajul C++ exist dou sisteme de intrri/ieiri:


Unul tradiional, motenit din limbajul C, n care operaiile de intrare/ieire se realizeaz cu ajutorul unor
funcii din biblioteca standard a sistemului (vezi capitolul 8);
Unul propriu limbajului C++, orientat pe obiecte.

Sistemul de I/O orientat pe obiecte al limbajului C++ trateaz n aceeai manier operaiile de I/O care
folosesc consola i operaiile care utilizeaz fiiere (perspective diferite asupra aceluiai mecanism).

La baza sistemului de I/E din C++ se afl:


dou ierarhii de clase care permit realizarea operaiilor de I/O;
conceptul de stream (stream-ul este un concept abstract care nglobeaz orice flux de date de la o surs
(canal de intrare) la o destinaie (canal de ieiere), la un consumator. Sursa poate fi tastatura (intrarea
standard), un fiier de pe disc sau o zon de memorie. Destinaia poate fi ecranul (ieirea standard), un
fiier de pe disc sau o zon de memorie (figura 13.1).
Fluxuri din Fluxuri din
clasa istream clasa ostream
Memoria intern

Fluxuri din Fluxuri din


clasa clasa
ifstream fiiere ofstream

Figura 13.1. Stream-ul - baza sistemului de I/O

Avantajele utilizrii stream-urilor sunt:


Flexibilitate mare n realizarea operaiilor de I/O (mai mare dect n cazul folosirii funciilor din C);
Posibilitatea de eliminare a erorilor care apar n mod frecvent la apelul funciilor de I/O obinuite, cnd
numrul specificatorilor de format difer de cel al parametrilor efectivi;
Posibilitatea de a realiza operaii de I/O nu numai cu date de tipuri predefinite, ci i cu obiecte de tip
abstract.

205
CAPITOLUL 13 Intrri/ieiri
Biblioteca de clase de I/O a limbajului C++ utilizeaz motenirea, polimorfismul i clasele abstracte. Ierarhia
are dou clase de baz (figura 13.2.):
Clasa virtual ios care ofer informaii despre fluxurile de date (variabile de stare, metode) i faciliti
tratarea erorilor;
Clasa streambuf (clas prieten cu ios), destinat operaiilor de I/O cu format.

ios streambuf

istream ostream strstreambase fstreambase

iostream

ifstream ofstream

fstream filebuf

Figura 13.2. Ierarhia claselor de intrare/ieire


Utilizarea ierarhiilor de clase de mai sus implic includerea headerului iostream.h.
Clasa ios are un pointer ctre streambuf. Are date membru pentru a gestiona interfaa cu streambuf i
pentru tratarea erorilor. Clasele derivate din clasa de baz ios:
Clasa istream, care gestioneaz intrrile: class istream:virtual public ios
Clasa ostream gestioneaz ieirile: class ostream: virtual public ios
Clasa iostream, derivat din istream i ostream, gestioneaz intrrile i ieirile. Fiecrui flux
de date i se asociaz n memorie o zon tampon numit buffer. Clasa furnizeaz funcii generale
pentru lucrul cu zonele tampon i permite tratarea operaiilor de I/O fr a avea n vedere
formatri complexe.
class iostream:public istream, public ostream
Clasele istream, ostream i iostream sunt, fiecare, clase de baz pentru clasele derivate:
class istream_withassign:public istream
class ostream_withassign:public ostream
class iostream_withassign:public iostream

Clasele cu sufixul _withassign furnizeaz urmtoarele fluxurile predefinite (instane), deja cunoscute:
1. cout (console output) obiect al clasei ostream_withassign, similar fiierului standard de ieire
definit de pointerul stdout (n C). Se folosete cu operatorul insertor, suprancrcat pentru tipurile
predefinite:
Exemplu: int n; cout<<n;
Convertete din format binar n zecimal valoarea lui n, i trimite (insereaz) n fluxul cout
caracterele corespunztoare fiecrei cifre obinute.
2. cin (console input) obiect al clasei istream_withassign, similar fiierului standard de intrare
definit de pointerul stdin (n C). A fost folosit cu operatorul extractor, suprancrcat pentru tipurile
predefinite:
Exemplu: int n; cin>>n;
Extrage din fluxul de intrare caracterele corespunztoare, le convertete din zecimal n binar i le
depune n memorie.
3. cerr: flux de ieire conectat la ieirea standard pentru erori (stderr n C) (fr buffer intermediar).
4. clog: flux de ieire conectat la ieirea standard pentru erori (fr buffer intermediar).

206
CAPITOLUL 13 Intrri/ieiri
Clasa streambuf este clas prieten cu ios. Ea furnizeaz funcii generale pentru lucrul cu
zonele tampon (buffere) i permite tratarea operaiilor de I/O fr formatri complexe. Din clasa
streambuf deriva clasa filebuf .

S urmrim care este rolul buffere-lor (zon tampon asociat fiecrui flux de date), prin urmtorul exemplu:

Exemplu: Memorie intern


void main()
{int a; double x; char sir[20];
cin>>a>>x>>ir; a
cout<<a<<' '<<x<<endl; date de x
cout<<sir<<endl; intrare
}
sir

Zona tampon (buffer-ul) este interfaa buffer cin


dintre program i sistemul de operare.
buffer cout

S urmrim cum se realizeaz transferul informaiei


n cazul operaiilor multiple: Figura 13.3. Rolul buffere-lor n operaiile de I/O
cin>>a>>x>>ir;
cin>>a;
Compilatorul verific dac numrul introdus este ntreg (se oprete cnd ntlnete altceva dect o cifr: n
acest caz - un blanc). l citete printr-o metod a tipului int, l convertete n binar i l transmite n memoria
intern n spaiul rezervat pentru variabila a. n ncheiere, cin>>a devine cin.
cin>>a>>x; // fluxul de date se transmite i lui x
Presupunem c am introdus de la tastatur 325 17.45e5 exemplu de ir, valorile pentru a, x i
sir. La apsarea tastei Enter, se transmite ctre sistemul de operare un octet cu semnificaia de sfrit
introducere date. Sistemul de operare transmite un semnal zonei tampon i abia acum se transmite valoarea
(fluxul de date) lui a. La citirea irului de caractere (pn la primul blank), se transfer octet cu octet (i se
adaug automat caracterul NULL), din zona tampon n memoria intern.

Observaii:
1. Stream-ul este secvenial.
2. El poate realiza intrri/ieiri formatate.
3. Este bine c n cazul unui flux de intrare s se verifice mai nti dac n zona tampon se gsete ceva.
Dac nu, se poziioneaz cursorul la nceputul zonei tampon.
4. Informaia de la buffer ctre memorie este gestionat prin program; informaia de la zona tampon ctre
alte periferice este gestionat de ctre sistemul de operare.

13.2. TESTAREA I MODIFICAREA STRII UNUI FLUX

Clasa ios, clas de baz a ierahiei claselor de I/O, definete o mulime de tipuri, variabile i metode
comune tuturor tipurilor de stream-uri.

Starea unui stream (rezultatul ultimului acces la acesta) este pstrat n cuvntul de stare, care este dat
membr a clasei ios. Fiecrei instanieri a unei clase de intrare/ieire i se asociaz propriul cuvnt de stare
(o mulime de indicatori de stare), care pstreaz toate informaiile aferente erorilor aprute n cursul
operaiilor cu stream-ul. Aceti indicatori sunt memorai la nivel de bit n data membru state.

class ios{
//
protected:

207
CAPITOLUL 13 Intrri/ieiri
int state; //pstreaz la nivel de bit valorile indicatorilor de stare
public:
enum io_state{
goodbit=0x00, //ultima operaie de intrare/ieire corect
eofbit=0x01, //s-a ntlnit sfritul de fiier ntr-o operaie de intrare (lipsa
//caracterelor disponibile pentru citire)
failbit=0x02, //setat dac ultima operaie de intrare/ieire a euat; stream-ul
//respectiv nu va mai putea fi folosit n operaii de I/O pn cnd
//bitul nu va fi ters
badbit=0x04, //ultima operaie de intrare/ieire invalid; n urma resetrii flag-ului
//este posibil ca stream-ul s mai poat fi utilizat
hardbit=0x08 //eroare irecuperabil
};
};

Testarea valorii cuvntului de stare asociat unui stream se realizeaz cu ajutorul metodelor:
int good();//Returneaz valoare diferit de zero dac cuvntul de stare este 0
int eof();//Returneaz valoare diferit de zero dac eofbit este setat
int fail();//Returneaz valoare diferit de zero dac failbit, hardbit sau badbit sunt setai
int bad();//Funcioneaz ca metoda fail, dar nu ia n considerare flagul failbit.

Modificarea valorii cuvntului de stare asociat unui stream se realizeaz cu ajutorul metodelor:
void clear(int i=0);
Seteaz data membru state la valoarea parametrului (implicit 0). Este capabil s tearg orice flag, cu
excepia flag-ului hardfail.
Exemplu:: a.clear(ios::badbit);
Seteaz bitul failbit i anuleaz valorile celorlai bii din cuvntul de stare a fluxului a. Pentru ca
ceilali bii s rmn nemodificai, se apeleaz metoda rdstate.
Exemplu: a.clear(a.rdstate()|val_f);
Se seteaz un singur flag, lsndu-le nemodificate pe celelalte; val_f are una din valorile definite de
enumerarea io_state.
int rdstate();
Returneaz valoarea cuvntului de stare, sub forma unui ntreg (valoarea datei membru state).
Exemplu: a.clear(ios::badbit | a.rdstate());
Seteaz bitul failbit, fr a modifica valorile celorlali bii:

Testarea cuvntului de stare se poate realiza i prin folosirea operatorilor ! i void* :


Operatorul ! este suprancrcat printr-o funcie membr, cu prorotipul:
int operator ! ();
care returneaz 0 dac un bit de eroare din cuvntul de stare este setat (ca i metoda fail).
Exemplu:
if (!cin) //echivalent cu if (!cin.good())
cout<<"Bit de eroare setat n cuvntul de stare!\n";
else cin>>a;
Operatorul void* convertete stream-ul ntr-un pointer generic. Conversia are ca rezultat zero dac cel
puin un bit de eroare este setat:
operator void *();
Exemplu: O construcie de forma: cin>>s; are ca valoare o referin la stream-ul cin, din clasa
istream. Aceast referin poate fi utilizat sub forma: if (cin>>s). . .

Pentru scoaterea unui stream din starea de eroare, fie dispare cauza erorii, fie trebuie terse flagurile care
semnalizeaz eroarea.

208
CAPITOLUL 13 Intrri/ieiri
13.3. FORMATAREA DATELOR DIN FLUXURILE DE INTRARE/IEIRE

Unul dintre principalele avantaje oferite de sistemul de I/O din limbajul C++ l reprezint ignorarea
aspectului formatrii, folosindu-se o formatare implicit. n plus, se permite definirea unei formatri
specifice pentru o anumit aplicaie. Aa cum s-a subliniat n cazul cuvntului de eroare, cuvntul de format
poate fi privit ca un ntreg, pentru care fiecare bit reprezint o constant predefinit din clasa ios. n cadrul
acestui cuvnt sunt definite cmpuri de bii (cuvntul de format este dat membr care conine un numr
de indici ce sunt bii individuali).

class ios {
//
protected:
long flag_x; //pstreaz la nivel de bit indicatorii de format
int x_width; //numrul de caractere utilizate pentru afiarea unei valori pe ecran
public:
enum
{skipws = 0x0001, // salt peste spaiile albe de la intrare
left = 0x0002, // aliniere la stnga la ieire
right = 0x0004, // aliniere la dreapta la iesire
internal = 0x0008, // aliniere dup semn sau specificator al bazei la ieire
dec = 0x0010, // conversie n baza 10
oct = 0x0020, // conversie octal la intrare/ieire
hex = 0x0040, // conversie hexa la intrare/ieire
showbase = 0x0080, // afiarea bazei la ieire
showpoint = 0x0100, // afiarea punctului zecimal pentru numere reale la ieire
uppercase = 0x0200, // afiarea cu majuscule a cifrelor hexa i a literei E la ieire.
showpos = 0x0400, // afiarea semnului + pentru numerele pozitive la ieire
scientific = 0x0800, //folosirea formatului exponenial (tiinific) pentru numerele reale
fixed = 0x1000, // folosirea formatului n virgul fix pentru numere reale la
unitbuf = 0x2000, // golete zona tampon dup fiecare ieire
stdio=0x4000 // golete "stdout" i "stdin" dup fiecare inserare
};
};
n figura 13.4. sunt prezentate numele cmpurilor de bii (acolo unde este cazul). n cadrul fiecrui cmp de
bii (adjustfield, basefield, floatfield) un singur bit poate fi activ.

floatfield
floatfield basefield adjustfield
scientific

showpoint
uppercase

internal
showbase

skipws
unitbuf

showpos

right
fixed

left
hex

oct

dec

Figura 13.4. Cmpurile de bii din cuvntul de stare

Modificarea cuvntului de format se poate realiza n urmtoarele moduri:


1. Cu ajutorul manipulatorilor (cu sau fr parametri);
2. Cu ajutorul unor funcii membre ale claselor istream sau ostream.

209
CAPITOLUL 13 Intrri/ieiri
13.3.1. FORMATAREA PRIN MANIPULATORI

Manipulatorii sunt funcii speciale, asemntoare operatorilor, care pot fi folosite mpreun cu operatorii de
inserie ntr-un flux de ieire sau de extracie dintr-un flux de intrare, n scopul modificrii caracteristicilor
formatului informaiilor de intrare/ieire. Manipulatorii furnizeaz, ca rezultat, fluxul obinut n urma aciunii
manipulatorilor, ceea ce permite ca acetia s fie tratai ca informaii de transmis. Manipulatorii permit,
deasemenea, nlnuirea operatorilor insertori sau extractori care utilizeaz formate diferite.

Manipulatorii pot fi:


Manipulatori fr parametri;
Manipulatori cu parametri;

13.3.1.1. Manipulatori fr parametri

Prototipul manipulatorilor fr parametri este:


ostream & nume_manipulator(ostream &);
istream & nume_manipulator(istream &);
Manipulatorii fr parametri (prezentai n tabelul 13.1.) se folosesc astfel:
flux_ieire<<manipulator;
flux_intrare>>manipulator;

Tabelul 13.1
Manipula Intrare/ Aciune
tor Ieire
dec I/O Formateaz datele numerice n zecimal (activeaz bitul de conversie zecimal)
hex I/O Formateaz datele numerice n hexa (activeaz bitul de conversie hexazecimal)
oct I/O Formateaz datele numerice n octal (activeaz bitul de conversie octal)
ws I Ignor caracterele "spaii albe" (activeaz bitul de salt peste spaiile albe)
endl O Afieaz (insereaz) un caracter '\n' i elibereaz fluxul
ends O Insereaz un caracter null, de sfrit de flux (\0)
flush O Videaz (golete) buffer-ul, elibereaz fluxul

13.3.1.2. Manipulatori cu parametri

Prototipul manipulatorilor fr parametri (prezentai n tabelul 13.2.) este:


istream & manipulator (argument);
ostream & manipulator (argument);

Tabelul 13.2.
Manipulator Intrare/ Aciune
Ieire
setbase(int baza) I/O Stabilete baza de conversie
resetiosflags(long f) I/O Atribuie valoarea 0 tuturor biilor indicai de argument,
lsnd restul biilor nemodificai (dezactiveaz indicatorii
specificai de f)
setiosflags (long f) I/O Atribuie valoarea 1 tuturor biilor indicai de argument,
lsnd restul biilor nemodificai (activeaz indicatorii
specificai de f)
setfill (int c) I/O Definete caracterul de umplere (cel implicit este spaiul
liber, blank-ul)
setprecision (int p) I/O Definete precizia pentru numerele reale
setw (int w) I/O Definete limea cmpului (numrul de octei care vor fi
citii sau afisai)

210
CAPITOLUL 13 Intrri/ieiri
Utilizarea manipulatorilor impune includerea header-ului iomanip.h.

Exerciiu: Exemplificarea modului de folosire a manipulatorilor pentru intrri/ieiri formatate.

#include <iostream.h>
#include <iomanip.h>
void main()
{int a,b,c;double alfa,x,y;long ll;char xx,yy;
float u,v; unsigned int w; unsigned char ab,db;
a=125,b=10; ll=100*a*b; cout<<"100*a*b="<<ll<<endl; //100*a*b=-6072
alfa=75.50;y=1.345678;
xx=35;yy=6; x=y/alfa-xx/yy; cout<<"x="<<x<<endl; //x=-4.982176
//setarea mrimea cmpului de afiare
cout<<"x="<<setw(8)<<x<<endl; //x=-4.982176
cout<<"x="<<setw(20)<<x<<endl; //x= -4.982176
//setarea lungimii cmpului de afiare i a caracterului de umplere
cout<<"x="<<setw(20)<<setfill('*')<<x<<endl; //x=***********-4.982176
// precizie
cout<<"x="<<setw(8)<<setprecision(2)<<x<<endl; //x=***-4.98
cout<<"x="<<setw(8)<<setprecision(0)<<x<<endl; //x=-4.982176
// afisarea octetului semnificativ var & 0377 si a celui mai putin semnificativ (var>>8) & 0377
w=34; ab='34' & 0377; db=('34'>>8)&0377;
cout<<"w="<<w<<" ab="<<ab<<" db="<<db<<endl; //w=34 ab=3 db=4
u=2579.75;v=12345.567E+10;
//formatare in octal si hexa
cout<<"a in baza 10="<<a<<" in octal="<<oct<<a<<" in hexa="<<hex<<a<<endl;
//a in baza 10=125 in octal=175 in hexa=7d
cout<<"b="<<dec<<b<<endl; //b=10
}

13.3.2. FORMATAREA PRIN METODE

Formatarea fluxurilor de intrare/ieire se poate realiza i prin metode ale clasei ios.

Funcia membr setf permite modificarea cuvntului de stare a formatrii. Ea este supradefinit astfel:
long setf (long) ;
Primete ca parametru un numr ntreg long i seteaz pe 1 biii specificai prin argument. Returneaz
valoarea anterioar a cuvntului de stare a formatrii. Ea poate fi folosit numai pentru flag-urile care nu
fac parte dintr-un cmp de bii.
Exemplu: cout. setf (ios:: showpos); //seteaz bitul showpos pe 1
long setf (long flags, long field) ;
Seteaz pe 1 biii specificai prin primul argument, doar n cmpul de bii definit ca al doilea argument.
Ea modific pe 0 toi biii din cmpul respectiv, dup care seteaz (pe 1) bitul respectiv.
Exemple:
cout. setf (ios:: showpos | ios :: uppercase | ios:: internal)
//toi biii vor fi setai pe valoarea 1
cout.setf (ios :: hex, ios :: basefield) //seteaz indicele hex din cmpul basefield
cout. setf (ios :: skipws | ios :: hex | ios:: showbase, ios :: basefield)
Funcia membr fill permite testarea sau modificarea caracterului de umplere i returneaz codul
caracterului curent de umplere:
int fill ( ) ;
Exemplu: cout.fill ( ); // ntoarce codul caracterului de umplere pt. cout
int fill (char) ;
Seteaz noul caracter de umplere i returneaz codul vechiului caracter de umplere.
Exemplu: cout.fill(# ); // seteaz un alt caracter de umplere ('#').

211
CAPITOLUL 13 Intrri/ieiri
Funcia membr precision permite testarea sau modificarea preciziei. Numim precizie numrul de
cifre semnificative (n GNU) sau numrul de cifre dup virgul (n TurboC)
int precision ( );
Returneaz valoarea actual a preciziei numerice.
int precision (int);
Seteaz precizia la valoarea parametrului i returneaz vechea valoare a preciziei.
Funcia membr width returneaz valoarea actual a lungimii cmpului de date sau seteaz valoarea
lungimii cmpului de date.
int width ( ) ;
.int width (int) ;
Exemplu: cout. width (10); //data se va afia ntr-un cmp de cel puin 10 caractere.
Astfel, dac argumentul este 0, la inseria ntr-un flux de ieire se transmit n stream atia octei ci are
data respectiv. Dac argumentul este diferit de 0, dar lungimea necesar afirii este mai mare, se
transmite numrul de octei necesari; iar dac lungimea necesar afirii este mai mic, se transmite
numrul de octei necesari, iar restul se completeaz cu caracterul de umplere.

Exerciiu:
#include <iostream.h>
void main()
{int i=123, j=456; double x=1234.567890123456, y=5678;
cout.width(5); cout<<i<<' '<<j<<endl; //123 456
cout<<i; //toate metodele sunt persistente, cu excepia metodei width
cout.width(5); cout<<j<<endl; //123 456
cout.setf(ios::showpos); //afis. +
cout<<i<<' '<<j<<endl; //+123 +456
cout.setf(ios::hex, ios::basefield);
cout.width(20); cout.precision(15); cout.fill('*');
cout.setf(ios::showpos | ios::showpoint);
cout<<x<<' '<<y<<endl; //***+1234.56789012346 +5678.00000000000
cout<<i<<' '<<j<<endl; //7b 1c8
cout.setf(ios::dec, ios::basefield);
cout.unsetf(ios::showpos); cout.fill(' ');
cout<<i<<' '<<j<<endl; //123 456
cout<<x<<' '<<y<<endl; //1234.56789012346 5678.00000000000
}

Observaie: Toate metodele sunt persistente, cu excepia metodei width care este valabil numai pentru
operaia urmtoare, dup care se seteaz la 0.

13.4. METODELE CLASEI istream

Clasa istream este derivat din clasa ios: ios:istream.


Supradefinirea operatorului de extracie >>
Operatorul de extracie din stream-ul (fluxul) de intrare este suprancrcat printr-o funcie membr,
pentru toate tipurile de baz. El are rolul de a extrage din fluxul de intrare caracterele necesare pentru a
obine o valoare dintr-un tip de baz.
istream & operator >> (&tip_de_baz);
Primul argument este implicit (this): clasa care l apeleaz. Al doilea argument este o referin ctre un
tip_ de_baz. Operatorul poate fi suprancrcat printr-o funcie prieten (vezi capitolul 11), pentru a
extrage din fluxul de intrare informaiile despre un obiect dintr-un tip definit de utilizator (clas):
friend istream & operator >>(istream &, clasa &);
Metoda get
istream & get (char &);
Metoda extrage din fluxul de intrare un caracter i l memoreaz n variabila referin, transmis ca
parametru. ntoarce o referin ctre istream.

212
CAPITOLUL 13 Intrri/ieiri
Exemplu: char c; cin.get(c);
Metoda get este suprancrcat i astfel:
int get ( );
Extrage din fluxul de intrare un singur caracter i l returneaz sub forma unui ntreg. Aceast metod
este utilizat, n special, la testarea sfritului de fiier (EOF, -1).
Metoda get este suprancrcat i astfel:
istream & get (char * ir, int lungime, char delimitator = \n)
Se extrage din fluxul de date de intrare un ir de caractere (char * ir = pointer ctre ir), cu
lungimea maxim specificat prin argumentul lungime, pn la ntlnirea delimitatorului
(delimitator nu se extrage din fluxul de date de intrare). Rezultatul se depune n variabila ir.
Metoda getline
Metoda determin preluarea din fluxul de intrare a unui ir de caractere, terminat cu un caracter
cunoscut.
istream & getline (char * ir, int lungime, char delimitator = EOF);
Acioneaz asemntor cu metoda get suprancrcat prin ultima form, cu deosebirea c din fluxul de
intrare se extrage i delimitatorul. Delimitatorul nu se introduce n ir.
Exemplu: char ir[50];cin.get (ir, 50, \ n); // sau cin.get(ir, 50);
Din fluxul de date de intrare se extrag caracterele pn la sfrit de linie, cel mult 50 de caractere.
Extragerea caracterelor din fluxul de intrare se termin fie la ntlnirea terminatorului, fie atunci cnd
s-a citit un numr de caractere egal cu lungime-1 .
Metoda gcount returneaz un ntreg care reprezinat numrul efectiv de caractere preluat prin
getline.
int gcount();
Metoda read extrage din fluxul de intrare un ir de caractere (octei) de lungime impus i-l
depoziteaz n zona de memorie ir.
istream & read (char * ir, int lungime);
Eemplu: char t[30]; cin.read(t, 20);
Metoda ignore este utilizat la golirea zonei tampon a stream-ului de intrare.
istream & ignore (int lungime, char delimitator = | );
Se extrag din fluxul de intrare caracterele pn la delimitator, dar nu mai multe dect numrul indicat de
parametru lungime. Caracterele extrase sunt eliminate, nu sunt memorate.
Metoda peck furnizeaz primul caracter din fluxul de intrare, fr a-l extrage ns din flux. Caracterul
va fi primul caracter extras la urmtoarea citire.
int peck( );
Exemplu: c = cin.peck ( );
Metoda putback insereaz n fluxul de intrare caracterul trimis ca argument.
istream & putback(char &);
Observaii:
1) int a; cin.get (a) cin >> a;
2) Metodele pot fi folosite n serie: Exemplu: cin.get(a).get(b).get (c);

13.5. METODELE CLASEI ostream

Supradefinirea operatorului de inserie <<


Operatorul de inserie n fluxul de ieire este suprancrcat printr-o funcie membr pentru toate tipurile
de baz. El are rolul de a introduce (insera) n fluxul de ieire caracterele necesare pentru a afia o
valoare dintr-un tip de baz.
ostream & operator << (tip_de_baz);
Primul argument este implicit (this). Al doilea argument este o expresie de tip de baz.
Operatorul poate fi suprancrcat printr-o funcie prieten, pentru a insera n fluxul de ieire informaiile
despre un obiect dintr-un tip definit de utilizator (clas):
friend ostream & operator << (ostream &, clasa &);
Metoda put insereaz n fluxul de date de ieire caracterul transmis ca parametru.
ostream put (char);

213
CAPITOLUL 13 Intrri/ieiri
Exemple:
char c='S'; cout . put ( c ); // echivalent cu cout << c;
char c1='A',c2='B',c3='C';cout.put(c1).put(c2).put(c3);
//echivalent cu:cout.put(c1);cout.put(c2); cout.put(c3);
// echivalent cu cout<<c1<<c2<<c3;
Metoda write insereaz n fluxul de date de ieire un numr de caractere, de lungime impus,
existente n zona tablou.
ostream & write (char * tablou, int lungime);
Exemplu: char t[]="Bun ziua!\n"; cout.write(t, 4);
//Insereaz n fluxul de ieire 4 caractere, ncepnd de la adresa t.

Exerciiu: Se ilustreaz formatarea unui flux de intrare/ieire att prin funcii membre, ct i cu ajutorul
manipulatorilor (cu sau fr parametri).
#include <iostream.h>
#include <iomanip.h>
void main()
{int i=123; char car, mesaj[]=" Apas tasta Enter\n";
cout<<setw(5)<<resetiosflags(ios::internal |ios::right);
cout<<setiosflags(ios::left)<<setfill('#')<<i<<endl;
cout<<setw(5)<<setiosflags(ios::showpos)<<setfill(' ')<<i<<endl;
cout<<setw(5)<<resetiosflags(ios::left)<<setfill('0')<<setiosflags(ios::right);
cout<<i<<endl;
cout<<"\n hexagesimal:"<<setw(5)<<hex<<i<<endl;
cout<<"\n octal:"<<setw(5)<<oct<<i<<endl;
cout<<"\n zecimal:"<<setw(5)<<dec<<i<<endl;
cout<<mesaj; cin.get(car);
double d=123.456789012345678901234567890123456789;
cout<<"Afisare d cu precizia implicit:"<<d<<endl;
cout<<"Afisare d cu lung 25 si precizie
15:"<<setw(25)<<setprecision(15)<<d<<endl;
cout<<"Schimbare caracter umplere &:"<<setw(25)<<setfill('&')<<d<<endl;
cout<<endl;
}

13.6. MANIPULATORI CREAI DE UTILIZATOR

Manipulatorii sunt funcii speciale care pot fi utilizate alturi de operatorii de inserie/extracie pentru a
formata datele de ieire/intrare. Pe lng manipulatorii predefini, utilizatorul i poate crea manipulatori
proprii.

Crearea manipulatorilor fr parametri


ostream &nume_manipulator (ostream &); //pentru un flux de ieire
istream &nume_manipulator (istream &); //pentru un flux de intrare
Crearea manipulatorilor cu parametri
Crearea manipulatorilor fr parametri necesit folosirea a dou funcii:
ostream & nume_manipulator (ostream &, int);

omanip <int> nume_manipulator (int n) // funcie ablon (template) cu parametru de tip int
{return omanip <int> (nume_manipulator, n);}

Deci, manipulatorii sunt funcii ale cror corpuri sunt stabilite de utilizator.

Exemplu: n exemplul urmtor se definesc manipulatorii indentare (indentare = naintea liniei propriu-
zise, se las un numr de spaii albe), convhex (realizeaz conversia din zecimal n hexa), init
(iniializeaz lungimea cmpului la 10 caractere, stbilete precizia la 4 i caracterul de umplere $).

214
CAPITOLUL 13 Intrri/ieiri
#include <iostream.h>
#include <iomanip.h>
ostream &convhex (ostream &ies)
{ies.setf(ios::hex, ios::basefield); ies.setf(ios::showbase); return ies;}
ostream &indentare (ostream &ies, int nr_spaii)
{for (int i=0; i<nr_spatii; i++) ies<<' '; return ies;}
ostream &init (ostream &ies)
{ies.width(10); stream.precision(4); ies.fill('$'); return ies;}
omanip <int> indentare (int nr_spaii)
{return omanip <int> (indentare, nr_spaii);}
void main()
{cout<<712<<' '<<convhex<<712<<endl;
cout<<indentare(10)<<"Linia1 text\n"<<indentare(5)<<"Linia2 text\n";
cout init<<123.123456;}

13.7. FLUXURI DE DATE PENTRU FIIERE

Un flux de intrare/ieire poate fi asociat unui fiier.

Pentru a asocia un flux de ieire unui fisier, este necesar crearea unui obiect de tipul ofstream. Clasa
ofstream este derivat din clasele ostream (motenete metodele care permit inserarea informaiilor
ntr-un flux de ieire) i fstreambase (motenete operaiile privitoare la asocierea fiierelor).

Pentru a asocia un flux de intrare unui fiier, este necesar crearea unui obiect de tipul ifstream. Clasa
ifstream este derivat din clasele istream (motenete metodele care permit extragerea informaiilor
dintr-un flux de intrare) i fstreambase (motenete operaiile privitoare la asocierea fiierelor).

Pentru crearea unor obiecte din clasele ifstream sau ofstream se impune includerea headere-lor
iostream.h i fstream.h.

Constructorii clasei ofstream sunt:


ofstream();
Fluxul nu este asociat nici unui fiier
ofstream(const char *nume_fisier, int mod_acces=ios:out);
Parametri constructorului sunt numele fiierului i modul de acces la acesta (scriere, fiier de ieire).
ofstream (int fd, char *buffer, int lung_buffer);
Parametrii sunt numrul intern al fisierului (fd), zona tampon de intrri/ieiri (buffer) i lungimea zonei
tampon (lung_buffer).

Constructorii clasei ifstream sunt:


ifstream();
Fluxul nu este asociat nici unui fiier
ifstream(const char *nume_fisier, int mod_acces=ios:in);
Parametri constructorului sunt numele fiierului i modul de acces la acesta (citire, fiier de intrare).
ifstream (int fd, char *buffer, int lung_buffer);
Parametrii sunt numrul intern al fiierului (fd), zona tampon de intrri/ieiri (buffer) i lungimea zonei
tampon (lung_buffer).

Exemplu:
Se declar obiectul numit fis_ies, de tipul ofstream, obiect asociat unui fiier cu numele DATE.txt,
deschis apoi pentru ieire (scriere). Scrierea n fiierul asociat obiectului se face printr-un flux care
beneficiaz de toate "facilitile" clasei ostream.
ofstream fis_ies("DATE.txt", ios::out); //sau: ofstream fis_ies("DATE.txt");
Scrierea n fiierul DATE.txt: fis_ies<< . . . << . . .;
Pentru scriere formatat sau scriere binar n fiierul asociat: fis_ies.write(. . . );

215
CAPITOLUL 13 Intrri/ieiri
Pentru examinarea strii fluxului de eroare corespunztor: if (fis_ies) . . .;

Se declar obiectul numit fis_intr, de tipul ifstream, obiect asociat unui fiier cu numele NOU.txt,
deschis apoi pentru intrare (citire). Citirea din fiierul asociat obiectului se face printr-un flux care
beneficiaz de toate "facilitile" clasei istream.
ifstream fis_intr("DATE.dat", ios::in); //sau: ifstream fis_intr("NOU.txt");
Citirea n fiierul NOU.txt: fis_intr>> . . . >> . . .;
Pentru citire formatat sau citire binar din fiierul asociat: fis_intr.read(. . . );
Pentru examinarea strii fluxului de eroare corespunztor: if (fis_intr) . . .;

Observaii: Conectarea (asocierea) unui flux unui fiier presupune:


Fie existena a dou tipuri de obiecte: un flux i un fiier;
Fie declararea unui flux care va fi asociat ulterior unui fiier.

Clasa fstream motenete att clasele ifstream, ct i ofstream. Ea permite accesul n citire/scriere.
Constructorul cu parametri al clasei fstream:
fstream(char *nume_fiier,int mod_deschid,int protec=filebuf::openprot);

Modul de deschidere (mod_deschid) a unui fiier poate fi:


ios::in fiier de intrare
ios::out fiier de ieire
ios::ate dup deschiderea fiierului, poziia curent este sfritul acestuia
ios::app mod append (de scriere la sfritul unui fiier existent)
ios::trunc dac fiierul exist, datele existente se pierd
ios::nocreate dac fiierul asociat nu exist, nu va fi creat dect la scriere
ios::binary fiier binar
ios::noreplace fiierul nu trebuie s existe

Modul de deschidere este definit printr-un cuvnt de stare, n care fiecare bit are o semnificaie particular.
Pentru setarea (activarea) mai multor bii, se folosete operatorul | (sau logic, pe bit), ca n exemplu.
class ios{
//..
public:
enum open_mode{
in=0x01, out=0x02, ate=0x04,
app=0x08, trunc=0x10, nocreate=0x20,
noreplace=0x40, binary=0x80
};
};

Exemple: ifstream f1("DATE.txt", ios::in|ios::nocreate);


fstream f2("pers.dat", ios::in|ios::out);
Metoda open
Prelucrarea unui fiier ncepe cu deschiderea acestuia, care se poate realiza:
La instanierea obiectelor din clasele ifstream, ofstream sau fstream, cu ajutorul constructorului cu
parametri (constructorul apeleaz automat funcia open);
Prin apelul explicit al funciei open.
Metoda open este definit n clasa fstreambase i este suprancrcat n funciile derivate din
aceasta. Ea are aceeai parametri ca i constructorul clasei i prototipul:
void open (char *nume_fiier, int mod_deschidere, int protecie);

Metoda close realizeaz nchiderea unui fiier:


void close();

216
CAPITOLUL 13 Intrri/ieiri
Exerciiu: n exemplul urmtor se asociaz fluxului de ieire (obiectului fis_ies) fiierul numit
text.txt. Se testeaz cuvntul de stare de eroare, iar dac nu au fost probleme la deschidere, n fiier se
scrie un text (2 linii), apoi, o serie de constante numerice, formatate. Se nchide fiierul. Acelai fiier este
asociat unui flux de intrare (pentru citire). Textul (scris anterior) este citit n variabila ir, apoi este afiat.
Se citesc din fiier i apoi sunt afiate constantele numerice. Se nchide fiierul.

#include <fstream.h>
#include <iomanip.h>
int main()
{ofstream fis_ies("text.txt"); //deschidere fiier text.txt
if (!fis_ies){ cout<<"Eroare la dechiderea fiierului!\n"; return 1;}
fis_ies<<"Scrierea unui text \n n fiier\n";
fis_ies<<100<<hex<<setw(10)<<100<<setw(20)<<setprecision(12);
cout<<123.456789012356789<<endl;
fis_ies.close(); //nchiderea fiierului
ifstream fis_intr("text.txt"); //deschiderea fis. ptr. citire
if (!fis_intr){cout<<"Eroare la deschiderea fis. ptr. citire!\n";return 1;}
char sir[100];
for (int k=0; k<9; k++) {fis_intr>>sir; cout<<sir<<'\n';}
cout<<endl; int i, j; double u; fis_intr>>i>>hex>>j>>u;
cout<<i<<' '<<j<<' '<<u<<endl; fis_intr.close(); return 0; }

Observaii:
Deschiderea i nchiderea fiierului s-ar fi putut realiza i astfel:
fstream fis_ies;fis_ies.open("text.txt", ios::out);fis_ies.close();
fstream fis_in;fis_in.open("text.txt", ios::in);fis_in.close();

Exemplu: S se scrie un program care concateneaz dou fiiere, depunnd rezultatul n al treilea fiier. Se
creaz trei fluxuri, f1, f2 i dest, care sunt ataate fiierelor corespunztoare (prin metoda open). Copierea
n fiierul destinaie se realizeaz prin folosirea metodelor get, put i funcia copy. Metoda close
ntrerupe legtura logic dintre fluxuri i fiiere.

#include <iostream.h>
#include <process.h>
#include <fstream.h>
void semn_er(char *c)
{ cerr<<"\n\n Eroare la deschiderea fisierului "<<c<<endl;exit(1); }
void copiere(ofstream &dest, ifstream &sursa)
{char C;
while (dest && sursa.get(C))
dest.put(C); }
void main()
{char nume_sursa1[14], nume_sursa2[14], destinatie[14];
ifstream f1, f2; ofstream dest;
cout<<"Numele celor 3 fisiere:"<<"Destinatie Sursa1 Sursa2\n";
cin.read(destinatie,13);cin.read(nume_sursa1,13);cin.read(nume_sursa2,13);
destinatie[13]=nume_sursa1[13]=nume_sursa2[13]='\0';
f1.open(nume_sursa1, ios::nocreate);
if (!f1) semn_er(nume_sursa1); //utiliz operator ! redefinit
f2.open(nume_sursa2, ios::nocreate);
if (!f2) semn_er(nume_sursa2); //utiliz operator ! redefinit
dest.open(destinatie);
if (!dest) semn_er(destinatie); //utiliz operator ! redefinit
copiere (dest, f1); copiere(dest, f2);
f1.close();f2.close();dest.close();
}

217
CAPITOLUL 13 Intrri/ieiri
Exerciiu: Se ilustreaz folosirea fluxurilor pentru operaii de citire/scriere n fiiere text.

#include <fstream.h>
#include <iostream.h>
void main()
{ ofstream fisierout("nou.txt"); // Deschide fisierul text nou.txt..
fisierout << " Teste fisiere "; //Scrie un text in fisier
fisierout.close(); // Inchide fisierul.
// Deschide un alt fisier text si scrie in acesta niste numere (numerele sunt separate prin spatii)
fisierout.open("numere.txt"); fisierout <<15<<" "<<42<<" "<<1;fisierout.close();
// Deschide fisierul nou.txt pentru citire.
ifstream fisierin; fisierin.open("nou.txt");
char p[50]; // Stabileste o zona de memorie folosita pentru citirea textului.
fisierin >>p; // Citeste si afiseaza primele doua cuvinte din fisier.
cout <<p<<" "; fisierin >>p; cout <<p<<endl;
fisierin.close(); // Inchide fisierul.
int numar; fisierin.open("numere.c");
// Deschide fisierul text numere.c pentru citirea numerelor intregi
// Citeste numere din fisier pana cand ajunge la sfarsitul fisierului.
while (!fisierin.eof())
{fisierin >> numar; // Citeste un numar intreg.
if (!fisierin.eof()) cout<<numar<<endl;
// Daca nu a ajuns la sfarsitul fisierului afiseaza numarul.
}
fisierin.close(); // Inchide fisierul.
// se citeste textul din fisierul nou.txt cuvant cu cuvant.
fisierin.open("nou.txt");
while (!fisierin.eof()) // Citeste cuvinte din fisier pana ajunge la sfarsitul fisierului.
{ // Citeste cuvant cu cuvant.
fisierin >>p; cout <<p<<endl;
}
}

13.8. FIIERE BINARE

Fiierele binare reprezint o succesiune de octei, asupra crora la intrare sau la ieire nu se realizeaz nici o
conversie. Ele sunt prelucrate binar, spre deosebire de exemplul anterior, n care prelucrarea se realiza n
mod text (un numr n format intern este reprezentat binar, dar n format extern el apare ca un ir de
caractere. Un ir n formatul extern are terminatorul '\n', iar n format intern are terminatorul '\0'). Deoarece
nu exist un terminator de linie, trebuie specificat lungimea nregistrrii. Metodele write, read nu
realizeaz nici o conversie.

Metoda write scrie n fiier un numr de n octei:


ostream &write(const char * tab, int n);
Metoda read citete din fiier n octei.
istream &read (const char * tab, int n);

Limbajul C++ ofer (ca i limbajul C) posibilitatea de acces direct ntr-un fiier conectat la un flux de date.
Dup fiecare operaie de citire (extragere din fluxul de intrare) sau citire (inserie n fluxul de ieire),
pointerul care indic poziia curent n fluxul de date este incrementat cu un numr egal cu numrul de octei
transferai. n aceast situaie se realizeaz un acces secvenial (ca n cazurile precedente).

Clasele ifstream i ofstream au ca metode funciile seekg (membr a clasei istream), respectiv
seekp (membr a clasei ostream) care permit modificarea valorii pointerului.
istream & seekg(long);
istream & seekg(long, seek_dir);

218
CAPITOLUL 13 Intrri/ieiri
ostream & seekp(long);
ostream & seekp(long, seek_dir);

Ambele metode primesc doi parametri:


un ntreg reprezentnd deplasarea pointerului n raport cu baza (referina) precizat de al doilea
parametru;
o constant ntreag care precizeaz baza. Valorile constantei sunt definite n clasa ios:

class ios{ //. . .


public:
enum seek_dir{
beg=0, deplasare fa de nceputul fiierului (implicit)
cur=1, deplasare fa de poziia curent
end=2 deplasare fa de sfritul fiierului
};
};

Pentru aflarea valorii pointerului, clasa ifstream are metoda tellg, iar clasa ofstream are metoda
tellp, cu prototipurile:
long istream::tellg();
long ostream::tellp();

Exemplu: Se creaz ierarhia de clase din figura 13.5., n care se implemen-


teaz clasa student i clasa proprie fisier_stud, clas class fstream
derivat din fstream. n acelai fiier, binar,
se realizeaz i scrierea i citirea. clase prietene
Datorit posibilitii de acces direct,
class student class fisier_stud
se pot modifica informaiile referitoare
la studentul nregistrat n fiier pe poziia k.
Figura 13.5. Ierarhia de clase
#include <fstream.h>
#include <iomanip.h>
class student
{ char nume[20];
int grupa, note[3];
public:
void citire_date();
friend ostream &operator<<(ostream &, const student &);
friend class fisier_stud;
};

class fisier_stud:public fstream //fiier binar cu obiecte din cls student


{public:
fisier_stud(){;};
fisier_stud(const char*num_f,int mod,int
protecie=filebuf::openprot):fstream(num_f,mod |ios::binary,protecie){}
void open(const char *num_f, int mod, int protectie=filebuf::openprot)
{fstream::open(num_f,mod|ios::binary,protectie);}//apelul met. open din cls. fstream
int citeste_f(student &);
int scrie_f (const student &);
};

void student::citire_date()
{ int gr, OK;
for (int k=0; k<21; k++) nume[k]=0;
cin.ignore(1000, '\n'); cout<<"Numele studentului:";
cin.get(nume, 21);cin.ignore(1000, '\n');
do{

219
CAPITOLUL 13 Intrri/ieiri
cout<<"Grupa:"; cin>>gr; OK=(cin && gr>0 && gr<8000);
if (!OK){
cout<<"Eroare. Repetai introducerea!\n"; cin.clear(); }
else {grupa=gr; cin.ignore(1000, '\n');}
}while (!OK);
for (int k=0; k<3; k++){
int n;
do{
cout<<"nota "<<k+1<<":"; cin>>n; OK=cin && n>0 && n<=10;
if (!OK){
cout<<"Nota gresit.Repetati!\n";cin.clear();cin.ignore(1000, '\n');
}
}while (!OK);
note[k]=n;cin.ignore(1000, '\n');
}
}
ostream &operator << (ostream &ies, const student &stud)
{ies<<"Student:"<<stud.nume<<" Grupa:"<<stud.grupa<<" Note:";
for (int k=0; k<3; k++) ies<<stud.note[k]<<' ';
ies<<endl;return ies;}

typedef union {student s; char sbin[sizeof(student)];} stud;

int fisier_stud::scrie_f(const student &s)


{stud s1; s1.s=s; write(s1.sbin, sizeof(student)); return bad(); }

int fisier_stud::citeste_f(student &s)


{stud s1; read(s1.sbin, sizeof(student)); s=s1.s; return bad();}

main()
{char Nume_Fis[]="Stud_bin.bin"; student s; fisier_stud fs; int gata;
//deschidere fiier ptr. scriere
fs.open (Nume_Fis, ios::out);
if (!fs){
cout<<"eroare la deschiderea fiierului "<<Nume_Fis<<" ptr. scriere\n";
return 1;}
cout<<"Poz. n fi la deschidere:"<<fs.tellp()<<endl; gata=0;
while(!gata)
{char rasp;
cout<<"Datele studentului:\n";s.citire_date();cout<<"Date introduse:"<<s<<endl;
do{
cout<<"Scriei date n fiier [D|N] ?";
rasp=toupper(cin.get());cin.ignore(1000, '\n');
} while (rsp!='D' && rsp!='N');
if (rsp == 'D'){
fs.scrie_f(s); cout<<"Poz. n fiier: "<<fs.tellp()<<endl;}
do{
cout<<"Continuai introducerea [D|N]?";rsp=toupper(cin.get());
cin.ignore(1000, '\n');
} while (rsp!='D' && rsp!='N');
if (rsp=='N') gata=1;
}
fs.close();
//citire
fs.open(Nume_Fis, ios::in);
if (!fs){
cout<<"Eroare la deschiderea fi-lui "<<Nume_Fis<<" ptr. citire\n";
return 1; }
cout<<"Poz. n fi la deschidere:"<<fs.tellg()<<endl;
cout<<"Date citite din fiier:\n"; int k=0;
while (!fs.eof())
{ fs.citete_f(s);

220
CAPITOLUL 13 Intrri/ieiri
if (!fs && !fs.eof()){ cout<<"Eroare la citire\n";return 1; }
if (!fs.eof()){cout<<s<<endl;cout<<"Poz n fiier:"<<fs.tellg();
cout<<endl;k++;}
}
cout<<"S-au citit din fiier:"<<k<<" studeni\n";
fs.close();

fs.open(Nume_Fis, ios::in | ios::out); //deschidere fisier actualizare (intr/ies)


if (!fs){
cout<<"Eroare la deschidere fis. "<<Nume_Fis<<" ptr. citire/ scriere\n";
return 1;
}
cout<<"Dai numrul stud-lui pentru care vrei s inlocuii datele:";cin>>k;
cin.ignore(1000, '\n'); fs.seekg(k*sizeof(stud));s.citire_date();fs.scrie_f(s);
fs.seekg(0); k=0;
while(!fs.eof()){
fs.citire_f(s);
if (!fs && !fs.eof()){cout<<"Eroare la citirea din fi:"<<Nume_Fis<<endl;
return 1; }
if (!fs.eof()){
cout<<s<<endl;cout<<"Poz n fiier:"<<fs.tellg()<<endl;k++;}
}
cout<<"S-au gasit n fiier:"<<k<<" studeni\n";
fs.close();
return 0;
}

NTREBRI I EXERCIII

Chestiuni teoretice

1. Ce nelegei prin conceptul de stream? 3. Ce sunt manipulatorii?


2. Care considerai c ar fi avantajele utilizrii 4. Cum i poate crea utilizatorul manipulatorii
abordrii orientate pe obiecte a sistemului de proprii?
I/O?

Chestiuni practice

Rezolvai problemele din capitolul 8, folosind abordarea orientat pe obiecte.

221

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