A pszeudokód olyan nyelvezet, amellyel algoritmusokat írunk le emberi olvasónak. Kevésbé részletes, mint egy programozási nyelv, de a szerkezete hasonló. Az, hogy a pszeudokód helyes-e, az attól függ, hogy megértik-e az olvasók az általa leírt lépéssort (szemben a programozási nyelvekkel, ahol a fordítóprogram egy merev szabályrendszer betartását várja el).
Itt elérhető egy román nyelvű cikk a pszeudokódról (pbinfo.ro).
Tartalom
- Változók, kifejezések
- Összetett utasítások
- Nyomonkövetés
- Pszeudokód átírása C++ nyelvre
- Egyik ciklus átírása a másikba
- Amíg → Ismételd … ameddig
- Amíg → Ismételd … ameddig
- Végezd el … amíg → Amíg
- Ismételd ameddig → Amíg
- Végezd el … amíg → Ismételd … ameddig
- Ismételd ameddig → Végezd el … amíg
- Minden → Amíg
- Minden → Végezd el … amíg
- Minden → Ismételd … ameddig
- Amíg → Minden (ha lehet)
- Végezd el … amíg → Minden (ha lehet)
- Ismételd … ameddig → Minden (ha lehet)
1. Változók, kifejezések
A változókat nem kell előre bejelenteni a típus megadásával, az első értékadáskor létrejönnek. Az értékadás alakja:
valtozonev ← ertek
Tehát a C++-ban megszokott = jel helyett egy balra mutató nyilat használunk.
A kifejezésekben használhatók változók és konstans értékek, illetve ezekkel végzett műveletek:
+: összeg-: különbség*: szorzat/: hányados. Figyelem: ez itt valós szám, ha az egész hányadost szeretnénk, akkor az egész részes jelölést használjuk, pl.[a/b](a és b hányadosának egész része).%: osztási maradék (egész számok esetén van csak értelme)
Feltételekben használható relációs műveletek (a megszokott matematikai jelentéssel):
- =, ≠ (itt nincs szükség dupla
=jelre, mert az értékadás más) - <, ≤, >, ≥
Logikai műveletek:
- ÉS - konjunkció (ez C++-ban az
&&) - VAGY - diszjunkció (mint C++-ban a
||) - NEM v. NOT - tagadás (a C++-beli
!)
Beolvasás és kiírás: A “beolvas” (röviden “be”) és kiír (röviden “ki”) utasításokkal történik.
2. Összetett utasítások
2.1. Elágazás (az if megfelelője)
Szerkezete:
Ha feltétel akkor
│ utasítások1
│különben
│ utasítások2
└■
A különben rész elhagyható, ha nincs rá szükség:
Ha feltétel akkor
│ utasítások1
└■
Működése:
- ha a “feltétel” szó helyére írt feltétel igaz, az “akkor” ág utasításai hajtódnak végre (utasítások1), különben a “különben” ág utasításai (utasítások2).
- a “különben” ág opcionális, ha nem akarunk ott semmit elvégezni, akkor nem kell kiírni
- kézírásban a bal oldalon egy folytonos függőleges vonalat húzunk (a szaggatott helyett)
Román megfelelője:
Dacă feltétel atunci
│ utasítások1
│altfel
│ utasítások2
└■
2.2. Elöltesztelő ciklus (a while megfelelője)
Szerkezete:
Amíg feltétel végezd el
│ utasítások
└■
Románul:
Cât timp feltétel execută
│ utasítások
└■
A működése azonos a while ciklussal (amíg a feltétel igaz, ismétli az utasításokat). A “végezd el” szószerkezet rövidíthető “v.e."-re (de vizsgákon nem ajánlott).
2.3. Hátultesztelő ciklus (a do-while megfelelője)
Két típusát is használják:
Végezd el … amíg
Szerkezete:
Végezd el
│ utasítások
│ ...
│amíg feltétel
└■
A működése azonos a do-while ciklussal (egyszer biztosan elvégzi az utasításokat, majd addig ismétel amíg a feltétel igaz).
Ismételd … ameddig
Szerkezete:
Ismételd
│ utasítások
│ ...
│ameddig feltétel
└■
A működése abban különbözik az előzőtől, hogy akkor ismétel, ha a feltétel HAMIS (ezért használunk más szavakat, az amíg szó jelenti azt, hogy igaz feltétel esetén ismétlünk, akár elöl, akár hátul van; az ameddig pedig azt, hogy hamis feltétel esetén ismétlünk és megállunk, amint igazzá válik).
Román megfelelője a végezd el … amíg-nak:
Execută
│ utasítások
│ ...
│cât timp feltétel
└■
Román megfelelője az ismételd … ameddig-nek:
Repetă
│ utasítások
│ ...
│până când feltétel
└■
2.4. Meghatározott lépésszámú ciklus (a for-hoz hasonlít, de sajátosabb)
Szerkezete:
Minden változónév ← kezdőérték, végérték, lépés végezd el
│ utasítások
└■
Románul:
Pentru változónév ← kezdőérték, végérték, lépés execută
│ utasítások
└■
Működése:
- a kezdőérték, végérték és lépés helyére számokat vagy kifejezéseket írunk, a “változónév” nevű változó a “lépésben” megadott egységenként végigmegy a kezdőértéktől a végértékig
- ha a lépést nem írjuk ki, akkor 1-nek számít
- a változót a cikluson belül nem szokás módosítani (konvenció szerint nem is engedhető meg)
Példák:
- kiírjuk a számokat 1-től n-ig:
Minden i ← 1, n végezd el
│ kiír i
└■
- kiírjuk a számokat n-től 1-ig visszafelé (itt -1-enként kell lépni):
Minden i ← n, 1, -1 végezd el
│ kiír i
└■
- kiírjuk a páratlan természetes számokat 1 és 100 között:
Minden i ← 1, 100, 2 végezd el
│ kiír i
└■
3. Nyomonkövetés
A nyomonkövetés azt jelenti, hogy végrehajtjuk kézzel egy algoritmus utasításait (sorban, egyesével) adott bemenetre. Közben egy táblázatban követjük a változók értékeinek változásait és a képernyőre kerülő kimenetet.
Példa: kövessük nyomon az alábbi algoritmust, ha a bemenet 8 3!
beolvas a, b
Ha a > b akkor
│ x ← a
│ a ← b
│ b ← x
└■
Minden i ← a, b, 2 végezd el
│ kiír 2*i + 1, " "
└■
kiír "vége"
Táblázat:
a | 8 3
---+------------------------------
b | 3 8
---+------------------------------
x | 8
---+------------------------------
i | 3 5 7
Kimenet:
7 11 15
vége
A táblázat egyes soraiban hagyhatunk ki helyett, hogy jobban követhető legyen, hogy melyik változás mikor történt (mintha lenne egy vízszintes időtengely a rajzon). Ha papíron dolgozunk, akkor a változók régi értékeit érdemes egy ferde vonallal lehúzni (így az 1-es mellé írt 2-est nem fogjuk véletlenül tizenkettőnek olvasni).
Ha egy változó tömb, akkor érdemes annak elemeit valamilyen jelekkel körülhatárolni (pl. [ és ], vagy { és }). És minden változást vagy helyben bejelölni (az adott elem alá vagy fölé), vagy mindegyik esetén úrja leírni a tömböt.
4. Pszeudokód átírása C++ nyelvre
Az átírás általában egyszerű, de néhány dologra oda kell figyelni:
- a C++ program elején lesznek olyan sorok, amik pszeudokódban nem voltak meg (#include<…> stb.)
- az utasításokat rendszerint ; kell zárja
- minden változót be kell jelenteni használat előtt, megadva annak a típusát
- a hátultesztelő ciklusok esetén a feltételt tagadni kell abban az esetben, ha ismételd…ameddig ciklust írunk át do-while-ra (mert az előbbi hamis, utóbbi pedig igaz feltétel esetén ismétel)
- a minden ciklus átírásakor egy megfelelően összeállított for-t használunk (figyelem: a minden ciklus esetén a kezdő és végérték zárt intervallumot alkot, ennek megfelelően a for-ban <= vagy >= operátorok kellenek majd)
Példa: az alábbi algoritmust szeretnénk C++-ra árírni.
beolvas n
Ismételd
│ kiír n, ': '
│ Minden i ← n, 1, -1 végezd el
│ │ kiír i, ' '
│ └■
│ kiír <új sor>
│ n ← n - 1
│ameddig n ≤ 0
└■
Megoldás:
| |
5. Egyik ciklus átírása a másikba
Arra kell figyelni, hogy a két algoritmus BÁRMILYEN MEGENGEDETT BEMENETRE ugyanúgy viselkedjen (tehát ugyanazt a kimenetet produkálja, néha esetleg még arra is figyelünk, hogy a változók értékei ugyanazok legyenek a végén).
Amíg → Végezd el … amíg
Mindkettő igaz feltétel mellett ismétel, de a hátultesztelő ciklus legalább egyszer végrehajtaná a benne levő utasításokat. Úgy tesszük a kettőt ekvivalenssé, hogy a végezd el … amíg köré egy elágazást rakunk az eredeti feltétellel.
Példa: írjuk át az alábbi algoritmust úgy, hogy amíg ciklus helyett végezd el … amíg-ot használjon!
beolvas n
Amíg n > 0 végezd el
│ kiír n, ' '
│ n ← n - 2
└■
Átírva:
beolvas n
Ha n > 0 akkor
│ Végezd el
│ │ kiír n, ' '
│ │ n ← n - 2
│ │amíg n > 0
│ └■
└■
Megjegyzés: az n = 0 bemenetre az algoritmus semmit nem kell kiírjon!
Amíg → Ismételd … ameddig
Hasonlít az előzőhöz, de arra is kell figyelni, hogy az ismételd … ameddig ciklus hamis feltétel esetén ismétel. Emiatt az eredeti feltételt meg kell tagadni!
Példa: írjuk át az alábbi algoritmust úgy, hogy amíg ciklus helyett ismételd … ameddig-et használjon!
beolvas n
Amíg n > 0 végezd el
│ kiír n, ' '
│ n ← n - 2
└■
Átírva:
beolvas n
Ha n > 0 akkor
│ Ismételd
│ │ kiír n, ' '
│ │ n ← n - 2
│ │ameddig n ≤ 0
│ └■
└■
Vagy:
beolvas n
Ha n > 0 akkor
│ Ismételd
│ │ kiír n, ' '
│ │ n ← n - 2
│ │ameddig NEM (n > 0)
│ └■
└■
Megjegyzés: az n = 0 bemenetre az algoritmus semmit nem kell kiírjon!
Végezd el … amíg → Amíg
Az előző két átíráshoz képest a problémánk itt most pont fordított jellegű: a végezd el … amíg ciklus legalább egy iteráció erejéig fut, még akkor is, ha a feltétele hamis (ezért is van a végére írva). Ahhoz, hogy ezt a viselkedést egy amíg ciklussal reprodukáljuk, kénytelenek leszünk megismételni a ciklus előtt azokat az utasításokat, amik a ciklustörzsben szerepelnek (feltéve, hogy egyáltalán fennállhat az a helyzet, hogy a feltétel kezdetben hamis).
Példa: amígra fogjuk átírni a következő algoritmus ismétlését.
beolvas n
Végezd el
│ kiír n, ' '
│ n ← [n / 10]
│amíg n ≠ 0
└■
Átírva:
beolvas n
kiír n, ' '
n ← [n / 10]
Amíg n ≠ 0 végezd el
│ kiír n, ' '
│ n ← [n / 10]
└■
Megjegyzés: az algoritmus az n = 0 bemenetre is ki kell írjon egy nullát, ezért az amíg előtt megismételtük a ciklusban szereplő utasításokat (hogy egyszer biztosan végre legyenek hajtva, aztán amíg a feltétel igaz, még ismétlődni fognak).
Ismételd ameddig → Amíg
Hasonlít az előzőhöz (tehát a ciklus belsejében levő utasításokat itt is leírjuk a ciklus elé), de arra is kell figyelni, hogy az ismételd … ameddig ciklus hamis feltétel esetén ismétel (ezért a feltételt meg fogjuk tagadni).
Példa: amígra fogjuk átírni a következő algoritmus ismétlését.
beolvas n
Ismételd
│ kiír n, ' '
│ n ← [n / 10]
│ameddig n = 0
└■
Átírva:
beolvas n
kiír n, ' '
n ← [n / 10]
Amíg n ≠ 0 végezd el
│ kiír n, ' '
│ n ← [n / 10]
└■
Megjegyzés: az algoritmus az n = 0 bemenetre is ki kell írjon egy nullát, ezért az amíg előt megismételtük a ciklusban szereplő utasításokat, a feltételt pedig tagadtuk, mert az amíg ciklus igaz feltétel esetén ismétel.
Végezd el … amíg → Ismételd … ameddig
A két ciklus viselkedése csak abban különbözik, hogy igaz vagy hamis feltétel esetén ismételnek, így átíráskor elég a feltételt tagadni. Például:
beolvas n
Végezd el
│ kiír n, ' '
│ n ← [n / 10]
│amíg n ≠ 0
└■
Átírva:
beolvas n
Ismételd
│ kiír n, ' '
│ n ← [n / 10]
│ameddig n = 0
└■
Ismételd ameddig → Végezd el … amíg
Az előző fordítottja (mert az ismételd … ameddig az hamis, a végezd el … amíg pedig igaz feltétel esetén ismétel).
Példa:
beolvas a, b
Ismételd
│ kiír a, ' '
│ a ← a + 2
│ameddig a > b
└■
Átírva:
beolvas a, b
Végezd el
│ kiír a, ' '
│ a ← a + 2
│amíg a ≤ b
└■
Megjegyzés: az algoritmus legalább egy értéket akkor is kiír, ha kezdetben a > b.
Minden → Amíg
Az átírás a ciklusok ismeretében egyszerű, arra kell odafigyelni, hogy a kezdeti és végső értéket is bevegyük az ismétlésbe (zárt legyen az intervallum), illetve a léptetést is mi végezzük.
Példa:
beolvas a, b
Minden k ← a, b, 2 végezd el
│ kiír k
└■
Átírva:
beolvas a, b
k ← a
Amíg k ≤ b végezd el
│ kiír k
│ k ← k + 2
└■
Megjegyzés: Előfordulhat (de nem kötelezően), hogy b értéke is ki lesz írva (pl. a = 2, b = 6).
Minden → Végezd el … amíg
Ez az átalakítás elvégezhető úgy is, hogy előbb amíg-ra, majd onnan végezd el … amíg-ra alakítunk, kis gyakorlattal viszont egyetlen lépésben is átírható (figyelni kell arra, hogy előfordulhat olyan eset, amikor a minden ciklus egy kört sem tesz meg).
Példa:
beolvas a, b
Minden k ← a, b, 2 végezd el
│ kiír k
└■
Átírva:
beolvas a, b
Ha a ≤ b akkor
│ k ← a
│ Végezd el
│ │ kiír k
│ │ k ← k + 2
│ │amíg k ≤ b
│ └■
└■
Megjegyzés: Előfordulhat (de nem kötelezően), hogy b értéke is ki lesz írva (pl. a = 2, b = 6).
Minden → Ismételd … ameddig
Az előzőhöz hasonlóan elvégezhető a minden → amíg → ismételd … ameddig vonalon haladva, vagy akár egyből is (figyelmesen):
Példa:
beolvas a, b
Minden k ← a, b, 2 végezd el
│ kiír k
└■
Átírva:
beolvas a, b
Ha a ≤ b akkor
│ k ← a
│ Ismételd
│ │ kiír k
│ │ k ← k + 2
│ │ameddig k > b
│ └■
└■
Amíg → Minden (ha lehet)
Nem mindig megoldható az átírás a minden ciklus sajátosságainak köszönhetően. Ha viszont elvégezhető (tehát előre meghatározott lépésközzel haladunk két határ között), akkor az eredetinél rövidebb leírást kapunk.
Szintén nem megoldható olyankor, ha a ciklusváltozót a ciklustörzsben módosítja az eredeti amíg ciklus, ugyanis ilyet a minden esetében konvenció szerint nem engedünk meg.
Példa:
beolvas a, b
i ← a
Amíg i ≤ b végezd el
│ kiír i
│ i ← i+1
└■
Átírva:
beolvas a, b
Minden i ← a, b végezd el
│ kiír i
└■
Más példa:
beolvas a, b
Amíg a ≤ b végezd el
│ kiír a
│ a ← a+1
└■
Átírva:
beolvas a, b
Minden i ← a, b végezd el
│ kiír i
└■
Ez utóbbinál már új változót használtunk, hogy ne legyen a kifejezés megtévesztő (Minden a ← a, b v.e.), ezért a ciklustörzsben is a helyett i-t használunk.
Végezd el … amíg → Minden (ha lehet)
Ugyanaz a helyzet, mint az amíg → minden átírásnál, elvégezhető egyetlen lépésben vagy a végezd el … amíg → amíg → minden útvonalon.
Példa:
beolvas a, b
i ← a
Végezd el
│ kiír i
│ i ← i+1
│amíg i ≤ b
└■
Átírva:
beolvas a, b
kiír a
Minden i ← a+1, b végezd el
│ kiír i
└■
Megjegyzés: az új kiírásra szükség van, mert az algoritmus akkor is ki kell írja az a értékét, ha kezdetben a >b. Mivel a-t már kiírtuk, ezért a minden ciklus a+1-től indul.
Ismételd … ameddig → Minden (ha lehet)
Ugyanaz a helyzet, mint az előzőnél, csak figyelembe kell venni, hogy az ismételd … ameddig hamis feltétel esetén ismétel.
Példa:
beolvas a, b
i ← a
Ismételd
│ kiír i
│ i ← i+1
│ameddig i > b
└■
Átírva:
beolvas a, b
kiír a
Minden i ← a+1, b végezd el
│ kiír i
└■