Organizarea datelor de intrare și ieșire

Bază~14 min3 pași

De ce contează?

Algoritmul tău e perfect, dar citești datele în ordinea greșită sau scrii rezultatul într-un format nepotrivit — și tot primești 0. Formatul datelor contează la fel de mult ca logica. Înainte să scrii o linie de cod, citește enunțul de două ori și înțelege exact cum arată problema.in.

Structura tipică a unui fișier .in

Enunțurile românești folosesc câteva formate standard. Recunoaște-le din prima și știi imediat cum să citești.

Format 1 — n urmat de n valori:

5
3 7 1 9 2
int n; fin >> n;
for (int i = 0; i < n; i++) { fin >> v[i]; }

Format 2 — n și m pe prima linie, matrice pe liniile următoare:

3 4
1 2 3 4
5 6 7 8
9 0 1 2
int n, m; fin >> n >> m;
for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++)
        fin >> a[i][j];

Format 3 — perechi de valori până la EOF:

1 5
3 8
2 7
int a, b;
while (fin >> a >> b) {
    // proceseaza perechea
}

Format 4 — o singură valoare pe linie:

42
17
93
int x;
while (fin >> x) { ... }

Șablonul complet de concurs

Acesta e punctul de plecare pe care îl poți folosi la orice problemă OJI/ONI:

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

ifstream fin("problema.in");
ofstream fout("problema.out");

int main() {
    int n;
    fin >> n;

    // ... rezolva problema ...

    fout << rezultat << "\n";
    return 0;
}
Observația-cheie

Declararea fin și fout global (în afara lui main) e o practică comună la concurs — le poți folosi din orice funcție fără să le transmiți ca parametri. Nu e obligatoriu, dar simplifică codul când ai mai multe funcții.

ios::sync_with_stdio — citire mai rapidă

Pentru probleme cu foarte multe date (n = 10⁶ sau mai mult), adaugă la începutul lui main:

ios::sync_with_stdio(false);
cin.tie(nullptr);

Dezactivează sincronizarea cu scanf/printf și accelerează cin/cout de ~5–10×. Nu combina cu scanf/printf după ce activezi acest trick — comportamentul devine nedefinit.

Greșeli de format frecvente

Un spațiu în plus la finalul liniei poate face diferența dintre AC și WA pe unii graderi:

// GRESIT: spatiu in plus dupa ultimul element
fout << a << " " << b << " " << c << "\n";   // "1 2 3 "

// CORECT: spatiu doar intre elemente
for (int i = 0; i < n; i++) {
    if (i > 0) fout << " ";
    fout << v[i];
}
fout << "\n";
Greșeli frecvente

Greșeala 1: Amesteci fin >> cu getline(fin, ...). După fin >> n, cursorul rămâne chiar înainte de \n. Primul getline citește acel newline gol. Adaugă fin.ignore() între ele pentru a-l consuma.

Greșeala 2: Folosești while (!fin.eof()) în loc de while (fin >> x). Varianta cu eof() poate executa o iterație în plus cu date nedefinite după ultimul element valid.

Greșeala 3: Indecși inconsistenți: declari int v[n] indexat 0..n-1, dar citești cu for (i=1; i<=n; i++). Sau invers. Alege o convenție (0-based sau 1-based) și aplică-o uniform în tot programul.

Greșeala 4: Scrii endl în loc de "\n" în bucle mari. endl golește bufferul la fiecare apel — de 50–100× mai lent decât "\n" pentru output voluminos.

Întrebarea 1 / 3

Cum citești o linie întreagă de text (cu spații) dintr-un ifstream fin?