Ultima problemă de la BAC informatică — itemul 3 din Subiectul III — pornește aproape întotdeauna de la un fișier text: „Fișierul bac.txt conține…”. Ca să iei punctele de acolo, trebuie să deschizi corect fișierul, să citești datele în ordinea în care sunt scrise și, uneori, să scrii rezultatul în alt fișier. Partea bună: în C++, cu ifstream și ofstream, lucrul cu fișierele seamănă aproape perfect cu cin și cout.
Biblioteca fstream și cele două tipuri de fluxuri
Ai nevoie de #include <fstream>. De acolo folosești două tipuri:
ifstream(input file stream) — pentru citirea dintr-un fișier;ofstream(output file stream) — pentru scrierea într-un fișier.
Declararea deschide și fișierul, dacă îi dai numele:
ifstream f("bac.txt");
ofstream g("rezultat.txt");
Din acest moment, f se folosește exact ca cin, iar g exact ca cout: f >> n; citește un număr, g << s << '\n'; scrie o valoare și trece la linia următoare. Numele variabilelor (f, g, fin, fout) le alegi tu. Numele fișierului, în schimb, trebuie să fie exact cel din enunț — inclusiv extensia.
La final poți închide fișierele cu f.close(); și g.close();. Ele se închid oricum automat la terminarea programului, dar e un obicei bun, mai ales pentru fișierele în care scrii.
Citirea unui număr cunoscut de valori
Cel mai simplu format: pe prima linie se află n, iar pe a doua n numere naturale. Programul de mai jos citește datele și afișează pe ecran suma numerelor pare:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream f("bac.txt");
int n, x, s = 0;
f >> n;
for (int i = 1; i <= n; i++)
{
f >> x;
if (x % 2 == 0) s = s + x;
}
cout << s;
f.close();
return 0;
}
Dacă fișierul conține 5 pe prima linie și 3 8 10 7 4 pe a doua, se afișează 22. Observă că nu am memorat numerele într-un vector: fiecare e prelucrat imediat după citire. La problemele de eficiență, asta face diferența la punctajul pentru memorie.
Operatorul >> sare automat peste spații, tab-uri și linii noi. Prin urmare, nu contează dacă numerele sunt pe aceeași linie sau pe linii diferite — le citești la fel.
Citirea unei matrice din fișier
Pe prima linie se află n și m, iar pe următoarele n linii câte m numere. Citirea e cea din cin, cu f în loc de cin:
int a[101][101], n, m, i, j;
f >> n >> m;
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
f >> a[i][j];
Scrierea în fișier
Unele enunțuri cer ca rezultatul să fie scris într-un fișier, nu afișat pe ecran. Scrii la fel ca pe ecran, doar că folosești fluxul de ieșire. Exemplu: din numere.in (care conține n și apoi n numere) se scriu în numere.out numerele divizibile cu 3, câte unul pe linie:
#include <fstream>
using namespace std;
int main()
{
ifstream fin("numere.in");
ofstream fout("numere.out");
int n, x;
fin >> n;
for (int i = 1; i <= n; i++)
{
fin >> x;
if (x % 3 == 0) fout << x << '\n';
}
fin.close();
fout.close();
return 0;
}
Atenție: ofstream golește fișierul la deschidere. Dacă fișierul de ieșire există deja, conținutul vechi se pierde.
Citirea textelor din fișier
Pentru cuvinte, f >> s (cu s de tip char[]) citește un cuvânt, oprindu-se la primul spațiu. Pentru o linie întreagă folosești f.getline(s, 256), unde 256 este dimensiunea tabloului.
Capcana clasică apare când amesteci cele două: dacă fișierul are pe prima linie un număr și pe a doua un text, după f >> n cursorul rămâne înaintea caracterului de linie nouă. Un getline imediat după ar citi o linie vidă. Soluția este să consumi acel caracter:
f >> n;
f.get(); // consumă '\n' de după n
f.getline(s, 256); // acum citește linia a doua
Cum arată de obicei cerința de la Subiectul III
Itemul 3 din Subiectul III (în modelul actual, 10 puncte: 2 pentru descrierea algoritmului, 8 pentru program — verifică întotdeauna ultimul model oficial pe subiecte.edu.ro) are de regulă această structură: fișierul conține un șir de numere, adesea foarte multe (de ordinul sutelor de mii sau al milioanelor), iar tu trebuie să afișezi pe ecran un rezultat care se poate calcula printr-o singură parcurgere. De multe ori nici nu se dă numărul de valori, așa că citești până la sfârșitul fișierului, cu while (f >> x) — tehnică pe care o explicăm separat.
Din punctul de vedere al fișierelor, lucrurile care îți aduc sau îți iau puncte sunt simple: biblioteca inclusă, fluxul declarat cu numele corect, citirea în ordinea din enunț și afișarea în locul cerut (ecran sau fișier).
cout; dacă spune „se scrie în fișierul…”, folosești un ofstream. Un rezultat corect scris în locul greșit poate costa puncte.Greșeli frecvente
- Lipsește
#include <fstream>, iar programul nu se compilează. - Numele fișierului greșit: „bac.txt” nu e același lucru cu „Bac.txt” sau „bac.in”.
- Citirea cu
cinîn loc def— o scăpare din grabă, după ce ai scris zeci de programe cu tastatura. - Folosirea
ifstreampentru scriere sau invers: un flux de citire nu acceptă<<. - Ordinea citirii diferită de ordinea din fișier, de exemplu m înainte de n.
De reținut
- ●
#include <fstream>;ifstream f("nume")pentru citire,ofstream g("nume")pentru scriere. - ●
f >> xfuncționează cacin >> xși sare peste spații și linii noi. - ● Numele fișierului se scrie exact ca în enunț.
- ● După
f >> n, foloseștef.get()înainte def.getline. - ● Prelucrează valorile pe măsură ce le citești, fără să le memorezi inutil.