Informatika érettségi 2006. Február
Elérkeztünk ahhoz az évhez, ahol valamiért 3db emelt szintű érettségi is volt. A feladat nehézsége az lehetett, hogy az adatokhoz időt kellett nyilvántartani. Ez volt az első érettségi, ahol komplex adattípussal kellett dolgozni.
A feladatkiírás
Egy új szolgáltatás keretében ki lehet kérni a napi telefonbeszélgetéseink listáját. A listát egy fájlban küldik meg, amelyben a következő adatok szerepelnek: hívás kezdete, hívás vége, hívott telefonszám. A hívás kezdete és vége óra, perc, másodperc formában szerepel.
6 15 0 6 19 0
395682211
9 58 15 10 3 53
114571155
A hívások listája időben rendezett módon tartalmazza az adatokat, és szigorúan csak egy napi adatot, azaz nincsenek olyan beszélgetések, amelyeket előző nap kezdtek vagy a következő napon fejeztek be. Továbbá az elmúlt időszak statisztikái alapján tudjuk, hogy a napi hívások száma nem haladja meg a kétszázat.
A telefonálás díjait a következő táblázat foglalja össze.
- A csúcsidő reggel 7:00:00-kor, a csúcsidőn kívüli időszak pedig 18:00:00-kor kezdődik. A díjazás számításakor az számít, hogy mikor kezdte az illető a beszélgetést. (Például: ha 17:55-kor kezdett egy beszélgetést, de azt 18:10-kor fejezte be, akkor is csúcsidőbeli díjakkal kell számlázni.)
- Minden megkezdett perc egy egész percnek számít.
- Minden telefonszám elején egy kétjegyű körzetszám, illetve mobil hívószám található.
- A mobil hívószámok: 39, 41, 71 kezdődnek, minden egyéb szám vezetékes hívószámnak felel meg.
A következő feladatokat oldja meg egy program segítségével! A programot mentse szamla néven!
- Kérjen be a felhasználótól egy telefonszámot! Állapítsa meg a program segítségével, hogy a telefonszám mobil-e vagy sem! A megállapítást írja ki a képernyőre!
- Kérjen be továbbá egy hívás kezdeti és hívás vége időpontot óra perc másodperc formában! A két időpont alapján határozza meg, hogy a számlázás szempontjából hány perces a beszélgetés! A kiszámított időtartamot írja ki a képernyőre!
- Állapítsa meg a hivasok.txt fájlban lévő hívások időpontja alapján, hogy hány számlázott percet telefonált a felhasználó hívásonként! A kiszámított számlázott perceket írja ki a percek.txt fájlba a következő formában!
perc telefonszám
- Állapítsa meg a hivasok.txt fájl adatai alapján, hogy hány hívás volt csúcsidőben és csúcsidőn kívül! Az eredményt jelenítse meg a képernyőn!
- A hivasok.txt fájlban lévő időpontok alapján határozza meg, hogy hány percet beszélt a felhasználó mobil számmal és hány percet vezetékessel! Az eredményt jelenítse meg a képernyőn!
- Összesítse a hivasok.txt fájl adatai alapján, mennyit kell fizetnie a felhasználónak a csúcsdíjas hívásokért! Az eredményt a képernyőn jelenítse meg!
Az adatstruktúra
A szöveges fájlban található sorok összetartozó adatokat tartalmaznak. A feladat megkönnyítése miatt érdemes egy modellt definiálni, amivel az adatokat kezeljük. Ezt egy külön fájlban elhelyezett Hivas osztályban definiáltuk.
public class Hivas
{
public TimeSpan Kezdete { get; set; }
public TimeSpan Vege { get; set; }
public double Percek
{
get { return Math.Ceiling((Vege - Kezdete).TotalMinutes); }
}
public string Telefonszam { get; set; }
public Hivas()
{
Telefonszam = string.Empty;
}
}
Az idő reprezentálására a keretrendszer által biztosított TimeSpan struktúrát használtuk, ami kiválóan alkalmas idő leírására. A Kezdete, Vege és a Telefonszam tulajdonságok majd a fájlból olvasódnak.
A Percek csak olvasható tulajdonság és egy adott hívás hosszát adja vissza percben (egész számra, felfelé kerekítve). Ez egy későbbi feladatban kell majd.
A megoldás
- Kérjen be a felhasználótól egy telefonszámot! Állapítsa meg a program segítségével, hogy a telefonszám mobil-e vagy sem! A megállapítást írja ki a képernyőre!
Az első feladat egy algoritmus leimplementálása, ami alkalmas arra, hogy megállapítsuk, hogy az adott szám mobiltelefonszám-e, vagy sem. A feladatkiírásból kiderül, hogy később szükségünk még lesz rá, ezért egy újrahasználható metódusként implementáltuk, amire hivatkozik az első feladat a megoldásában.
private bool MobilSzam(string szam)
{
return szam.StartsWith("39")
|| szam.StartsWith("41")
|| szam.StartsWith("71");
}
public void Feladat01()
{
Console.WriteLine("Kérek egy telefonszámot:");
string szam = Console.ReadLine();
if (MobilSzam(szam))
{
Console.WriteLine("Ez egy mobilszám");
}
else
{
Console.WriteLine("Ez nem mobilszám");
}
}
- Kérjen be továbbá egy hívás kezdeti és hívás vége időpontot óra perc másodperc formában! A két időpont alapján határozza meg, hogy a számlázás szempontjából hány perces a beszélgetés! A kiszámított időtartamot írja ki a képernyőre!
A 2. feladat lényegében a 3. feladat előkészítője, mert itt a szövegből időpontokat gyártó kódrészletet kell előkészíteni. Azonban ez a feladat sehol sem közli a felhasználó által használandó adatformátumot a bevitelhez. Itt, mivel nem akartuk túlbonyolítani a megoldást, ezért a könnyű utat választottuk és a TimeSpan beépített Parse metódusát használtuk az adatkonvertálásra.
Az időtartam kiszámítása ezután a két érték kivonása egymásból. Ez alapján a percek száma nagyon könnyen megállapítható a TotalMinutes tulajdonság olvasásával.
public void Feladat02()
{
Console.WriteLine("Hívás kezdete:");
var start = TimeSpan.Parse(Console.ReadLine());
Console.WriteLine("Hívás vége:");
var end = TimeSpan.Parse(Console.ReadLine());
TimeSpan hossza = end - start;
//minden megkezdett perc egész percnek számít
//felfelé kell kerekíteni
Console.WriteLine("Hívás ideje: {0} perc", Math.Ceiling(hossza.TotalMinutes));
}
- Állapítsa meg a hivasok.txt fájlban lévő hívások időpontja alapján, hogy hány számlázott percet telefonált a felhasználó hívásonként! A kiszámított számlázott perceket írja ki a percek.txt fájlba a következő formában!
perc telefonszám
A 3. feladat bonyolultsága a beolvasásban rejlik. Egyes érettségi feladatok esetén több sorban vannak összetartozó adatok összeömlesztve. Szerencsére a való életben kevés olyan adatformátum van, amit ennyire buta módon terveztek volna meg, de mint tudjuk, ez egy állatorvosi ló.
A formátumban minden második sor a telefonszámot tartalmazza, az előtte lévő pedig az idő adatokat. A sorok számolásával eldönthetjük, hogy páros vagy páratlan sorszámon állunk és ez alapján tudjuk kezelni az adatot.
Az adatok minden 2. sor beolvasása után tárolhatóak csak le későbbi felhasználásra, mivel itt van meg minden adatunk az adattároló osztályunk példányosításához. Az adatokat a _hivasok lista fogja tárolni, ami a megoldás osztályunkban található.
A percek megállapítása egy adott híváshoz a kiírás esetén csupán annyi, hogy az osztályunkban elhelyezett Percek tulajdonság értékét kiolvassuk.
A beolvasást viszont tovább nehezíti, hogy az adatok szóközzel vannak elválasztva, amit a TimeSpan Parse metódusa nem kezel. Ezért a sort beolvassuk szövegként, majd szóközönként szétszedjük. Az így kapott tömbön LINQ segítségével futtatjuk az int struktúra Parse() metódusát, majd az eredményeket tömbbé alakítjuk. Így lényegében kapunk egy hat elemű egész szám tömböt, amivel könnyen fel tudjuk tölteni az idő adatokat.
public void Feladat03()
{
//beolvasás
using (var file = File.OpenText("HIVASOK.TXT"))
{
string? sor = null;
int sorszamlalo = 0;
TimeSpan aktualisStart = new TimeSpan();
TimeSpan aktualisVege = new TimeSpan();
do
{
sor = file.ReadLine();
if (!string.IsNullOrEmpty(sor))
{
if (sorszamlalo % 2 == 0)
{
//páros sor -> idő
int[] idok = sor.Split(' ').Select(s => int.Parse(s)).ToArray();
aktualisStart = new TimeSpan(idok[0], idok[1], idok[2]);
aktualisVege = new TimeSpan(idok[3], idok[4], idok[5]);
}
else
{
//telefonszám
//itt már megvan minden adat a letároláshoz
_hivasok.Add(new Hivas
{
Telefonszam = sor,
Kezdete = aktualisStart,
Vege = aktualisVege,
}) ;
}
}
++sorszamlalo;
}
while (!string.IsNullOrEmpty(sor));
}
//kiírás
using (var file = File.CreateText("percek.txt"))
{
foreach (var hivas in _hivasok)
{
file.WriteLine("{0} {1}", hivas.Percek, hivas.Telefonszam);
}
}
}
- Állapítsa meg a hivasok.txt fájl adatai alapján, hogy hány hívás volt csúcsidőben és csúcsidőn kívül! Az eredményt jelenítse meg a képernyőn!
A gigantikus beolvasás és kiírás után egy egyszerű és kompakt feladat, amit LINQ segítségével könnyen meg tudunk oldani. Lényegében meg kell számolunk, hogy hány hívás volt 7 és 18 óra között, valamint mennyi volt 7 óra előtt és 18 óra után.
public void Feladat04()
{
int csucsidoben = _hivasok.Count(hivas => hivas.Kezdete.Hours > 7 && hivas.Kezdete.Hours < 18);
int kivul = _hivasok.Count(hivas => hivas.Kezdete.Hours < 7 || hivas.Kezdete.Hours > 18);
Console.WriteLine("Hívások csúcsidőben: {0}", csucsidoben);
Console.WriteLine("Hívások csúcsidőn kívül: {0}", kivul);
}
- A hivasok.txt fájlban lévő időpontok alapján határozza meg, hogy hány percet beszélt a felhasználó mobil számmal és hány percet vezetékessel! Az eredményt jelenítse meg a képernyőn!
Szintén egy egyszerű feladat, ha már az elején elolvastuk a teljes feladatleírást és gondolkodtunk. Az első feladathoz elkészített mobilszám megállapító metódus újrafelhasználásával ki tudjuk válogatni LINQ segítségével a mobilt célzó hívásokat és össze is tudjuk őket szummázni a Hivas osztályunk Percek tulajdonsága alapján.
A vezetékes hívások megállapítása és számolása szinte ugyan ez, csak ott azt figyeljük, hogy mikor nem mobilszám a hívott szám.
public void Feladat05()
{
var mobilpercek = _hivasok
.Where(hivas => MobilSzam(hivas.Telefonszam))
.Sum(hivas => hivas.Percek);
var vezetekespercek = _hivasok
.Where(hivas => !MobilSzam(hivas.Telefonszam))
.Sum(hivas => hivas.Percek);
Console.WriteLine("Mobil hívások: {0} perc", mobilpercek);
Console.WriteLine("Vezetékes hívások {0} perc", vezetekespercek);
}
- Összesítse a hivasok.txt fájl adatai alapján, mennyit kell fizetnie a felhasználónak a csúcsdíjas hívásokért! Az eredményt a képernyőn jelenítse meg!
A végére ismételten egy összegzés. LINQ segítségével elő tudjuk szűrni a hívásokat, amelyek csúcsidőben történtek. Ezt követően már csak végig kell rajtuk iterálni, megnézni, hogy a szám mobilszám-e és ha igen, akkor a mobil percdíjjal szorozni a hívás perceinek számát. Ellenkező esetben pedig vezetékes percdíjjal szorzunk. A kiszámított hívás összeget hozzáadjuk az osszeg változóhoz, ami a ciklus után a fizetendő telefonszámla összegét tartalmazza.
public void Feladat06()
{
const double vezekespercDij = 30.0;
const double mobilpercDij = 69.175;
var csucsidohivasok = _hivasok.Where(hivas => hivas.Kezdete.Hours > 7 && hivas.Kezdete.Hours < 18);
double osszeg = 0;
foreach (var hivas in csucsidohivasok)
{
if (MobilSzam(hivas.Telefonszam))
{
osszeg += hivas.Percek * mobilpercDij;
}
else
{
osszeg += hivas.Percek * vezekespercDij;
}
}
Console.WriteLine("csúcsdíjas hívásokért fizetendő: {0}", osszeg);
}


2020.07.02. @ 19:06
Remek blog, ajánlani fogom az összes barátomnak 😀 csak így tovább
2020.07.02. @ 20:57
köszönjük 🙂