Documente Academic
Documente Profesional
Documente Cultură
Capitolul 13
Capitolul 13
Intrri/ieiri
INTRRI/IEIRI
13.1. Principiile de baz ale sistemului de
I/O din limbajul C++
13.2. Testarea i modificarea strii unui flux
13.3. Formatarea unui flux
13.3.1. Formatarea prin manipulatori
13.3.2. Formatarea prin metode
13.4.
13.5.
13.6.
13.7.
13.8.
Fluxuri din
clasa ostream
Memoria intern
Fluxuri din
clasa
ifstream
fiiere
Fluxuri din
clasa
ofstream
197
CAPITOLUL 13
Intrri/ieiri
Posibilitatea de a realiza operaii de I/O nu numai cu date de tipuri predefinite, ci i cu obiecte de tip
abstract.
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.
streambuf
ios
istream
ostream
fstreambase
strstreambase
iostream
ifstream
ofstream
fstream
filebuf
198
CAPITOLUL 13
Intrri/ieiri
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).
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:
void main()
{int a; double x; char sir[20];
cin>>a>>x>>ir;
cout<<a<<' '<<x<<endl;
cout<<sir<<endl;
}
Memorie intern
a
date de
intrare
x
sir
buffer cin
buffer cout
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.
199
CAPITOLUL 13
Intrri/ieiri
(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:
int state;
public:
enum io_state{
goodbit=0x00,
eofbit=0x01,
failbit=0x02,
badbit=0x04,
};
hardbit=0x08
};
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())
else
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 *();
200
CAPITOLUL 13
Intrri/ieiri
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.
201
skipws
left
right
adjustfield
internal
dec
oct
hex
showbase
showpoint
uppercase
basefield
showpos
scientific
fixed
unitbuf
floatfield
floatfield
CAPITOLUL 13
Intrri/ieiri
Aciune
Formateaz datele numerice n zecimal (activeaz bitul de conversie zecimal)
Formateaz datele numerice n hexa (activeaz bitul de conversie hexazecimal)
Formateaz datele numerice n octal (activeaz bitul de conversie octal)
Ignor caracterele "spaii albe" (activeaz bitul de salt peste spaiile albe)
Afieaz (insereaz) un caracter '\n' i elibereaz fluxul
Insereaz un caracter null, de sfrit de flux (\0)
Videaz (golete) buffer-ul, elibereaz fluxul
Intrare/
Ieire
I/O
I/O
Aciune
Stabilete baza de conversie
Atribuie valoarea 0 tuturor biilor indicai de argument,
202
CAPITOLUL 13
Intrri/ieiri
cout<<"b="<<dec<<b<<endl;
}
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:
203
CAPITOLUL 13
Intrri/ieiri
cout. setf (ios:: showpos | ios :: uppercase | ios:: internal)
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 ('#').
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.
CAPITOLUL 13
Intrri/ieiri
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.
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);
205
CAPITOLUL 13
Intrri/ieiri
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;
}
CAPITOLUL 13
Intrri/ieiri
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 propriuzise, 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 $).
#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;}
ifstream();
207
CAPITOLUL 13
Intrri/ieiri
208
CAPITOLUL 13
Intrri/ieiri
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);
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()
209
CAPITOLUL 13
Intrri/ieiri
{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();
}
// 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();
CAPITOLUL 13
Intrri/ieiri
nu exist un terminator de linie, trebuie specificat lungimea nregistrrii. Metodele write, read nu
realizeaz nici o conversie.
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);
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,
cur=1,
end=2
};
};
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 implemenclass fstream
teaz clasa student i clasa proprie fisier_stud, clas
derivat din fstream. n acelai fiier, binar,
clase prietene
se realizeaz i scrierea i citirea.
Datorit posibilitii de acces direct,
class fisier_stud
class student
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 &);
211
CAPITOLUL 13
Intrri/ieiri
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{
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));
int fisier_stud::citeste_f(student &s)
{stud s1;
read(s1.sbin, sizeof(student));
return bad();
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{
212
CAPITOLUL 13
Intrri/ieiri
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);
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?
2. Care considerai c ar fi avantajele utilizrii
abordrii orientate pe obiecte a sistemului de
I/O?
3. Ce sunt manipulatorii?
4. Cum i poate crea utilizatorul manipulatorii
proprii?
213
CAPITOLUL 13
Intrri/ieiri
Chestiuni practice
Rezolvai problemele din capitolul 8, folosind abordarea orientat pe obiecte.
214