De ce contează?
Imaginează-ți o bandă rulantă pe care cineva așază, pe rând, niște cartonașe cu numere scrise pe ele. Tu stai la capăt și iei cartonașele unul câte unul, în ordinea în care vin. Nu poți sări peste vreunul, nu poți lua două odată și — cel mai important — odată ce ai luat un cartonaș, el nu se mai întoarce pe bandă. Iei primul, apoi următorul, apoi următorul. Exact așa „citește” un program datele de la tastatură: ia valorile de pe o bandă invizibilă, în ordine, una după alta, fără drum înapoi.
Intuiția
Când rulezi un program, datele pe care le tastezi nu ajung direct în variabile. Ele intră mai întâi într-o zonă de așteptare numită fluxul de intrare (standard input). Acolo stau aliniate, în ordinea în care le-ai scris. Programul tău cere o valoare, iar fluxul i-o dă pe prima nefolosită. Cere încă una, primește următoarea. Tot ce afișezi pleacă pe un drum asemănător, fluxul de ieșire, și apare pe ecran.
Ideea-cheie pe care vrem să o prinzi: citirea nu „caută” valori prin tot ce ai tastat, ci doar consumă pe rând următoarea bucată din flux.
Ce este
În C++ folosim două obiecte din biblioteca <iostream>:
cin— fluxul de intrare standard. Cu operatorul>>extragem o valoare din el.cout— fluxul de ieșire standard. Cu operatorul<<trimitem o valoare spre ecran.
O linie de citire arată așa: cin >> n;. Se citește „ia din cin următoarea valoare și pune-o în n”. Săgețile >> arată chiar direcția în care „curg” datele: dinspre flux spre variabilă. La afișare, cout << n;, săgețile << arată că datele curg dinspre variabilă spre ecran.
Un detaliu important: >> sare automat peste spații albe (spațiu, tab, linie nouă) înainte de a citi. De aceea nu contează dacă scrii numerele separate prin spațiu sau pe linii diferite — fluxul le vede la fel: o coadă de „cuvinte” (token-uri) despărțite de spațiu alb.
Fluxul de intrare este ca o coadă la casă: are un singur capăt din care se servește, mereu primul de la rând. Fiecare >> ia exact un token și înaintează cursorul. Ce ai consumat o dată nu mai poți reciti — coada doar înaintează, niciodată nu dă înapoi.
Cum arată
Să spunem că la tastatură ai introdus aceste date, pe două linii:
3
10 20 30Pentru flux, liniile noi și spațiile sunt doar despărțitori. El vede o singură coadă de patru token-uri: 3, 10, 20, 30. Cursorul (^) arată următorul token care urmează să fie citit.
La început, înainte de orice citire, cursorul e la primul token:
3 | 10 | 20 | 30 |
t0 | t1 | t2 | t3 |
cursor |
Executăm cin >> n;. Operatorul ia token-ul 3, îl pune în n și mută cursorul mai departe:
3 | 10 | 20 | 30 |
t0 | t1 | t2 | t3 |
citit | cursor |
Acum citim al doilea număr cu cin >> x;. Se ia 10, restul rămân în coadă:
3 | 10 | 20 | 30 |
t0 | t1 | t2 | t3 |
citit | cursor |
Continuând la fel, următoarele două citiri consumă 20 și 30, iar coada rămâne goală — am terminat exact când token-urile s-au epuizat.
Observă că n (valoarea 3) ne spune câte numere urmează. Citim întâi acest contor, apoi extragem exact atâtea valori din restul cozii. De aici reiese direct programul: un >> pentru contor, apoi un >> repetat de n ori.
Implementare C++
Problema clasică: se citește n, apoi n numere întregi, și se afișează suma lor.
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n; // citim cate numere urmeaza
long long suma = 0; // long long ca sa evitam overflow la sume mari
for (int i = 0; i < n; i++) {
int x;
cin >> x; // citim al i-lea numar din flux
suma += x; // il adaugam la suma curenta
}
cout << suma << "\n"; // afisam rezultatul si trecem la linie noua
return 0;
}
// Pentru intrarea: 3
// 10 20 30
// programul afiseaza: 60Logica e fix banda rulantă din analogie: primul cin >> n ia contorul, apoi bucla cere de n ori următorul token și îl adună. Fluxul livrează valorile în ordine, indiferent dacă le-ai tastat pe o linie sau pe mai multe.
Refolosim aceeași variabilă x la fiecare pas pentru că, după ce am adunat o valoare la suma, nu mai avem nevoie de ea — o suprascriem cu următoarea.
endl față de caracterul de linie nouă
Ai două moduri de a trece la o linie nouă în afișare:
cout << suma << endl; // linie noua + golire (flush) a bufferului
cout << suma << "\n"; // doar linie noua, fara flushAmbele mută afișarea pe rândul următor. Diferența: endl forțează golirea bufferului (trimite imediat tot ce s-a acumulat spre ecran), iar "\n" doar inserează caracterul de linie nouă și lasă sistemul să golească bufferul când îi convine. Pentru programul tipic de concurs, unde afișezi multe linii, "\n" este mai rapid — flush-ul repetat al lui endl încetinește vizibil ieșirea când scrii sute de mii de rânduri. Folosește endl doar când chiar vrei golire imediată; altfel preferă "\n".
Greșeala numărul unu la începători: uiți să citești contorul n înainte de buclă, sau inversezi ordinea citirilor. Dacă scrii bucla care citește numerele înainte de cin >> n, primul număr „util” va fi de fapt înghițit drept contor, iar totul se decalează. Ține minte regula benzii rulante: token-urile vin într-o ordine fixă, iar fiecare >> ia exact următorul. Citește în program exact în ordinea în care valorile apar în flux — întâi n, apoi cele n numere.
A doua capcană: aduni într-un int în loc de long long. La n mare cu valori mari, suma poate depăși limita unui int (aproximativ două miliarde) și „se învârte” în negativ — un overflow tăcut care trece testele mici și pică pe cele mari.