Până acum am creat șiruri și am accesat elemente individuale ale acestora. Dar, nu prea are rost să grupăm elemente împreună dacă nu le și folosim împreună. În cadrul acestui episod vom vedea cum putem folosi întregul șir.
În majoritatea operațiilor cu șiruri pe care le folosim trebuie să lucrăm cu fiecare element al șirului. Spunem că parcurgem, traversăm sau iterăm elementele șirului respectiv.
Traversarea clasică
Să presupunem că avem un șir și dorim să calculăm suma elementelor sale. Vom crea o funcție care va primi ca parametru un șir și numărul elementelor acestuia și va returna suma acestor elemente.
Pentru a parcurge șirul vom folosi o variabilă care va avea valori cuprinse între 0 și n - 1, unde n este numărul elementelor șirului. Cu ajutorul acesteia vom putea accesa fiecare element al șirului și le putem aduna. Funcția noastră ar putea fi următoarea:
1 2 3 4 5 6 7 8 9 |
private static int Suma(int[] sir, int n) { int suma = 0; for (int i = 0; i < n; i++) { suma += sir[i]; } return suma; } |
Observăm că instrucțiunea din linia 4 face ca variabila i să aibă, pe rând, valorile cuprinse între 0 și n - 1; apoi, în linia 4, prin sir[i] accesăm cel de-al i-lea element al șirului și adunăm la sumă valoarea respectivă. Pentru a calcula suma am folosit metoda prezentată la sfârșitul episodului XII (inițializarea cu 0 și adunarea succesivă a valorilor).
Acum, am putea efectua apeluri de genul:
1 2 |
System.Console.WriteLine(Suma(new int[] {1, 2, 3}, 3)); int s = Suma(new int[]{2457, 47}, 2); |
Proprietatea length
Este oarecum neplăcut că a trebuit să precizăm lungimea șirului. De fapt, e chiar riscant; putem greși destul de ușor. De exemplu, am putea folosi o valoare prea mică și atunci nu am mai aduna toate numerele sau am putea folosi o valoare prea mare și atunci am încerca să adunăm elemente care nu există. Puteți încerca să vedeți ce se întâmplă dacă efectuăm apelurile următoare:
1 2 |
System.Console.WriteLine(Suma(new int[] {1, 2, 3}, 2)); System.Console.WriteLine(Suma(new int[] {1, 2, 3}, 4)); |
Ne-am dori să putem calcula automat această valoare. Din fericire, array-urile au o proprietate care ne spune câte elemente conțin. Pentru a accesa o proprietate trebuie să precizăm variabila, urmată de un punct și de numele proprietății.
Proprietatea care conține numărul elementelor unui array este Length. Așadar, pentru a determina numărul elementelor șirului a, putem folosi a.Length.
Să încercăm acum să rescriem apelul:
1 2 |
int[] a = {1, 2, 3}; System.Console.WriteLine(Suma(a, a.Length)); |
Apelând în acest mod, evităm să greșim dimensiunea șirului, dar parcă ar fi mai bine ca funcția să știe să își determine singură numărul elementelor. Nici nu e prea greu să o modificăm; nu vom mai avea n ca parametru; îl vom calcula. Noua funcție ar putea fi:
1 2 3 4 5 6 7 8 9 |
private static int Suma(int[] sir) { int n = sir.length; int suma = 0; for (int i = 0; i < n; i++) { suma += sir[i]; } return suma; } |
Apelurile modificate sunt:
1 2 |
System.Console.WriteLine(Suma(new int[] {1, 2, 3})); int s = Suma(new int[]{2457, 47}); |
Dimensiunea unui șir este un număr și poate folosită oriunde este folosit un număr; nu trebuie nepărat să stocăm valoarea într-o altă variabilă. Putem scăpa de n cu totul:
1 2 3 4 5 6 7 8 9 |
private static int Suma(int[] sir) { int suma = 0; for (int i = 0; i < sir.Length; i++) { suma += sir[i]; } return suma; } |
Instrucțiunea for each
În exemplele de până acum am avut nevoie de toate elementele dintr-un șir. Pentru aceasta am folosit o variabilă care lua pe rând valorile tuturor indicilor posibil și apoi accesam elementele respective. Scenariul este atât de frecvent încât limbajul C# ne oferă o "scurtătură", așa-numita instrucțiune for each (în traducere, pentru fiecare).
Practic, vom preciza doar șirul cu care lucrăm și o variabilă care va conține, pe rând, valorile elementelor șirului respectiv. Numărul iterațiilor este dat de numărul elementelor șirului (dacă nu este întâlnită vreo instrucțiune care să întrerupă prematur execuția buclei: break, return sau altele pe care nu le-am prezentat încă).
Pentru a folosi noua instrucțiune vom scrie foreach (un singur cuvânt), urmat de o paranteză deschisă, declarația variabilei care va conține valorile, cuvântul in, un șir, o paranteză închisă și apoi instrucțiunea sau blocul de instrucțiuni care formează corpul buclei.
Putem rescrie funcția noastră astfel:
1 2 3 4 5 6 7 8 9 |
private static int Suma(int[] sir) { int suma = 0; foreach (int valoare in sir) { suma += valoare; } return suma; } |
Evident, tipul variabilei care va conține elementele șirului trebuie să fie același cu tipul acestor elemente.
Va urma
În cadrul episodului următor vom vedea că putem avea șiruri de șiruri.