Új hozzászólás Aktív témák
-
scream
veterán
válasz proci985 #1900 üzenetére
Nem értem,mi az hogy érdemes a valós kódot leírni?
Belinkeltem az egész kódomat még a mostani legelső hszemben, (egy link ami a pastebin.com-ra mutat) majd csak megemlítettem egy kódrészletnél hogy az adott hibát hogyan próbáltam megoldani.
Most hogy már megvan a bekérés meg nagyjából maga a kiválogatás, nem kezdenék bele egy teljesen új programkódba, hanem a meglévőt korrigálnám, hogy a csak -1-el rendelkező tanulókat ne listázza ki...
@dabadab :
Használtam én csak nagyon nem tetszett neki a tanulok i-edik eleme...
-
-
vector<vector<int>> studentResults;
vector<int> competingStudents;
for(unsigned int i = 0; i < studentResults.size(); i++){
for(unsigned int j = 0; j < studentResults[i].size(); j++){
if(studentResults[i][j] != -1){
competingStudents.push_back(i);
break;
}
}
}kb ennyi. a versenyző diákok számából meg a névre már lehet következtetni, ha tárolod őket.
valahol meg el kell kezdeni, programozáshoz elején idő és kitartás kell, de megéri.
[ Szerkesztve ]
Don't dream it, be it. // Lagom amount.
-
-
-
pityaa23
senior tag
Sziasztok!
Kaptam egy házit programozásból, linkelem is.
Feladat
aminosav.txt
bsa.txtszerk: visual studioban programozunk, C++ programnyelv.
Tudnátok adni ötleteket, hogy hogy kezdjek neki?
konkrétan az a bajom, hogy az aminosav txt-ből hogy tudnám valahogy rendezni vagy az adatokra konkrétan rákeresni. Gondolkoztam, hogy mivel minden sor \n végű így az alapján szét tudnám választani őket és tömbökbe rakni az egyes aminosavakat, innen talán már könnyebb lenne dolgozni velük. Ez lenne kb a 3.-ik feladatig.A 4. feladatban, meg kéne számolni a C, H, O, N, S betűket majd beszorozni egyenként az atomszámukkal gondolom? Bár nem értem azt a részt hogy az aminosavak összekapcsolódásakor kilép egy Hˇ2O molekula.
5.- Feladatban is mondjuk elkezdeném írni tömbbe a beolvasott adatokat, közben keresni kéne az Y vagy W vagy F betűket, és amint talált, egy új tömböt kezdenék? Ha ez megvan akkor a legnagyobb tömb lenne a megoldás, bár nem tudom hogy tudnám a láncban elfoglalt helyét így meghatározni.
6. Feladat. Itt is gyakorlatilag lehetne kezdeni úgy mint az ötösben, csak a keresésnél R majd A vagy R majd V -t talál akkor kezd új tömböt. Az első tömbben megszámolnám a C-betűket majd kiíratnám.
Kezdő vagyok, lehet sokkal egyszerűbben is meg lehetne oldani, nem tudom ezért is várnék némi ötletet ha tudtok! Határidőm December 8 reggel 8 óra a beadáshoz. Ha addig nem tudnám megoldani lehetne számítani valaki segítségére? Fontos lenne, akár egy évet is csúszhatok, ha nem lesz meg a tárgy sajnos...
Köszönöm mindenkinek előre is!
[ Szerkesztve ]
-
mgoogyi
senior tag
válasz pityaa23 #1909 üzenetére
Csinálsz egy ehhez hasonló Aminosav osztályt:
Class Aminosav
{
private:
std::string rovidites;
char betujel;
int C,H,O,N,S;
const static int C_TOMEG = 12;
const static int *_TOMEG = ...
const static int *_TOMEG = ...
stb.
public:
Aminosav( >>paraméterek<< ) :
rovidites (p1),
betujel(p2),
stb.
{
}
std::string OsszegKeplet()
{
...
}
int RelativTomeg()
{
...
}
stb.
};Beolvasáskor valamilyen konténerbe(pl. std::set vagy std::vector) bepakolod őket a file-ból beolvasott adatok alapján.
Minden részfeladathoz csinálsz neki egy függvényt, és a függvényben megoldod a részfeladatot.
pl a relatív tömeg az egy súlyozott összeadás.Beolvasás: std::ifstream-mel például, a sorok parsolása meg tokenekre szedéssel vagy sscanf.
Az a kérdés, hogy milyen szinten vagy és mi nem világos abból, amit leírtam?
-
jattila48
aktív tag
Kétfázisú inicializálás az, amikor az objektumot a konstruktora nem inicializálja teljesen, hanem még egy inicializáló tfv.-t kell meghívni ahhoz, hogy az objektum használható legyen. Akkor szokták használni, ha az inicializálás során virtuális tfv.-t kell meghívni, vagy a konstruktor nem dobhat exception-t. A kétfázisú inicializálást általában kerülendőnek tekintik. Azonban szerintem kifejezetten hasznos is lehet, és nagyban egyszerűsítheti a megfelelő resource kezelést pl. memory leak elkerülésére használható. Ha pl. van egy objektumunk, aminek inicializálása során két memória foglalást végez, előfordulhat hogy az első allokáció sikeres, a második pedig nem. Konstruktorral megoldva ilyenkor auto_ptr-t használhatunk, mert az első pointert fel kell szabadítani, mielőtt a második allokáció sikertelensége miatt a konstruktor exception-t dob. Ilyenkor az objektum destruktora nem fut le, mert csak teljesen megkonstruált objektumra fut le a destruktor, ha az kilép a scope-ból. Na már most kétfázisú inicializálással az objektumot a konstruktora úgy hozza létre, hogy a szóban forgó két pointert NULL-lal inicializálja, majd az inicializáló tfv. elvégzi a szükséges allokációkat. Ha valamelyik allokáció nem sikerül, akkor az init tfv. exception-t dob, vagy false-val tér vissza, de a sikertelen allokáció eredményeként a pointer NULL marad. Az objektum destruktora csak a nem NULL pointert szabadítja fel, a NULL-t békén hagyja.
class A {
public:
A():c(NULL),d(NULL){}
~A();
bool init(int,int);
private:
char * c;
char *d;
}A::~A()
{
if(c!=NULL)delete[] c;
if(d!=NULL)delete[] d;
}bool A::init(int n,int m)
{
c=new char[n];
d=new char;
return true;
}void main(void)
{
try{
A a; //Ez mindenkepp lefut, nem dob exception-t
a.init(10,0x7fffffff); //A::d-nek tul nagy memoriat akarunk foglalni, ezert exception-t dob
}
catch(std::bad_alloc &){
std::cout << "Memory allpc error";
}
//Itt a lefoglalt A::c felszabadult, nincs memory leak
}A lényeg az, hogy a try blokk végén az A destruktora lefut, mert az A a objektum konstruktora mindenképp lefutott. Kicsit olyan ez, mintha az A osztály maga is egy "smart pointer" lenne.
Mit szóltok hozzá? Ugye nem is feltétlenül rossz a kétfázisú inicializálás?„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
mgoogyi
senior tag
válasz jattila48 #1911 üzenetére
- auto_ptr-rel nem tudsz tömböt felszabadítani (ha tudsz is róla, nem biztos, hogy mindenkinek egyértelmű, főleg mert char tömbökkel dolgozol)
- miért lenne baj a kétfázisú inicializálás? azt kell használni, ami célszerű az adott helyzetben.
- az exception dobás elkerülhető a new esetén az std::nothrow paraméterrel: new(std::nothrow), ekkor NULL pointer-t ad vissza a new, ha nem volt elég memória.
- a destruktorodnak muszáj az objektumod által lefoglalt dolgokat felszabadítani, ez nem kérdés. Nem értem ezt a nagy felhajtást.
- a try catchet ennyi erővel berakhatod a ctor-ba is, ha csak az exception a nagy problémád -
jattila48
aktív tag
válasz mgoogyi #1912 üzenetére
Így van, az auto_ptr nem jó tömbre.
Általában nem tanácsolják a kétfázisú inicializálást. Egy olyan helyzetet próbáltam mutatni, ahol mégiscsak célszerű lehet.
Ha a try cathc-et berakom a ctor-ba, ekkor a try-ban auto_ptr-t kéne használni, ami nem jó tömbre.
Az exception-nel az a problémám, hogy ha ctor-ban keletkezik, akkor nem fut le a destruktor (mivel ekkor nem lett teljesen megkonstruálva az objektum), és azok a felszabadítások amiket a destrukdornak kéne elvégezni, nem végződnek el. A kétfázisú inicializálás azon segít, hogy a destruktor mindenképp lefut (mivel a ctor nem dobott exceptiont, hiszen a kritikus inicializálást az init tfv. végzi), és elvégzi a nem NULL pointerek felszabadítását. A ctor-nak természetesen NULL-lal kell inicializálni a szóbanforgó pointereket.
Egyébként éppen tömb inicializálása kapcsán jött ez elő. Remélem így érthetőbb a dolog, persze felhajtást nem szeretnék csinálni, csak megbeszélni, kinek mi a véleménye.„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
scream
veterán
Valaki tudna abban segíteni, hogy EBBEN a kódban miket kéne még beírni a voidokhoz, hogy rendesen menjen?
Már ezzel szenvedek és nem tudom miért nem akar menni.
-
mgoogyi
senior tag
válasz jattila48 #1913 üzenetére
Én még különösebb iránymutatást nem hallottam kétfázisú inicializálással kapcsolatban, pedig egy ideje már c++-ozok.
A ctor-os try catch dolog:
A felszabadítós dolgokat be lehet rakni egy függvénybe és azt hívod a ctor catch ágában és a dtor-ban is.
Na szóval az a véleményem, hogy ez nem egy lényeges kérdés. -
mgoogyi
senior tag
Mi a probléma konkrétan?
A függvény törzsébe nem tudod mit írj, vagy a paraméterlistájába?
Le se fordul?
Vagy ha elakad, hol akad el?Közben megpróbáltam lefordítani.
kivalogatas függvény:113.sor: string Mehetnek[N];
miért definiálod újra, ott van paraméterként
egyébként stack-en foglalt (nem írsz new-t) tömb esetén a tömbméret konstans kell legyen
(pl. const int N = 500 vagy #define N 500)114.sor: újradefiniálás megint, ha csak 0-ázni akarod, akkor elég a K = 0, de ekkor meg nincs értelme, hogy paraméter legyen
main:
33. sor: kivalogatas(N, M, Tanulok); - több, mint 3 paraméter kéne
34. sor: kiiras(); - nem hívhatod meg paraméterek nélkül, mert vannak paramétereibekeres:
89.sor: cin >> Tanulok.nev; - itt elsőre nem tom mi a baja, átírnám cin.getline-osra első próbálkozásképp
kiiras:
139.sor: cout <<"\n" <<" " << Mehetnek(i) <<endl; - itt sem értem miért nem kajolja be, egy .c_str() biztos megoldja
Összefoglalva:
Próbálj meg lépésenként haladni, és miután kipróbálsz(fordít,futtat, minden ok) egy kisebb dolgot, utána lépsz tovább.Most itt összehánytál egy csomó mindent, aztán halvány fingod sincs, hogy mi nem jó.
[ Szerkesztve ]
-
jattila48
aktív tag
válasz mgoogyi #1917 üzenetére
Biztosan meg lehet oldani másképp is ezt a problémát, pl. ahogy írod. Az én javaslatomnak az az előnye, hogy a konstruktorban nem kell kezelni az exceptiont, sőt az init tfv.-ben sem. Az init tfv. természetesen generálhat exceptiont, de azt lehet kezelni felsőbb szinten, és mikor az objektum kilép a scope-ból a destruktora (illetve a tagobjektumok destruktorai) automatikusan mindig elvegzik a deallokációt. Tehát bármilyen "mélyről" jön egy pointer tag inicializálásával keletkező exception, a végén minden sikeresen allokált pointer tag automatikusan felszabadul.
Nem mondtam, hogy ez lényeges kérdés, viszont szerintem érdekes. Ha nem akarsz, ne válaszolj rá! A kétfázisú inicializálást pedig sok tanulmány ellenzi. Keress rá!„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
mgoogyi
senior tag
válasz jattila48 #1920 üzenetére
Úgy nézek ki, mint aki nem akar válaszolni?
- Az alapvető szabály (amennyire tudom), hogy ctor-ból és dtor-ból nem jöhet ki exception.
- Kétfázisú inicializálást meg akkor szoktak használni, amikor valamilyen hibakezelés szükséges, amit nem tehetünk meg a ctor-ban.Pl. mint amit te írsz, abban az esetben helytálló a dolog, hogy kétfázisú inicializálás kell. De ha veled kéne dolgoznom és csak az interface-ét látnám annak, amit használnom kell, akkor azt látnám, hogy az init visszatér egy bool-al, nyilván ez kéne, hogy jelezze, hogy sikerült-e az init. Ha teli kell raknom a kódot try - catch-el, mert mindenféle exception-re számítanom kell, akkor nem lesz nagy öröm használni az osztályodat.
És ha 1-nél többször kell használnom, amit csináltál, akkor már jobb, ha te try-catch-ezel az init-ben, az összes mindenki másnak, akik meg hívják az init függvényed, nekik meg elég a visszatérési értéket vizsgálniuk. -
scream
veterán
válasz mgoogyi #1918 üzenetére
Sajnos még kezdő "programozó" vagyok, most tapasztalom ki mit hogyan kéne.
Mellesleg "csak" ( ) félreértelmeztem, hogy mit is csinál a void paraméterlistája és nem voltak deklarálva az int mainben a dolgok, illetve a K-t &K-ként kell átadni és megy is.
"Most itt összehánytál egy csomó mindent, aztán halvány fingod sincs, hogy mi nem jó."
Köszönöm a biztató szavakat
[ Szerkesztve ]
-
pityaa23
senior tag
válasz mgoogyi #1910 üzenetére
Köszi!
Holnap tudok nekiállni. Eléggé amatőr vagyok. Későn kezdtem el foglalkozni vele. Programozás 1 tantárgyon túl vagyok, ami a struktúrákig tartott. Komolyabb dolgokat nem csináltunk. Most a programozás 2 eléggé nehezen megy, jó nagy különbség van nehézség terén a 2 tárgy között. Levelezőn tanulok, 3 hete volt az első óra, szóval nagyon idő se volt gyakorolgatni. Most yútúb videókat nézve kell tanulnom, mert az oktatás az kb annyi, hogy órán legépelünk egy programot, gondolkozni vagy önerő az nulla. Ezen a hétvégén vettük az osztályokat, de a fele anyagot le sem adták. Szuper. 15.-én Zh, addig szerintem minden időmet bele kell ölnöm, hogy összehozzak egy kettest. Házi egyébként a 2006 májusi emelt szintű programozás érettségi egyik feladata, csak ott ugye más nyelven írták.
Esetleg ha van ötletetek, hogyan tudnék gyorsan megtanulni programozni ne tartsátok magatokban!
-
mgoogyi
senior tag
Bocs, nem akartalak megbántani, de ennyire nem fog egyszerűen menni a tanulás, csak kis lépésekben.
Elsőnek csak csinálj egy kisebb programot, ami beolvas valamit és kiírja a képernyőre.
2, beolvassas azokat a dolgokat, amikre szükséged lesz és azokat kiírja
3, a beolvasott dolgokat eltárolod valahogy, majd azokon végiglépkedve íratod ki
4, elkezdhetsz gondolkozni a többi dolgonA "biztató" szavak azért jöttek ki belőlem, mert a kódod túl sok hibát tartalmaz egyszerre és úgy tűnik, hogy nem probáltad ki az alapvető dolgokat, mint beolvasás, stb.
Meg kell küzdeni lépésenként mindennel. -
mgoogyi
senior tag
válasz pityaa23 #1923 üzenetére
Keress neten a házitokhoz hasonló feladatokat és próbáld megoldani.
+ kérdezz itt, ha van időm, válaszolok.Mindenképp értened kéne ezeket, majdnemhogy készségszinten:
for, while ciklusok
if, else if, else
pointerek, pl int *
referenciák pl. int &
new, new[], delete, delete[]
tömbök kezelése
class
{
private:
public:
protected:konstruktor
destruktoradattagok
tagfüggvények
virtual tagfüggvényekstatic adattagok
static függvényeköröklődés
}fontosabb collection-ök: std::set, vector, list
Mondjuk ez így elég sok, nem igazán két hetes téma.
Jó lenne tudni, hogy mi az, amit elvárnak.[ Szerkesztve ]
-
scream
veterán
-
mgoogyi
senior tag
Ez azért nehezen hihető, mert van olyan része a kódnak, ami nem fordul le.
Javítom a kódod és nemsokára felrakom pastebin-re.[ Szerkesztve ]
-
pedig a kódrészletek darabonként próbálgatása ahol lehet tényleg sokat javít. sokkal egyszerűbb egy 20soros kódban megérteni pár dolgot, mint kapásból integrálni egy többszáz sorosba.
ha nem vagy biztos a pointerkezelésben és a függvényhívásokban, akkor különösen ajánlott először kipróbálni ezeket egy dummy vectoron, és csak utánna integrálni a véglegesbe.
gyakorlatilag hiába kell kétszer megírni a kódot, az ember időt nyer vele.
még egy tipp: használj értelmes változóneveket ha nem feladatkiírás (ha igen, akkor is megoldható a dolog), a numberOfClasses kissé beszédesebb, mint az M. (ha pedig nem lehet, használj angol változóneveket, későbbiekben a magyar változónevek akkor jók, ha a cég biztos nem akarja eladni a kódot országhatáron túlra)
[ Szerkesztve ]
Don't dream it, be it. // Lagom amount.
-
scream
veterán
válasz proci985 #1929 üzenetére
Igazából a feladat szövege miatt választottam ezeket a változóneveket, mert osztályzatot kapok rá és nehogy belekössenek, hogy : "Ejj kisfiam, nem megmondtam, hogy csak azt alkalmazd, amit előadáson elmondott az előadó?! "
De köszönöm, és a későbbiekben megfogadom.
[ Szerkesztve ]
-
jattila48
aktív tag
válasz mgoogyi #1921 üzenetére
Ez így is van. A kliens felé biztosított init nem generál exceptiont, hanem bool-lal tér vissza. Viszont ez az init tagobjektumok init-jét hívja, amik generálhatnak exceptiont, de azok itt lekezelésre kerülnek.
Kontruktor-nak meg muszáj exceptiont generálni ha valami hiba történik, hiszen másképp nem tudja jelezni a hibát. A bad_alloc-ot lekezelheti (sőt!), de utána új exceptiont kell generálnia.„Kétségtelen, hogy nem tudjuk, mit tegyünk, de felkészültek és elszántak vagyunk.” - Olaf Scholz német kancellár
-
mgoogyi
senior tag
válasz jattila48 #1933 üzenetére
Igazad lehet.
Valszeg jobb a konstruktor-ból hibát dobni, mint kétfázisúan inicializálni.
Viszont ha tényleg exception lehetséges a konstruktorban alapesetben, akkor már inkább elmennék a factory irányba, ami lekreálja az objektumot, visszaad rá egy pointert és azt nézheti a hívó fél, hogy NULL vagy sem.
Ebben az esetben a hívó félnek nem kell semmi meglepetésre számítania. -
Qwertz_
csendes tag
Üdv!
Valaki lenne szíves és megmondaná nekem, hogy miért nem működik a következő kód? Egyetlen hibát ír, de nem tudom, miért. #include <iostream>
#include <string>
#define H 21
#define W 80
using namespace std;
int main() {
string s;
cout << "Mi legyen a szoveg?" <<endl;
cin >> s;
int h=0, w=0, hs=1, ws=1;
while (true) {
for(int i=0;i<h;i++)
cout << endl;
for(int i=0;i<w; i++)
cout << " ";
cout << s;
for(int i=0; i<H-h; i++)
cout << endl;
h += hs;
w += ws;
if (w == W-(s.size()))
ws = -1;
if (h == H-1)
hs = -1;
if(w == 0)
ws = 1;
if (h == 0)
hs = 1;
usleep(5000);
}
} -
válasz Qwertz_ #1935 üzenetére
hm, ez "mit ír ki az adott program" kérdés lett volna?
tipp: máskor az egyetlen hibát is mellékeld, általában segít.
Jhonny06: ahogy nézem gyakorlatilag a sleep()hez hasonló wrapper funkció csak 10^-6 szorzóval, szóval kéne neki Sleep(5)el.
[ Szerkesztve ]
Don't dream it, be it. // Lagom amount.
-
Qwertz_
csendes tag
Sziasztok!
Remélem tudtok segíteni, nagyon hálás lennék!
Sehogyan nem tudom megoldani, hogy a következő program bármely gomb lenyomására lépjen ki:
#include <iostream>
#include <string>
#include <windows.h>
#include <conio.h>
#define H 25
#define W 80
using namespace std;
int main()
{
setlocale(LC_ALL, "hun");
string s;
int i;
// szöveg bekérése
cout << "Képernyővédő szövege:" <<endl;
cin >> s;
// h: x koordináta, w: y koordináta, hs: függőleges irány, ws: vízszintes irány
int h,w,hs,ws,a;
h=0;
w=0;
hs=1;
ws=1;
a=0;
fflush(stdin);
while (true)
{
// függőleges igazítás
for(i=1;i<h;i++)
cout << endl;
// vízszintes igazítás
for(i=1;i<w;i++)
cout << " ";
// szöveg kiírása
cout << s;
// maradék sorok kitöltése
for(i=0; i<H-h; i++)
cout << endl;
// következő pozíciók kiszámítása
h += hs;
w += ws;
// irányok beállítása a széleken
if (w == W-(s.size()))
ws = -1;
if (h == H-1)
hs = -1;
if(w == 0)
ws = 1;
if (h == 0)
hs = 1;
// késleltetés
Sleep(200);
}
return 0;
}Lenne szíves segíteni valaki?
[ Szerkesztve ]
-
amargo
addikt
válasz Qwertz_ #1939 üzenetére
Erre használják többek között a hatul tesztelő ciklusokat, ha csak túl akarsz lenni rajta, akkor használd a break-et.
“The workdays are long and the weekend is short? Make a turn! Bike every day, bike to work too!”
-
-
amargo
addikt
válasz proci985 #1943 üzenetére
Persze megy azzal, csak nekem kicsit fura, mert 1x mindenképpen leakarod futtatni.
Qwertz_: Láttam a privátokat, de ha segítek itt teszem.
Ahhoz, hogy bármilyen gombra kilépjen, előbb be kell kérni azt.
Sok mindent nem értek ezzel a kóddal kapcsolatban, egy végtelen ciklusban szaladgálsz és mindenfélét próbálsz ott csinálni.
Ezzel pl mi a célod, főleg úgy, hogy a h és a w elsőnek 0:
// függőleges igazítás
for(i=1;i<h;i++)
cout << endl;
// vízszintes igazítás
for(i=1;i<w;i++)
cout << " ";
// szöveg kiírása
cout << s;
És azzal, hogy ezt végtelenszer végzed el?“The workdays are long and the weekend is short? Make a turn! Bike every day, bike to work too!”
-
-
44kos
tag
Sziasztok!
Most kezdtem el a programozni, elsőnek egy könyvön rágom át magamat, az egyik példájánál elakadtam:
A kérdésem a 12. sorhoz kapcsolódik, miért ez lesz az eredménye a kimeneten?A cout parancs jobbról balra értékelődne ki?
Azért kérdem, mert ha így is van, miért ebben a sorrendben írja ki a szöveget és a számot?
Amikor meghívódik az Add() függvény, kiírja a képernyőre a szöveget, hogy Itt a az Add().... és ezután miért nem rögtön az eredményt, amivel visszatér írja ki, miért ékelődik be a függvény által kiírt szöveg és az eredmény(7) közé a "visszaadott érték" szöveg?[ Szerkesztve ]
Új hozzászólás Aktív témák
● ha kódot szúrsz be, használd a PROGRAMKÓD formázási funkciót!
- iPad Pro 11 WiFi 128GB M1 (3rd gen. 2021) + Apple Pencil 2
- GAMER PC - NZXT - RTX 3060Ti 8GB - i7 7700 - 32GB DDR4 - 500GB M.2 Nvme SSD - 1TB HDD
- BONTATLAN Új Iphone 15 PRO 128-512GB Független 1év Apple GARANCIA Deák Térnél Azonnal Átvehető.
- ÚJ Bontatlan Macbook Pro 16 M3 Pro MAX 14 30GPU 96GB 2TB Magyar billentyűzet Azonnal átvehető.
- 5% kedvezmény a Cammus szimulátor termékeihez.