E blokk · Tömbök, listák, Dictionary · 2. tananyag
Az E1-ben egyenként értük el az elemeket. A tömb ereje akkor jön elő, amikor egy ciklus megy végig rajta: ugyanaz a három sor dolgoz fel öt vagy ötszáz elemet. Ma megtanulod feltölteni, bejárni és feldolgozni a tömböt — és megismered a programozási tételeket, a tömbös feladatok bevált megoldási mintáit.
for-ral
(indexszel) és foreach-csel
(index nélkül), és tudod, mikor melyiket.A for ciklus változója (C4) pontosan azt a 0 … Length − 1 sort járja be, amit a tömb indexei:
int[] jegyek = new int[5]; for (int i = 0; i < jegyek.Length; i++) { jegyek[i] = Konzol.SzamotKer($"{i + 1}. jegy: ", 1, 5); }
jegyek.Length
áll, nem az 5-ös szám: így ha a tömb mérete változik, a ciklus magától
alkalmazkodik.i + 1-et mutatunk (ő
1-től számol), a tömbbe i-vel írunk.Módosítás ugyanígy — például minden jegy javítása eggyel, ha még nem ötös:
for (int i = 0; i < jegyek.Length; i++) { if (jegyek[i] < 5) { jegyek[i]++; } }
for (int i = 0; i < jegyek.Length; i++) { Console.WriteLine($"{i + 1}. jegy: {jegyek[i]}"); }
foreach (int jegy in jegyek) { Console.WriteLine(jegy); }
A foreach-t olvasd így: „a
jegyek minden egyes
jegy-ére hajtsd végre”. Nem használ indexet,
így túlcímzés (E3) sem fordulhat elő vele.
A jegy = 5; a foreach
törzsében fordítási hiba (CS1656). Ha az elemeket módosítani kell,
for kell:
jegyek[i] = 5;.
| Helyzet | Ciklus |
|---|---|
| minden elemet csak olvasni kell (kiírás, összeg, keresés) | foreach — rövidebb, nem lehet elcímezni |
| kell az index (sorszám kiírása, szomszédos elemek) | for |
| az elemeket módosítani kell | for |
| csak a tömb egy részét kell bejárni (pl. minden másodikat) | for |
Melyik ciklus való a feladathoz? Ha mindkettő természetes megoldás, azt jelöld.
A tömbös feladatok többsége néhány visszatérő mintára épül. Ezeket a magyar informatikaoktatás programozási tételeknek nevezi. A C4-es akkumulátor-mintából indulnak ki.
Összegzés — az elemek összege (és belőle az átlag):
int osszeg = 0; foreach (int jegy in jegyek) { osszeg += jegy; } double atlag = (double)osszeg / jegyek.Length;
Megszámlálás — hány elem teljesít egy feltételt:
int otosok = 0; foreach (int jegy in jegyek) { if (jegy == 5) { otosok++; } }
Maximumkiválasztás — a legnagyobb elem és a helye:
int maxIndex = 0; for (int i = 1; i < jegyek.Length; i++) { if (jegyek[i] > jegyek[maxIndex]) { maxIndex = i; } } Console.WriteLine($"A legjobb jegy: {jegyek[maxIndex]} ({maxIndex + 1}. helyen)");
Ha a keresés 0 kezdőértékkel indulna, és minden elem negatív lenne, a program hibásan 0-t adna eredményül. Ezért a kiindulópont az első elem, és a ciklus 1-ről indul. Minimumhoz ugyanez a minta, fordított hasonlítással.
Eldöntés — van-e legalább egy, a feltételnek megfelelő elem:
bool vanEgyes = false; foreach (int jegy in jegyek) { if (jegy == 1) { vanEgyes = true; break; // az első találat után felesleges tovább nézni } }
A break a
C6-ból
ismerős. Ha a találat helye is kell (keresés),
for-ral ugyanez, a
break előtt az index eltárolásával.
int[] eredeti = { 1, 2, 3 }; int[] masik = eredeti; masik[0] = 99; Console.WriteLine(eredeti[0]); // 99 — az eredeti is megváltozott!
Az int változó értékadáskor
másolódik
(D2).
A tömb másképp viselkedik: a változó nem magát a tömböt tárolja, hanem egy
hivatkozást (referenciát) rá. A
masik = eredeti a hivatkozást másolja, nem a
tömböt — a két név ugyanazt a tömböt éri el. Az ilyen
típusokat referenciatípusnak hívjuk; a H blokkban
részletesen tárgyaljuk.
Ha valódi másolat kell, új tömböt kell létrehozni, és elemenként átmásolni:
int[] masolat = new int[eredeti.Length]; for (int i = 0; i < eredeti.Length; i++) { masolat[i] = eredeti[i]; }
A tömb átadható paraméterként, és visszaadható visszatérési értékként:
int[] jegyek = Beolvas(5); Console.WriteLine($"Átlag: {Atlag(jegyek):F2}"); int[] Beolvas(int db) { int[] tomb = new int[db]; for (int i = 0; i < tomb.Length; i++) { tomb[i] = Konzol.SzamotKer($"{i + 1}. jegy: ", 1, 5); } return tomb; } double Atlag(int[] tomb) { int osszeg = 0; foreach (int elem in tomb) { osszeg += elem; } return (double)osszeg / tomb.Length; }
A referencia miatt fontos különbség van a D2-höz képest: ha a metódus a
kapott tömb elemeit módosítja, a változás a hívónál is
látszik. Egy void Nullaz(int[] tomb) metódus
tehát tényleg kinullázza a hívó tömbjét. Ez hasznos lehet, de legyen
szándékos — a metódus neve árulja el, ha módosít.
| Tünet | Mi történt? | Mit tegyél? |
|---|---|---|
CS1656: Cannot assign to 'jegy' because it is a 'foreach iteration variable' | a foreach változójának akartál értéket adni | módosításhoz for kell: jegyek[i] = … |
| a ciklus „eggyel többet” fut és kivétellel leáll | i <= jegyek.Length a feltétel | a feltétel i < jegyek.Length (E3) |
| a program csak 5 elemet kezel, pedig a tömb nagyobb | a ciklusfejben a szám szerepel: i < 5 | i < tomb.Length |
| a maximum 0 lesz, pedig minden elem negatív | a keresés 0 kezdőértékkel indult | kezdőérték az első elem, a ciklus 1-ről indul |
| az átlag egész szám (pl. 3 a 3,6 helyett) | egészosztás: osszeg / tomb.Length | (double)osszeg / tomb.Length (B3) |
| a „másolat” módosítása az eredetit is megváltoztatja | masik = eredeti csak a hivatkozást másolja | új tömb + elemenkénti másolás (4. szakasz) |
Jegynaplo, .NET 10 +
Konzol.cs.int[] Beolvas(int db) metódust, amely
feltölti a tömböt 1–5 közötti jegyekkel.double Atlag(int[] t),
int Megszamol(int[] t, int jegy),
int LegjobbIndex(int[] t),
bool VanBenne(int[] t, int jegy).string.Join),
az átlagot két tizedessel, az ötösök számát, a legjobb jegyet és a
helyét, és azt, hogy van-e egyes (pirossal, ha igen).Jegynaplo: tombok es programozasi tetelek.Az 5, 3, 4, 5, 1 jegyekre az átlag 3,60, két ötös van, a legjobb jegy 5 (az 1. helyen), és a program jelzi az egyest.
⭐ alap · ⭐⭐ haladó · ⭐⭐⭐ kihívás
Tölts fel egy 10 elemű tömböt 1-től 10-ig a számok négyzetével
(1, 4, 9, …) ciklussal, és írd ki foreach-csel.
Egy tömbben a hét napi lépésszámai vannak. Írd ki az összes lépést és a napi átlagot.
Kérj be 6 hőmérsékletet egy tömbbe, és írd ki a legalacsonyabbat és azt, hányadik napon volt.
Írj int[] Megfordit(int[] t) metódust,
amely új tömbben adja vissza az elemeket fordított sorrendben. Az
eredeti tömb ne változzon — ellenőrizd kiírással!
Egy tömbben egy dolgozat pontszámai vannak (0–100). Írd ki, hány diák kapott jelest, jót, közepest, elégségest és elégtelent (a C7.1 ponthatárai szerint) — egyetlen bejárással.
Minden kérdésnél egy válasz helyes. A végén pontszámot kapsz.
| Fogalom | Jelentés |
|---|---|
| bejárás | a tömb összes elemének sorra vétele ciklussal |
foreach | index nélküli bejárás; a ciklusváltozó csak olvasható |
| programozási tétel | bevált megoldási minta tömbös feladatokra (összegzés, megszámlálás, maximumkiválasztás, eldöntés, keresés) |
| összegzés | az elemek összegének kiszámítása akkumulátorral |
| megszámlálás | a feltételnek megfelelő elemek számának meghatározása |
| maximumkiválasztás | a legnagyobb elem (és helyének) megkeresése |
| eldöntés | annak megállapítása, van-e a feltételnek megfelelő elem |
| referenciatípus | a változó hivatkozást tárol, nem magát az adatot — ilyen a tömb |
for (int i = 0; i < t.Length; i++).foreach
rövidebb és biztonságosabb — a ciklusváltozója nem írható.