Citirea datelor din fișier

Bază~13 min3 pași

De ce contează?

La OJI sau ONI, programul tău nu vorbește cu un om — primește date dintr-un fișier text și trebuie să scrie rezultatul în alt fișier. Dacă citești de la tastatură în loc de fișier, obții 0 puncte chiar dacă algoritmul e perfect. Fișierele sunt regula numărul unu a concursului.

De ce fișiere la concurs?

Judecătorul automat (graderul) rulează programul tău cu date de test pregătite dinainte. Nu poate tasta nimic — trimite datele printr-un fișier .in și citește rezultatul din .out. Fără fișiere, programul tău nu primește niciun input și nu produce niciun output evaluat.

Convenție standard la olimpiadele românești:

Date intrare:  problema.in
Date iesire:   problema.out

Metoda 1 — ifstream (recomandată)

ifstream (input file stream) este clasa C++ dedicată citirii din fișiere. Deschizi fișierul o dată, apoi citești din el exact ca din cin.

#include <iostream>
#include <fstream>
using namespace std;

int main() {
    ifstream fin("suma.in");   // deschide fisierul pentru citire

    int n, x;
    fin >> n;                  // citim n din fisier
    long long suma = 0;
    for (int i = 0; i < n; i++) {
        fin >> x;
        suma += x;
    }

    cout << suma << endl;      // scriem la consola (pentru acum)
    fin.close();               // optional: se inchide automat la final
    return 0;
}

Operatorul >> funcționează identic cu cin >> — sare peste spații și newline-uri, indiferent cum sunt aranjate datele în fișier.

Metoda 2 — freopen (mai scurtă)

freopen redirecționează stdin — sursa din care citește cin — spre un fișier. Tot codul rămas folosește cin ca de obicei, fără nicio altă modificare.

#include <iostream>
using namespace std;

int main() {
    freopen("suma.in", "r", stdin);  // redirecteaza cin spre fisier

    int n, x;
    cin >> n;
    long long suma = 0;
    for (int i = 0; i < n; i++) {
        cin >> x;
        suma += x;
    }

    cout << suma << endl;
    return 0;
}

Avantajul față de ifstream: dacă ai deja un program care citește cu cin, adaugi o singură linie în loc să înlocuiești fiecare cin cu fin.

Observația-cheie

La concurs, fișierul .in trebuie să fie în același director cu executabilul. Pe grader asta e automat. Local, pune suma.in lângă suma.cpp (sau în folderul unde rulezi programul din IDE).

Citire până la sfârșitul fișierului (EOF)

Unele probleme nu specifică câte valori urmează — citești până se termină fișierul:

int x;
while (fin >> x) {   // returneaza false la EOF
    suma += x;
}

Expresia fin >> x returnează false în momentul în care nu mai sunt date de citit. Bucla se oprește singură, corect, fără iterații în plus.

Complexitate

Citirea din fișier are aceeași complexitate ca citirea de la tastatură — O(1) per valoare, O(n) pentru n valori. Nu există penalizare de viteză față de cin.

Greșeli frecvente

Greșeala 1: Deschizi fișierul cu ofstream în loc de ifstream. ofstream e pentru scriere — îl golește și creează un fișier gol. Datele tale dispar.

Greșeala 2: Greșești numele fișierului ("Suma.in" vs "suma.in"). Linux (unde rulează graderul) e case-sensitive. Scrie exact cum specifică enunțul.

Greșeala 3: Nu verifici dacă fișierul s-a deschis cu succes. if (!fin) { ... } îți spune dacă fișierul lipsește — util la debug local, când nu înțelegi de ce programul nu citește nimic.

Greșeala 4: Folosești freopen și uiți că cin e acum redirecționat — nu mai poți citi de la tastatură în același program.

Întrebarea 1 / 3

La OJI/ONI, datele de intrare vin din: