Tartalom
Az alábbi feladatokban egyszerű, C# alaptípusból alkotott listákkal, majd rekordokat tartalmazó listák feltöltésével kapcsolatos feladatokkal foglalkozunk.
15.1. feladat (Feltöltés billentyűzetről N elemszámra – szint: 1). Egy törtszámokat tartalmazó listát töltsünk fel billentyűzetről oly módon, hogy a program kezelője a program elején megadja, hogy hány elemre lehet számítani(n), majd beírja az n számú törtértéket! A program a bevitel közben mindig írja ki, hogy hányadik számnál tart a bevitel, és mennyi van még hátra! A program a bevitel végén írja vissza az adatokat a képernyőre, a számokat egymás mellé írva, szóközzel elválasztva, majd adja meg a számok átlagát!
Magyarázat: A feladat egy egyszerű ciklussal megoldható, lényegében problémamentes. Ha valaki jobb minőségű kódot szeretne készíteni, legfeljebb arra kell ügyelnie, hogy a beírt szám valóban tört alakú legyen. Tudni kell, hogy magyar területi beállítások mellett a Double.Parse a törtszámokban a tizedesvessző megjelenésére számít, és nem a tizedespontra. A bekérésben esetleg előforduló tizedespontot vesszőre tudjuk cserélni a Replace metódus hívásával (a 15.1. forráskód).
15.2. feladat (Feltöltés billentyűzetről szám végjelig – szint: 1). Egy törtszámokat tartalmazó listát töltsünk fel billentyűzetről oly módon, hogy a program kezelője a program elején nem adja meg, hogy hány adat lesz! Helyette választunk egy speciális számértéket, például a 0.0 értéket. Amennyiben ezt a számot írnánk be, úgy a program fejezze be a bevitelt! A program a bevitel végén írja vissza az adatokat a képernyőre, a számokat egymás mellé írva, szóközzel elválasztva, majd adja meg a számok átlagát!
Magyarázat: A vége jel kezelése egy középen tesztelős ciklussal a leglátványosabb,
legegyszerűbb. Ismert tény, hogy sokan ódzkodnak a középen tesztelős ciklustól, a break
használatától. Megpróbálhatjuk megírni ezt a ciklust is akár elöl tesztelős, akár hátul
tesztelős tisztán logikai ciklussal, amelyben nincs break, de azt fogjuk találni, hogy a kilépési tesztet
x==0.0
kétszer is be kell írnunk. Ekkor pedig kitörhet a lázadás a kódredundancia oldaláról. Nem
törünk lándzsát egyik megoldás mellett sem, és ellene sem foglalunk állást (egyfajta megoldást
lásd a 15.2. forráskódban).
15.3. feladat (Feltöltés billentyűzetről string végjelig – szint: 1). Egy törtszámokat tartalmazó listát töltsünk fel billentyűzetről oly módon, hogy a program kezelője a számok bevitelét egy speciális szöveggel zárja (pl. a „*” karaktert írja be, vagy begépeli, hogy „vége”)! A program a bevitel végén írja vissza az adatokat a képernyőre, a számokat egymás mellé írva, szóközzel elválasztva, majd adja meg a számok átlagát!
Magyarázat: Az előző feladat megoldása után ez sem jelenthet gondot, mindössze arra kell ügyelni, hogy a vége ellenőrzést a double.Parse előtt hajtsuk végre, mivel a különleges stringértékek nem parzolhatóak át számmá, kivétel dobásával leállna a program (lásd a 15.3. forráskód).
15.4. feladat (Feltöltés véletlen számokkal – szint: 1). Egy listát töltsünk fel véletlen egész számokkal oly módon, hogy a páros sorszámú listaelemek a
, a páratlan sorszámú listaelemek a
intervallumból kerüljenek ki! A listába kerüljön be n ilyen szám, az n értékét a program induláskor kérje be! A program a végén írja vissza az adatokat a képernyőre, a számokat egymás mellé írva, vesszővel elválasztva, majd adja meg a számok átlagát!
Magyarázat: Gyakori elvi hiba kezdő programozóknál, hogy nem egy, de több Random példányt is készítenek programjaikban. Tudnunk kell, hogy a Random példányok a véletlenszám-generáláshoz szükséges kezdőértéket a rendszerórából veszik át. Ezért a közel egy időben készült példányok egy kezdőértékről indulnak, ugyanazon véletlen számokat fogják előállítani (természetesen ha ugyanazon intervallumot használjuk). Különböző intervallumok használata sem indokolja a több Random példány jelenlétét a programban, mivel minden egyes véletlenszám-előállítás esetén külön-külön kell megadni a kívánt intervallumot. Ezért is egyetlen Random példányt érdemes használni végig a generálás során (15.4. forráskód).
Másrészről ügyelnünk kell az átlagszámításra, mivel itt már nem törtszámok, de egész
számok átlagáról van szó. Ekkor a korábban használt sum/n
nem fog helyes eredményt adni, ha
a sum típusa (és az n típusa is) egész szám. Nem érdemes sem a sum, sem az n típusát
másra választani, helyette explicit típuskonverziót kell használni az osztás elvégzésekor
(double)sum/n
(lásd 15.5. forráskód).
15.5. feladat (Feltöltés véletlen növekvő számokkal – szint: 1). Egy listát töltsünk fel véletlen egész számokkal oly módon, hogy az első listaelem a
intervallumba essen, a következő listalemek az őket megelőző elemtől legyenek „valamennyivel” nagyobbak, a különbség az
intervallumból kerüljön ki! A lista hosszát (n darab) a program induláskor kérje be! A program a végén írja vissza az adatokat a képernyőre, a számokat egymás mellé írva, vesszővel elválasztva, majd adja meg a számok átlagát!
Magyarázat: A lista első elemét megadott módon kell képezni. A következő elem értékének előállításához az előző értékből kell kiindulni, melyhez újabb random értéket kell adni. A feladat nem túl bonyolult, de eredménye nagyon értékes. Anélkül kaphatunk „rendezett”, véletlen számokat tartalmazó számsort, hogy rendezőalgoritmust kellene ismernünk! A megoldást lásd a 15.6. forráskódban.
15.6. feladat (Feltöltés fájlból (a) – szint: 1). Egy text fájl soronként egy törtszámot tartalmaz. Írjunk olyan programot, amely bekéri a fájl nevét, majd beolvassa a számokat a fájlból! A bevitel véget ér, ha a fájl minden sorát beolvastuk, vagy üres sort olvastunk be a fájlból. A program a bevitel végén írja vissza az adatokat a képernyőre, a számokat egymás mellé írva, vesszővel elválasztva, majd adja meg a számok átlagát!
Magyarázat: A fájlból beolvasást többször bemutattuk már. Mivel ennek során stringeket olvasunk be, az üres sor detektálása sem lehet problémás. Az üres sor felfedezéséhez egy jó minőségű megoldást mutatunk be a 15.7. forráskódban. Alkalmazzuk a beolvasott sorra a Trim függvényt (ez levágja a sor bevezető és záró white-space karaktereit), a kapott string hosszát vessük össze a 0-val!
15.7. feladat (Feltöltés fájlból (b) – szint: 1). Egy text fájl soronként egy vagy több törtszámot tartalmaz. Amikor több szám is szerepel egy sorban, akkor vesszővel vannak elválasztva. A vessző után szóközök is szerepelhetnek a jobb vizuális tördelés érdekében. Írjunk olyan programot, amely bekéri a fájl nevét, majd beolvassa a számokat a fájlból! A bevitel véget ér, ha a fájl minden sorát beolvastuk, vagy üres sort olvastunk be a fájlból. A program a bevitel végén írja vissza az adatokat a képernyőre, a számokat egymás mellé írva, vesszővel elválasztva, majd adja meg a számok átlagát!
Magyarázat: A beolvasott értékes sort a Split függvény segítségével vághatjuk fel a vessző karakter mentén törtszámokra. A darabokra alkalmazzuk a Trim függvényt, hogy a feladatban is említett felesleges szóközöket levágjuk. A kapott számokat adjuk hozzá a listához (15.8. forráskód)!
15.8. feladat (Feltöltés billentyűzetről listaszerűen – szint: 1). Egy egész számokat tartalmazó listát töltsünk fel billentyűzetről oly módon, hogy a program kezelője egy időben egyszerre több számot is beírhat, vesszővel elválasztva! Ekkor minden számot adjunk hozzá a listához! Ha csak egy számot írna be a kezelő, akkor azt az egy számot. A bevitelt akkor fejezzük be, ha a kezelő egyetlen számot sem ír be (üres string)! A program a bevitel végén írja vissza az adatokat a képernyőre, a számokat egymás mellé írva, vesszővel elválasztva, majd adja meg a számok átlagát!
Magyarázat: Az előző feladatban ismertetett módszer tökéletesen alkalmas ebben a feladatban is, csak a sor beolvasását ez esetben nem a fájlból, hanem billentyűzetről kell elvégezni (15.9. forráskód).
15.9. feladat (Feltöltés billentyűzetről összeghatárig – szint: 1). Egy egész számokat tartalmazó listát töltsünk fel billentyűzetről oly módon, hogy a program kezelője addig írhat be számokat, amíg azok összege el nem éri az előre megadott értéket (például 100)! A program a bevitel közben folyamatosan figyelje az összeghatárt, illetve mindig írja ki, hogy hányadik számnál tart a bevitel, hol tart az összeg, mennyi van még hátra az értékhatárig! A program a bevitel végén írja vissza az adatokat a képernyőre, a számokat egymás mellé írva, vesszővel elválasztva, majd adja meg a számok átlagát!
Magyarázat: A korábban ismertetett adatbekéréseket alapul vehetjük, mindössze a kilépés feltétele változik meg ez esetben (15.10. forráskód).
15.10. feladat (Feltöltés egyedi számokkal – szint: 1). Egy egész számokat tartalmazó listát töltsünk fel billentyűzetről oly módon, hogy a listába nem kerülhet be ugyanazon szám többször is! Ha a program kezelője olyan számot írna be, amely már volt, akkor a program ezt jelezze ki! A bevitelt a kezelő akkor fejezheti be, ha sikerült neki egymás után háromszor is olyan értéket beírni, amely még nem szerepelt korábban (amit a program elfogad). A program a bevitel végén írja vissza az adatokat a képernyőre, a számokat egymás mellé írva, vesszővel elválasztva, majd adja meg a számok átlagát!
Magyarázat: Olvassuk el figyelmesen a feladatot! Nem akkor kell befejezni az adatbevitelt, amikor a lista mérete eléri a 3-at (3 különböző számot tartalmaz), hanem amikor egymás után 3-szor sikeres adatbevitel történt. Érdemes bevezetni egy sikeres számlálót, melyet minden siker esetén növelünk 1-gyel, ha hibázunk, akkor lenullázzuk. A bevitel akkor fejeződik be, amikor a számláló eléri a 3-at.
A sikeresség ellenőrzéséhez érdemes kifejleszteni egy egyszerű függvényt, mely megadja a lista aktuális tartalma és egy új x érték esetén, hogy ez az x érték szerepel-e a listán vagy sem (15.11. forráskód). Ez alapján a főprogram már könnyen kialakítható (15.12. forráskód).
15.11. feladat (Fájlból két halmaz – szint: 2). Egy text fájl soronként egy vagy több törtszámot tartalmaz. Amikor több szám is szerepel egy sorban, akkor vesszővel vannak elválasztva. A vessző után szóközök is szerepelhetnek a jobb vizuális tördelés érdekében. A text fájl két számlistát tartalmaz, a két számlista között egy üres sor szerepel a fájlban. A program olvassa be mindkét számlistát két különböző listaváltozóba! Adjuk meg, melyik számlistában szereplő számoknak nagyobb az átlaga!
Magyarázat: A 15.7. feladat megoldása során bemutatott módszer alapján a feladat már szinte problémamentesen megoldható. Az üres sor első elérésekor nem kell leállni a beolvasáskor, hanem folytatni kell a második üres sor vagy a fájl végének eléréséig.
Trükkös megoldást alkalmazhatunk, ha jól uraljuk a referencia típust. Egy harmadik lista változót vezethetünk be, mely először az első listára mutat, majd váltáskor a második listára állunk át vele. Számoljuk az üres sorok számát is, de csak akkor lépünk ki a ciklusból, ha ez a számláló eléri a 2-t. A megoldást lásd a 15.13. forráskódban.
15.1. forráskód. Lista feltöltése billentyűzetről
List<double> szamok = new List<double>(); Console.Write("Hany szamrol lesz szo:"); int n = int.Parse(Console.ReadLine()); for (int i = 0; i < n; i++) { Console.Write("Kerem a {0}. szamot:", i + 1); string s = Console.ReadLine(); double d = double.Parse( s.Replace(’.’,’,’)); szamok.Add(d); } // foreach (double x in szamok) Console.Write("{0} ", x); Console.WriteLine(); // double sum = 0; foreach (double x in szamok) sum = sum+x; Console.WriteLine("Atlag={0}", sum / n);
15.2. forráskód. Lista feltöltése végjelig
List<double> szamok = new List<double>(); int i = 0; while (true) { Console.Write("Kerem a {0}. szamot:", i + 1); string s = Console.ReadLine(); double d = double.Parse( s.Replace(’.’,’,’)); if (d == 0.0) break; else szamok.Add(d); i++; }
15.3. forráskód. Lista feltöltése string végjelig
List<double> szamok = new List<double>(); int i = 0; while (true) { Console.Write("Kerem a {0}. szamot:", i + 1); string s = Console.ReadLine(); if (s == "*" || s == "vege") break; double d = double.Parse( s.Replace(’.’,’,’)); szamok.Add(d); i++; }
15.4. forráskód. Lista generálása
List<double> szamok = new List<double>(); Random rnd = new Random(); for(int i=0;i<n;i++) { if (i % 2 == 0) szamok.Add(rnd.Next(10, 51)); else szamok.Add(rnd.Next(40, 81)); }
15.5. forráskód. Egész számok átlaga
int sum = 0; foreach (int x in szamok) sum = sum+x; Console.WriteLine("Atlag={0}", (double) sum / n);
15.6. forráskód. Rendezett lista generálása
List<int> szamok = new List<int>(); Random rnd = new Random(); int x = rnd.Next(10, 31); for(int i=0;i<n;i++) { szamok.Add(x); x = x + rnd.Next(1, 6); }
15.7. forráskód. Lista feltöltése számokkal file-ból
List<double> szamok = new List<double>(); StreamReader f = new StreamReader(@"szamok.txt", Encoding.Default); while (f.EndOfStream == false) { string s = f.ReadLine(); if (s.Trim().Length==0) break; double d = double.Parse( s.Replace(’.’,’,’) ); szamok.Add( d ); } f.Close();
15.8. forráskód. A fájlban egy sorban több szám is szerepelhet
List<double> szamok = new List<double>(); StreamReader f = new StreamReader(@"szamok.txt", Encoding.Default); while (f.EndOfStream == false) { string s = f.ReadLine(); if (s.Trim().Length==0) break; string[] ss = s.Split(’,’); foreach(string p in ss) { double d = double.Parse( p.Trim().Replace(’.’,’,’)); szamok.Add( d ); } } f.Close();
15.9. forráskód. A beírt sorban több szám is szerepelhet
List<int> szamok = new List<int>(); while (true) { string s = Console.ReadLine(); if (s.Trim().Length==0) break; string[] ss = s.Split(’,’); foreach(string p in ss) { int d = int.Parse(p.Trim()); szamok.Add( d ); } }
15.10. forráskód. Adatbekérés összeghatárig
List<int> szamok = new List<int>(); int sum = 0; while (sum<100) { string s = Console.ReadLine(); if (s.Trim().Length==0) break; int d = int.Parse(s.Trim()); szamok.Add( d ); sum = sum + d; }
15.11. forráskód. Ellenőrző függvény: az x szerepel-e a listán
static bool szerepel_e(List<int> l, int x) { foreach (int d in l) if (d == x) return true; // return false; }
15.12. forráskód. Az adatbekérés főprogramja
List<int> szamok = new List<int>(); int siker = 0; while (siker<3) { string s = Console.ReadLine(); int d = int.Parse(s.Trim()); if (szerepel_e(szamok, d) == true) siker = 0; else { szamok.Add(d); siker++; } }
15.13. forráskód. Két számhalmaz beolvasása
List<double> szamok1 = new List<double>(); List<double> szamok2 = new List<double>(); List<double> akt = szamok1; StreamReader f = new StreamReader(@"szamok.txt", Encoding.Default); int ures_db = 0; while (f.EndOfStream == false) { string s = f.ReadLine(); if (s.Trim().Length == 0) { ures_db++; if (ures_db == 2) break; akt = szamok2; continue; } string[] ss = s.Split(’,’); foreach (string p in ss) { double d = double.Parse(p.Trim().Replace(’.’, ’,’)); akt.Add(d); } } f.Close();