13. fejezet: Tömbök gyakorlati használata példákkal
Már láttunk gyakorlatban vektorokat és mátrixokat (avagy tömböket). Némi ismétlésként tekintsük át őket!
Deklaráció: típus név [elemszám];
Minta: int akarmi [5]; // Ez egy 5-elemű, 1-dimenziójú tömböt deklarál, melynek minden eleme egész (int) lesz.
Az elemeket akár a deklaráció alkalmával is feltölthetjük. Például:
int akarmi [] = { 16, 2, 77, 40, 12071 };
Nem szabad elfelejteni, hogy az egyes elemekre hivatkozni a következőképpen lehet:
akarmi[0] // Ez lesz 16
akarmi[1] // Ez lesz 2...
Gyakorlati példában vegyünk fel két tömböt! Az egyikbe rakjuk bele az első 5 Árpád-házi király nevét, majd a másodikba az uralkodásuk idejét (től-ig).
---------------------------------------------
// Árpád-házi királyok
#include <iostream>
using namespace std;
#define ELVALASZT " ----- "
int main ()
{
// Deklarációs rész - értékadással
string kiraly [5] = {"Szent Istvan", "Orseolo Peter", "Aba Samuel", "Orseolo Peter", "I. Andras"};
int uralk[6][1];
uralk[0][0]=1000;
uralk[0][1]=1038;
uralk[1][0]=1038;
uralk[1][1]=1041;
uralk[2][0]=1041;
uralk[2][1]=1044;
uralk[3][0]=1044;
uralk[3][1]=1046;
uralk[4][0]=1046;
uralk[4][1]=1060;
// Kiiratási rész
cout <<"Elso 5 Arpad-hazi kiralyunk\n";
for (int i=0;i<5;i++)
{
cout << kiraly[i] <<ELVALASZT; //Király nevének kiírása
cout << uralk[i][0] <<" - " <<uralk[i][1] <<"\n"; //Uralkodási évének kiírása
}
return 0;
}
---------------------------------------------
Egyes C++ nyelvjárásokban megengedett a többszörös értékadás, tehát két változónak is ugyanazt az értéket adhatjuk, de ez sajnos itt nem lehetséges!
Ettől függetlenül érdemes megnézni a többszörös értékadás ötletét, mivel így megkíméltük magunkat attól, hogy több ugyanolyan értéket egymás után többször is be kelljen gépelnünk.
Kicsi kitérőként tanuljunk meg képernyőt törölni! Ehhez egy új beépülő kell, majd jöhet maga a parancs is:
---------------------------------------------
#include <iostream>
#include <cstdlib> // Ez lesz az új beépülő modul.
using namespace std;
int main ()
{
system("cls"); //Ez pedig maga a képernyőtörlés.
}
---------------------------------------------
Most ezt a királyos programot bővítsük annyival, hogy minden uralkodó után írassuk ki, hogy hány évig uralkodott. Ez persze csak a kiíratási részt érinti. Most csak a kiíratási részt másolom ide:
---------------------------------------------
// Kiíratási rész
cout <<"Elso 5 Arpad-hazi kiralyunk\n";
for (int i=0;i<5;i++)
{
cout << kiraly[i] <<ELVALASZT; //Király nevének kiírása
cout << uralk[i][0] <<" - " <<uralk[i][1] <<"\n"; //Uralkodási évének kiírása
cout <<ELVALASZT <<"Uralkodas hossza: " <<uralk[i][1]-uralk[i][0] <<" ev.\n\n";
}
return 0;
---------------------------------------------
Még egy csavart tegyünk bele! Ugyanis kellene az is, hogy ki uralkodott a leghosszabb ideig. Ehhez be kell vezetni még pár változót, hogy munkánkat megkönnyebbítsük. Íme az (egyik lehetséges) eredmény:
---------------------------------------------
// Árpád-házi királyok
#include <iostream>
#include <cstdlib>
using namespace std;
#define ELVALASZT " ----- "
int main ()
{
// Deklarációs rész - értékadással
string kiraly [5] = {"Szent Istvan", "Orseolo Peter", "Aba Samuel", "Orseolo Peter", "I. Andras"};
int uralk[6][1];
int hossz[6];
uralk[0][0]=1000;
uralk[0][1]=1038;
uralk[1][0]=1038;
uralk[1][1]=1041;
uralk[2][0]=1041;
uralk[2][1]=1044;
uralk[3][0]=1044;
uralk[3][1]=1046;
uralk[4][0]=1046;
uralk[4][1]=1060;
// Kiiratási rész
system("cls");
cout <<"Elso 5 Arpad-hazi kiralyunk\n";
int legtobb; // Ez legyen a leghosszabb ideig uralkodó indexe
int leghosszabb = 0; // Ennyi ideig uralkodott
for (int i=0;i<5;i++)
{
cout << kiraly[i] <<ELVALASZT; //Király nevének kiírása
cout << uralk[i][0] <<" - " <<uralk[i][1] <<"\n\n"; //Uralkodási évének kiírása
hossz[i] = uralk[i][1]-uralk[i][0]; //Uralkodás hosszának kiszámítása
cout <<ELVALASZT <<"Uralkodas hossza: " <<hossz[i] <<" ev.\n";
if (hossz[i]>leghosszabb)
{
// cout <<"\n Ez hosszabb lesz!"; //Csak a tesztelés miatt maradt benne!
legtobb = i;
leghosszabb = hossz[i];
}
}
cout <<"\n\n Legtovabb uralkodott: " <<kiraly[legtobb];
cout <<"\n Uralkodas hossza: " <<leghosszabb;
return 0;
}
---------------------------------------------
Ami még a vektorokhoz tartozik, azok a karakteres vektorok. Lássunk erre is egy példát!
Deklaráljuk a következő tömböt: char jenny [20];
Ez ugye egy 20-elemű vektor, melynek minden egyes tagja 1-1 karakter.
Fel lehet tölteni például a következővel:
Hello\0, ahol az egyes elemek értéke a következő lesz:
jenny[0]="H"
jenny[1]="e"
jenny[2]="l"
jenny[3]="l"
jenny[4]="o"
jenny[5]="\0"
Ez utóbbi lesz a szöveget lezáró jel, ami a rendszernek fontos. Lényeges, hogy bár mi "\0"-át látunk, ami látszólag 2 db karakternyi helyet foglal, de a rendszer ezt egyetlennek érzi!
Az előző deklarációt így is meg lehet oldani: char jenny[] = { 'H', 'e', 'l', 'l', 'o', '\0' };
Viszont ez esetben a tömb vége a \0 mutatójánál lesz, azaz 5-nél, nem pedig 20-nál.
Tudom, hogy ez egy meglehetősen bonyolult, de lesz még egyszerűbb is! Íme:
char jenny [] = "Hello";
Lássunk egy gyakorlati példát is! Kérjük be a felhasználó családnevét, majd egy sima üdvözlet után írjuk vissza:
---------------------------------------------
// Karakteres tömbök használata
#include <iostream>
#include <cstdlib>
using namespace std;
int main ()
{
char kerdes[] = "Kerem a csaladi nevet: ";
char udv[] = "Hello, ";
char nev [80];
cout << kerdes;
cin >> nev;
system("cls");
cout << udv << nev << "!";
return 0;
}
---------------------------------------------
Vegyük észre, hogy a kiírásnál, illetve a cin-nel történő bekérésnél nem kell a zárójeleket használni!Érdemes észrevenni, hogy a rendszer igen gördülékenyen működik, ha valakinek csak egy családi neve van, mint általában. De mi van, ha a teljes nevét kérjük, ami több, mint egy tagú. Ilyenkor sajnos csak a családnevet kapjuk vissza. A probléma onnan ered, hogy a cout és (nekünk most főleg) a cin automatikusan minden egyes szó mögé tesz egy "\0" jelet, amivel lezárja az aktuális szót. Ezzel a kiírásunkat, sajnos agyoncsapja. Helyette egy apró trükköt kell alkalmazni, mégpedig egy új beépülőt is be kell vetni, ami egy új bekérési lehetőséget ad.
---------------------------------------------
// Karakteres tömbök használata 2.
#include <iostream>
#include <cstdlib> // Ez a képernyőtörlés miatt kell
#include <string> // Ez az új beépülő
using namespace std;
int main ()
{
char kerdes[] = "Ke'rem a teljes neve't: ";
char udvozlet[] = "Hello, ";
string teljesnev; // Immár szöveget kérünk, nem karaktereket
cout << kerdes;
getline(cin,teljesnev); // Ez az új szöveg-bekérési eljárás
system("cls");
cout << udvozlet << teljesnev << "!";
return 0;
}
---------------------------------------------
14. fejezet: További gyakorló feladatok
Ezt a részt azoknak szántam, akik még nem biztosak a tudásukban és szeretnének még gyakorolni. Tanári tapasztalataim azt mutatják, hogy eddig a pontig viszonylag könnyű eljutni egy közepes képességű csoporttal, esetleg egy gyengével is. A csoportnak itt viszont nagyon erősen javasolt pár tudásukat megerősítő feladatot feladni. Ezek jönnek most! (Megjegyzés: a feladatok többsége némi matematikai tudást is igényel.)
14.1. Kérje be egy háromszög három oldalát. Jelezze, ha az adatokból nem szerkeszthető háromszög. Ha szerkeszthető, akkor számolja ki a kerületét és a területét!
Itt először is be kell kérni a három oldalt. Ez már nem okozhat gondot! (Azért ne feledkezzünk meg a megfelelő kiírásról sem.)
---------------------------------------------
#include <iostream>
#include <cstdlib> // Ez a képernyőtörlés miatt kell
#include <math.h> // Ez a gyökvonáshoz kell
using namespace std;
#define VESSZO ","
int main ()
{
system("cls");
double a,b,c;
// Adatbekérés
cout << "Feladat: Egy haromszog 3 oldalat bekerve dontse el, hogy szerkesztheto-e, majd ha igen, akkor szamolja ki a haromszog teruletet es keruletet!\n\n";
cout << "Kerem az 1. oldalt! ";
cin >> a;
cout << "\nKerem a 2. oldalt! ";
cin >> b;
cout << "\nKerem a 3. oldalt! ";
cin >> c;
cout << " A haromszog oldalai: " << a << VESSZO << b << VESSZO << c <<"\n";
// Szerkeszthetőség bekérése
bool szerkhet = false; // Ez azt jelzi, hogy szerkeszthető-e a háromszög
if ((a+b>c) and (a+c>b) and (b+c>a))
{
szerkhet = true;
}
if (szerkhet==false)
{
cout << "\nA haromszog nem szerkesztheto!";
}
else
{
cout << "\nA haromszog szerkesztheto!";
}
// Kerület és terület kiszámítása
double ker, s, szamit, ter;
ker = a+b+c;
cout << "\nA haromszog kerulete: " << ker;
s = ker / 2;
szamit = s*(s-a)*(s-b)*(s-c);
ter = sqrt(szamit);
cout <<"\nA haromszog terulete: " << ter;
return 0;
}
---------------------------------------------
14.2. Egy kis cégnek 10 dolgozója van. Kérje be ezek havi bruttó fizetését. Számolja ki az átlagát, majd minden egyes fizetésről döntse el, hogy átlag alatti vagy feletti, esetleg megegyezik vele.
---------------------------------------------
#include <iostream>
#include <cstdlib> // Ez a képernyőtörlés miatt kell
using namespace std;
#define VESSZO ","
int main ()
{
system("cls");
int fizu [10];
// Adatbekérés
cout << "Feladat: 2.) Egy kis cégnek 10 dolgozója van. Kérje be ezek havi bruttó fizetését. Számolja ki az átlagát, majd minden egyes fizetésről döntse el, hogy átlag alatti vagy feletti, esetleg megegyezik vele.\n\n";
for (int i=1; i<11; i++)
{
cout <<"\nKerem a(z) " <<i <<". dolgozo fizeteset:";
cin >> fizu[i];
}
cout <<"\n\nTehat a fizetesek: ";
for (int i=1; i<11; i++)
{
cout <<fizu[i] << VESSZO;
}
//Számítások
int osszeg = 0;
for (int i=1;i<11;i++)
{
osszeg = osszeg + fizu[i];
}
double atlag;
atlag = osszeg / 10;
cout <<"\nFizetesek atlaga: " <<atlag;
for (int i=1;i<11;i++)
{
cout <<"\n" <<i <<". fizetes: " << fizu[i] <<" ";
if (fizu[i]<atlag) cout << " alacsony";
if (fizu[i]>atlag) cout <<" magas";
if (fizu[i]==atlag) cout <<" atlagos";
}
return 0;
}
---------------------------------------------
A fenti megoldásban egyetlen kivetnivaló akad: a végén, amikor a fizetéseket összehasonlítjuk az átlaggal, akkor azt lehetne egyetlen feltétellel is megoldani...
14.3. A program olvasson be pozitív egész számokat addig, amíg 0-t nem kap. Írja ki a beolvasott értékek mennyiségét, átlagát és az átlagtól való eltérések átlagát!
---------------------------------------------
#include <iostream>
#include <cstdlib> // Ez a képernyőtörlés miatt kell
using namespace std;
#define VESSZO ","
#define maxx 200 // Maximum ennyi számot tárolunk.
int main ()
{
system("cls");
int beker, szamol;
int tomb[maxx];
// Adatbekérés
cout << "Feladat: 3.) A program olvasson be pozitív egész számokat addig, amíg 0-t nem kap. Írja ki a beolvasott értékek mennyiségét, átlagát és az átlagtól való eltérések átlagát!\n\n";
szamol = 0;
do
{
szamol++;
cout <<"Kerem a kovetkezo szamot! ";
cin >> beker;
tomb[szamol]=beker;
}
while (beker != 0);
// Adatok visszaírása
cout <<"\nA bevitt szamok: \n";
for (int i=1; i<szamol;i++)
{
cout <<tomb[i] << VESSZO;
}
// Adatok feldolgozása
double atlag, osszeg = 0;
for (int i=1;i<szamol;i++)
{
osszeg = osszeg + tomb[i];
}
atlag = osszeg / szamol;
cout <<"\nA bevitt szamok atlaga: " <<atlag;
return 0;
}
---------------------------------------------
A megoldásban egyetlen egy „trehányságot” sikerült elkövetni: van a kiírásnál egy felesleges vessző. Nos, ezt a problémát az olvasóra bízom!
14.4. Írja ki a program az első 20 olyan számot, amely nem osztható sem 2-vel, sem 3-mal, sem 5-tel!
---------------------------------------------
#include <iostream>
#include <cstdlib> // Ez a képernyőtörlés miatt kell
using namespace std;
#define VESSZO ","
int main ()
{
system("cls");
cout <<"Feladat: 4.) Írja ki a program az első 20 olyan számot, amely nem osztható sem 2-vel, sem 3-mal, sem 5-tel!";
//Számolási rész
int sz[20], szamol = 1;
int szam = 6; //Ezzel a számmal fogok próbálkozni, hogy megfelel-e.
do
{
if ((szam % 2 == 0) or (szam % 3 == 0) or (szam % 5 == 0))
{
// cout <<"\n" <<szam <<"Ez rossz!"; // Csak a tesztverzióban kellett!
}
else
{
// cout <<"\n" <<szam <<"Ez viszont megfelel!"; //Csak a tesztverzióban kellett!
sz[szamol] = szam; // Itt elraktározom a következő számot
szamol++; // Az indexet is növelem eggyel
}
szam++; // Veszem a következő számot
}
while (szamol<20);
//Kiírási rész
cout <<"\nA megtalalt szamok:\n";
for (int i=1; i<20;i++)
{
cout <<sz[i];
if (i<19) cout << VESSZO; //Ezzel a megoldással sikerül elkerülni az utolsó vessző okozta problémát!
}
return 0;
}
---------------------------------------------
Érdemes észrevenni, hogy ebben a verzióban maradt némi „felesleges” kiírás még a teszt-verzióból. Ezt érdemes megszokni, mivel így a program a későbbiekben is jól érthető lesz és könnyebb felfogni a működését...
14.5. Egy sorozat képzési szabálya a következő: a soron következő elem legyen az előző kettő összegénél eggyel nagyobb. Írassa ki a sorozat első 20 elemét, ha az első két elem egyaránt 1.
---------------------------------------------
#include <iostream>
#include <cstdlib>
using namespace std;
#define VESSZO ","
int main ()
{
system("cls");
cout <<"Feladat: 5.) Egy sorozat képzési szabálya a következő: a soron következő elem legyen az előző kettő összegénél eggyel nagyobb. Írassa ki a sorozat első 20 elemét, ha az első két elem egyaránt 1.";
int sor[20];
//Számolási rész
sor[1] = 1;
sor[2] = 1;
for (int i=3; i<21; i++)
{
sor[i]= sor[i-1]+sor[i-2]+1;
}
//Kiíratás
cout <<"\nA sorozat elemei: \n";
for (int i=1; i<21; i++)
{
cout <<sor [i];
if (i != 20) cout << VESSZO;
}
return 0;
}
---------------------------------------------
14.6. Kérjen be egy pozitív számot. Írassa ki a szám négyzetét, négyzetgyökét, szinuszát és 10 alapú logaritmusát!
---------------------------------------------
#include <iostream>
#include <cstdlib>
#include <math.h> // Ez a matematikai függvények miatt kell
using namespace std;
#define VESSZO ","
int main ()
{
system("cls");
// Bekérés
double szam;
cout <<"Feladat: 6.) Kérjen be egy pozitív számot. Írassa ki a szám négyzetét, négyzetgyökét, szinuszát és 10 alapú logaritmusát!";
do
{
cout <<"\nKerek egy pozitiv szamot!";
cin >> szam;
if (szam<=0) cout <<"\nHibas szamot adott meg! Kerem ujra!\n";
}
while (szam<=0);
//Kiíratások és számolások
cout <<"\n\nA beadott szam: " <<szam;
cout <<"\nNegyzete : " <<szam*szam;
cout <<"\nGyoke : " <<sqrt(szam);
cout <<"\nSzinusza : " <<sin(szam);
cout <<"\nLogaritmusa: " <<log10(szam);
return 0;
}
---------------------------------------------
14.7. Kérje be egy gömb sugarát, majd írassa ki a gömb térfogatát és felszínét!
Ez egy egyszerű matematikai művelet lesz!
---------------------------------------------
#include <iostream>
#include <cstdlib>
#include <math.h> // Ez a matematikai függvények miatt kell
using namespace std;
#define VESSZO ","
#define PI 3.1415
int main ()
{
system("cls");
// Bekérés
double r; //Ez a gömb sugara
cout <<"Feladat: 7.) Kérje be egy gömb sugarát, majd írassa ki a gömb térfogatát és felszínét!";
do
{
cout <<"\nKerek egy pozitiv szamot!";
cin >> r;
if (r<=0) cout <<"\nHibas szamot adott meg! Kerem ujra!\n";
}
while (r<=0);
//Kiíratások és számolások
cout <<"\n\nA beadott szam: " <<r;
cout <<"\nA gomb terfogata: " <<4*r*r*r*PI/3;
cout <<"\nA gomb felszine : " <<4*r*r*PI;
return 0;
}
---------------------------------------------
14.8.) Kérje be egy kocka oldalát, majd írassa ki a felszínét, térfogatát, a köré és a beleírt gömb sugarait!
Az előzőhöz hasonlóan ez is csak egy matematikai műveletsor lesz.
---------------------------------------------
#include <iostream>
#include <cstdlib>
#include <math.h> // Ez a matematikai függvények miatt kell
using namespace std;
#define VESSZO ","
int main ()
{
system("cls");
// Bekérés
double a; //Ez a kocka oldala
cout <<"Feladat: 8.) Kérje be egy kocka oldalát, majd írassa ki a felszínét, térfogatát, a köré és a beleírt gömb sugarait!";
do
{
cout <<"\nKerek egy pozitiv szamot!";
cin >> a;
if (a<=0) cout <<"\nHibas szamot adott meg! Kerem ujra!\n";
}
while (a<=0);
//Kiíratások és számolások
cout <<"\nA beadott szam : " <<a;
cout <<"\nA kocka terfogata : " <<a*a*a;
cout <<"\nA kocka felszine : " <<6*a*a;
cout <<"\nA beirt gomb sugara : " <<a/2;
cout <<"\nA koreirt gomb sugara: " <<sqrt(3)*a/2;
return 0;
}
---------------------------------------------
14.9.) Kérjen be két különböző pozitív egész számot, majd írassa ki a köztük lévő egészeket, azok összegét és szorzatát!
Itt egy külső eljárást is használunk cserére, ha az szükséges.
---------------------------------------------
#include <iostream>
#include <cstdlib>
using namespace std;
#define VESSZO ","
void csere(int& x, int& y) //Egyszerű csere
{
double z;
z = x;
x = y;
y = z;
}
int main ()
{
system("cls");
// Bekérés
int a,b; //Ez a két szám
cout <<"Feladat: 9.) Kérjen be két különböző pozitív egész számot, majd írassa ki a köztük lévő egészeket, azok összegét és szorzatát!";
do
{
cout <<"\nKerek egy pozitiv egesz szamot!";
cin >> a;
if (a<=0) cout <<"\nHibas szamot adott meg! Kerem ujra!\n";
}
while (a<=0);
do
{
cout <<"\nKerek egy pozitiv egesz szamot!";
cin >> b;
if (b<=0) cout <<"\nHibas szamot adott meg! Kerem ujra!\n";
}
while ((b<=0) and (a!=b));
//Kiíratások és számolások
if (b<a) csere(a,b); // A csere rutint előre meg kell írni!
cout <<"\nKisebb : " <<a;
cout <<"\nNagyobb: " <<b;
cout <<"\nKoztuk levo egeszek: ";
int osszeg = 0, szorzat = 1;
for (int i=a+1; i<b;i++)
{
cout <<i;
if (i<b-1) cout <<VESSZO;
osszeg = osszeg + i;
szorzat = szorzat * i;
}
cout <<"\nOsszeguk : " <<osszeg;
cout <<"\nSzorzatuk: " <<szorzat;
return 0;
}
---------------------------------------------