Răspuns pe scurt
Pentru n elemente numerotate de la 0, parcurgerea folosește indicii de la 0 la n − 1 și condiția i < n. La i = n, testul este fals și corpul nu mai rulează. Condiția i <= n ar include și poziția n. Pentru n = 0, corpul nu se execută deloc.
La un vector cu cinci elemente numerotate de la 0, ultimul indice este 4. De aceea, bucla care pornește de la i = 0 folosește condiția i < n, unde n este numărul de elemente de parcurs. La i = n, corpul nu mai rulează.
Explicația este pentru liceenii aflați la primele lecții despre tablouri unidimensionale în C++. Folosim un tablou obișnuit, int a[5], numit adesea „vector” la școală. Tipul std::vector din biblioteca C++ este altceva.
Cum ajunge al cincilea element pe poziția 4?
Numerotarea începe cu 0. Pentru datele 3, 7, 2, 8 și 4, corespondența este:
| Elementul | Indicele i | Valoarea a[i] |
|---|---|---|
| primul | 0 | 3 |
| al doilea | 1 | 7 |
| al treilea | 2 | 2 |
| al patrulea | 3 | 8 |
| al cincilea | 4 | 4 |
Numerele 4 și 5 pot părea interschimbabile când te gândești la „al cincilea element”. Uită-te însă la ce scrii: int a[5] declară cinci elemente, iar a[4] îl accesează pe ultimul. Proiectul standardului C++, la definiția tablourilor, numerotează cele N elemente de la 0 la N − 1.
Un program pe care îl poți urmări de la început la sfârșit
#include <iostream>
int main() {
int a[5] = {3, 7, 2, 8, 4};
int n = 5;
int suma = 0;
for (int i = 0; i < n; ++i) {
std::cout << a[i] << ' ';
suma += a[i];
}
std::cout << std::endl << "Suma: " << suma << std::endl;
}
Programul afișează 3 7 2 8 4, apoi Suma: 24. Înainte de buclă, suma este 0. După fiecare element adunat, ea devine 3, 10, 12, 20 și 24.
De ce se oprește înainte să citească a[5]?
Urmărește chiar ultima trecere. La i = 4, testul 4 < 5 este adevărat: programul afișează a[4] și îl adună la sumă. Abia după aceea, ++i îl mărește pe i la 5.
Urmează un nou test. 5 < 5 este fals, deci nu se mai execută corpul. Faptul că i ajunge la 5 nu înseamnă că programul și citește a[5]. Condiția este verificată înaintea fiecărei treceri, așa cum arată regula instrucțiunii for.
Ce schimbă semnul egal din i <= n?
Cu i <= n, testul 5 <= 5 rămâne adevărat. Bucla ar încerca și citirea lui a[5], deși tabloul nostru se termină la a[4]. Limita este explicată și în documentația Microsoft despre tablouri.
Această citire are comportament nedefinit: limbajul nu garantează un rezultat. Programul poate părea că funcționează, poate afișa altceva sau se poate opri cu o eroare. Nu există o „valoare a lui a[5]” pe care să o treci în tabelul acestui exemplu. Regula accesului la un obiect este precizată în secțiunea despre indirectare din proiectul standardului.
Dacă începi de la i = 1 și păstrezi i < n, apare altă greșeală: citești doar pozițiile 1–4. Nu depășești tabloul, dar sari peste valoarea 3 de la poziția 0. Suma devine 21.
Cinci locuri disponibile, numai trei valori cerute
Schimbă în program doar int n = 5; în int n = 3;. Tabloul are tot cinci elemente. Bucla afișează însă numai 3 7 2 și calculează suma 12, fiindcă se oprește înainte de indicele 3.
a[3] există, dar este în afara porțiunii cerute. Când citești sau rezolvi o problemă, separă numărul de locuri rezervate de numărul de valori pe care trebuie să le prelucrezi. În acest program, n poate fi între 0 și 5, iar elementele citite au fost deja inițializate.
Dar dacă în caiet ai indicii de la 1 la n?
Convenția este posibilă dacă rezervi și locul cu indicele n. De pildă, int a[6] = {}; are pozițiile 0–5. Poți lăsa a[0] nefolosit și pune cinci valori pe pozițiile 1–5. Pentru ele, bucla pornește de la 1 și folosește i <= n, cu n = 5.
C++ păstrează numerotarea de la 0 a tabloului; tu alegi să nu folosești prima poziție. Verifică ce convenție urmează exercițiul înainte să copiezi condiția buclei.
Încearcă un singur element
Fără să rulezi, schimbă n în 1 și scrie ce se afișează. Bucla intră o dată, cu i = 0: vezi valoarea 3 și suma 3. La i = 1 se oprește. Poți repeta această verificare fără rezolvarea în față cu primele două valori.
Pentru o cerință în care schimbi primul și ultimul element dintre cele n folosite, indicii sunt 0 și n − 1, dacă n este mai mare decât 0. Tutorialul despre interschimbarea cu o variabilă auxiliară explică pasul următor: cum păstrezi valoarea pe care urmează să o înlocuiești.