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.