Fișiere text
Până acum, toate programele noastre citeau date de la
tastatură (cin) și afișau
rezultate pe ecran (cout).
Dar la concursuri (inclusiv Olimpiada), datele se citesc dintr-un fișier și rezultatele se scriu în alt fișier.
De ce fișiere?
- La concursuri, evaluatorul nu tastează datele - le pune într-un fișier.
- Rezultatul tău trebuie să apară într-un fișier pe care evaluatorul îl verifică.
- Fișierele pot conține cantități mari de date, imposibil de tastat manual.
Ce avem nevoie?
Pentru a lucra cu fișiere în C++, folosim biblioteca
fstream:
#include <fstream>Aceasta ne oferă:
ifstream- pentru citire din fișier (input file stream)ofstream- pentru scriere în fișier (output file stream)
Citirea dintr-un fișier
Forma generală
#include <fstream>
using namespace std;
ifstream fin("date.in");
int main()
{
int x;
fin >> x;
return 0;
}Ce face fiecare linie?
ifstream fin("date.in");- deschide fișieruldate.inpentru citire. Se pune dupăusing namespace std;, ca variabilă globală.fin >> x;- citește o valoare din fișier, exact cacin >> x.
fin funcționează identic cu
cin, dar citește din fișier în loc
de tastatură. Tot ce știi despre cin se aplică și
la fin.
Scrierea într-un fișier
Forma generală
#include <fstream>
using namespace std;
ofstream fout("date.out");
int main()
{
fout << 42 << endl;
return 0;
}Ce face fiecare linie?
ofstream fout("date.out");- deschide (sau creează) fișieruldate.outpentru scriere. Se pune tot ca variabilă globală.fout << 42 << endl;- scrie în fișier, exact cacout.
fout funcționează identic cu
cout, dar scrie în fișier în loc
de pe ecran.
Structura standard a unui program cu fișiere
Aceasta este structura pe care o vom folosi mereu:
#include <fstream>
using namespace std;
ifstream fin("nume.in");
ofstream fout("nume.out");
int main()
{
// citim cu fin, scriem cu fout
return 0;
}Declarăm fin și fout
global, imediat după
using namespace std;. Așa sunt accesibile oriunde
în program.
Primul exemplu complet
Problema: citim două numere din numere.in și
scriem suma lor în numere.out.
#include <fstream>
using namespace std;
ifstream fin("numere.in");
ofstream fout("numere.out");
int main()
{
int a, b;
fin >> a >> b;
fout << a + b;
return 0;
}numere.in:
12 18numere.out:
30Citirea mai multor valori
La fel ca la cin, putem citi mai multe
valori:
fin >> a >> b >> c;Sau într-o buclă:
int n;
fin >> n;
for (int i = 1; i <= n; i++) {
int x;
fin >> x;
// prelucrăm x
}Exemplu: suma a n numere din fișier
suma.in:
5
3 7 2 9 4#include <fstream>
using namespace std;
ifstream fin("suma.in");
ofstream fout("suma.out");
int main()
{
int n;
fin >> n;
int suma = 0;
for (int i = 1; i <= n; i++) {
int x;
fin >> x;
suma = suma + x;
}
fout << suma;
return 0;
}suma.out:
25Exemplu: maximul din fișier
maxim.in:
6
3 8 2 15 4 7#include <fstream>
using namespace std;
ifstream fin("maxim.in");
ofstream fout("maxim.out");
int main()
{
int n;
fin >> n;
int x;
fin >> x;
int maxim = x;
for (int i = 2; i <= n; i++) {
fin >> x;
if (x > maxim) {
maxim = x;
}
}
fout << maxim;
return 0;
}maxim.out:
15Transformarea
unui program cu cin/cout în
fișiere
Regula este simplă - înlocuim:
| Tastatură/Ecran | Fișier |
|---|---|
#include <iostream> |
#include <fstream> |
cin >> x |
fin >> x |
cout << x |
fout << x |
Și adăugăm ifstream fin(...) și
ofstream fout(...) după
using namespace std;.
Exemplu - înainte (tastatură):
#include <iostream>
using namespace std;
int main()
{
int a, b;
cin >> a >> b;
cout << a + b;
return 0;
}După (fișiere):
#include <fstream>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");
int main()
{
int a, b;
fin >> a >> b;
fout << a + b;
return 0;
}Restul codului rămâne identic. Doar sursa și destinația datelor se schimbă.
Folosirea
ambelor: iostream și fstream
Poți folosi ambele simultan - de exemplu, citești din fișier dar afișezi și pe ecran (util la depanare):
#include <iostream>
#include <fstream>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");
int main()
{
int a, b;
fin >> a >> b;
int suma = a + b;
cout << "Suma este: " << suma << endl; // pe ecran (pentru tine)
fout << suma; // în fișier (pentru evaluator)
return 0;
}Sfat pentru concursuri
La OJI și alte concursuri, evaluatorul citește doar
fișierul de ieșire. Ce afișezi pe ecran cu
cout nu contează.
Poți folosi cout pentru a verifica rapid ce face
programul tău, dar nu uita să scrii rezultatul final în fișier
cu fout.
Numele fișierelor
- Numele fișierelor sunt date în enunțul problemei (ex:
date.in,date.out). - Trebuie scrise exact cum apar în enunț (cu litere mici, cu extensia corectă).
- Fișierul de intrare trebuie să existe deja (altfel programul nu poate citi).
- Fișierul de ieșire este creat automat dacă nu există.
Greșeli frecvente
1. Fișierul de intrare nu există
Dacă fișierul date.in nu se află în același
folder cu programul, citirea eșuează fără eroare vizibilă -
variabilele rămân neinițializate.
2. Confuzia între
ifstream și ofstream
ifstream= citire (input)ofstream= scriere (output)
Dacă le inversezi, programul nu funcționează.
3. Uitarea lui
#include <fstream>
Fără această bibliotecă, ifstream și
ofstream nu sunt recunoscute.
4. Numele greșit al fișierului
ifstream fin("Date.in"); // GREȘIT dacă fișierul e "date.in"Numele trebuie să fie exact - pe unele sisteme, literele mari și mici contează.
5. Declararea în
main() în loc de global
La concursuri, cel mai simplu este să declari
fin și fout global
(după using namespace std;). Așa nu trebuie să le
transmiți la funcții și sunt accesibile oriunde.
Ce să reții
- La concursuri, citim din fișier (
ifstream) și scriem în fișier (ofstream). - Declarăm
finșifoutglobal, imediat dupăusing namespace std;. finfuncționează cacin,foutfuncționează cacout.- Includem
#include <fstream>în loc de (sau pe lângă)#include <iostream>. - Transformarea e mecanică: înlocuim
cincufinșicoutcufout. - Fișierul de intrare trebuie să existe, cel de ieșire se creează automat.
- La Olimpiadă, numele fișierelor sunt date în enunț - trebuie scrise exact.