2. hét: nyomkövetés, vezérlés
Czirkos Zoltán, Frey Balázs, Bulla Ádám · 2024.09.22.
Nyomkövetés. Vezérlési szerkezetek: elágazások, ciklusok. Összetett vezérlési szerkezetek, összefüggő ciklusok és független változók.
Felkészülés a laborra:
- A vezérlési szerkezetekről tanultak megértése.
Adott az alábbi program.
egyik = input("Írj be valamit: ")
masik = input("Írj be még valamit: ")
print(egyik + masik)
Másold be a fejlesztőkörnyezetbe, és futtasd le! Mi történik akkor, ha azt írod be neki, hogy alma, és hogy fa? És mi történik akkor, ha 2-t és 3-at írsz be neki? (Miért nem 5?) Magyarázd meg (magyar nyelvű szövegben), hogy mi történik!
Ha ez megvolt, írd át a programot ilyenre:
egyik = int(input("Írj be valamit: "))
masik = int(input("Írj be még valamit: "))
print(egyik + masik)
Figyeld meg, mi a különbség a kódban! Az első két sor változott, a harmadik nem. Próbáld most ki 2-vel és 3-mal! Mit tapasztalsz? Mi történik akkor, ha most próbálod beírni az előbbi szavakat? Magyarázd meg az eredményt!
Az előadás szorzótáblás programjánál szóba jött,
hogy létezik egy tabulátor nevű karakter, és hogy azt "\t"
-vel kell a forráskódban megadni. Ennek kapcsán pedig arról
is, hogy a különleges karaktereket \
visszaperrel kell jelölni, ha szöveg belsejében szerepelnek
a forráskódban.
Írd ki egyetlen egy print()
utasítással az alábbi szövegeket! Ügyelj arra, hogy ahol
két sorban vannak a minta szerint a kimenetek, ott a programodnak is úgy kell megjelenítenie őket.
A print('hello') kiírja, hogy "hello", és kezd egy új sort.
A "\t" karaktert tabulátornak nevezzük. A következő 8-cal osztható sorszámú oszlopra lehet ugrani vele.
Írj programot, amely segít kiszámolni a felhasználónak, hogy hány doboz festéket kell vennie a lábakon álló tartály festéséhez! Ehhez használnod kell majd az első előadásokon tanultakat. Indulj ki az előadáson bemutatott kör kerülete és területe programból!
A tartálynak ismerjük a magasságát és az átmérőjét. Mindenhol le kell festeni, az oldalát, a tetejét és az alját is. Tudjuk azt is, hogy egy doboz festék 2 m2 felület lefestéséhez elegendő.
Tartály festése Milyen magas? 2 Mennyi az átmérője? 1.2 4.900885 doboz festék kell.
Figyelj arra, hogy a program kódjában tizedesvessző helyett tizedespontot kell használni (pl. 3.14
, persze jó a
math.pi
is), ugyanígy a bemenet megadásánál is. Ha nem jön ki a fenti eredmény, gondold át, helyes-e a képlet, amit
használsz.
Megoldás
print("Tartály festése")
magas = float(input("Milyen magas? "))
atmero = float(input("Mennyi az átmérője? "))
sugar = atmero/2
doboz = (2 * sugar**2 * math.pi + magas * 2 * sugar * math.pi) / 2
print(doboz, "doboz festék kell.")
Írj programot, amely a felhasználótól bekéri két síkbeli pont x
és
y
koordinátáit, és kiírja a közéjük húzott egyenes szakasz hosszát (Pitagorasz tételével)!
szakasz | hossz |
---|---|
(0;0)–(1;1) | 1.414214
|
(1;5)–(4;1) | 5
|
(-3;2)–(5;7) | 9.433981
|
Megoldás
import math
x1 = float(input("x1 = "))
y1 = float(input("y1 = "))
x2 = float(input("x2 = "))
y2 = float(input("y2 = "))
hossz = math.sqrt((x1-x2)**2 + (y1-y2)**2)
print(hossz)
Hasonló feladatok
Ha ez a feladat nehezen ment, megoldhatsz pár hasonló feladatot a példatárból, mielőtt a következő feladatra rátérsz.
Vigyázz, a laborfeladatokat erősen ajánlott az utolsó feladatig megoldani, hogy a jövő hétre felkészült legyél. Ha nem sikerül, fejezd be őket otthon!
Írj programot, amely az ax2+bx+c=0
másodfokú egyenlet együtthatóit kérdezi a felhasználótól! Ezek valós
számok. Ezek után írja ki az egyenlet x1
és x2
megoldását! A megoldóképlet:
Próbáld ki a bal oldalt látható egyenletekre! Ezekkel ellenőrizni tudod a megoldásod. Próbáld ki aztán a jobb oldali egyenletekre is. Mit tapasztalsz? Miért?
egyenlet | megoldás |
---|---|
2x2-x-6 = 0 | x1=2, x2=-1.5 |
x2-12x+35 = 0 | x1=5, x2=7 |
egyenlet | megoldás |
---|---|
2x2-4x+2 = 0 | ? |
x2+2x+10 = 0 | ? |
Írd át úgy a programot, hogy figyelembe vegye azokat az eseteket, amikor nincs, vagy csak egy valós gyök van, és eszerint végezd a kiírást! Ehhez a diszkriminánst kell megvizsgálni, ami a gyökjel alatti rész. Például, ha ott negatív szám van, nincsen valós megoldás, mert nem lehet negatív számból gyököt vonni.
Megoldás
Arra kell figyelni, hogy ne vonj negatív számból négyzetgyököt. A gyökvonás előtt a diszkrimináns vizsgálatával meg kell nézni, hány valós megoldás lesz.
Itt egy nagyobb kifejezést kapsz, amiben többféle operátor (összeadás, kivonás, szorzás stb.) szerepel. Ezeknek a műveleteknek Pythonban ugyanúgy van precedenciája, mint a matematikában. A szorzás pl. magasabb rendű művelet, mint az összeadás. A nyelv precedencia szabályai összetettebbek; erről majd előadáson lesz szó.
A diszkr == 0
vizsgálat elméletben helyes, gyakorlatban azonban nem előnyös ilyet írni. A kerekítési hibák
miatt előfordulhat az, hogy 0-hoz olyan közeli szám adódik, amit már 0-ra kerekít a számítógép. Erről is később lesz szó
előadáson.
import math
a = float(input("a: "))
b = float(input("b: "))
c = float(input("c: "))
diszkr = b**2 - 4* a * c
if diszkr > 0:
x1 = (-b - math.sqrt(diszkr)) / (2*a)
x2 = (-b + math.sqrt(diszkr)) / (2*a)
print("x1: ",x1)
print("x2: ",x2)
elif diszkr == 0:
print(-b / (2*a))
else:
print("Az egyenletnek nincs megoldása")
Hasonló feladatok
Ha ez a feladat nehezen ment, megoldhatsz pár hasonló feladatot a példatárból, mielőtt a következő feladatra rátérsz.
Vigyázz, a laborfeladatokat erősen ajánlott az utolsó feladatig megoldani, hogy a jövő hétre felkészült legyél. Ha nem sikerül, fejezd be őket otthon!
Olyan programot kell írnod, amelyik számtani sorozatot jelenít meg.
- A számtani sorozat differenciáját a felhasználó adhassa meg! A sorozat két határát (alsó és felső) is! Ezek egész számok kell legyenek.
- Hogy „reagálja le” a program azt, ha rossz sorrendben adod meg a határokat?
Javítsd meg, hogy ilyenkor is működjön! Ezt legjobb úgy csinálni, ha a két határt
nem
mn
ésmx
, hanem valamilyen semleges nevű változóba teszed először (pl.hatar1
,hatar2
), mert amíg nem vizsgáltad meg őket, addig nem jó ötlet minimumnak és maximumnak nevezni. Tehát olvasd be őket, vizsgáld meg a sorrendet, és utána kerüljenekmn
-be ésmx
-ba a számok! Hogy miért nemmin
ésmax
a változók nevei, arról majd később tanulunk. (itt nem okozna egyébként gondot...)
Megoldás
diff = int(input("Mennyi a sorozat differenciája?"))
hatar1 = int(input("Mennyi a sorozat egyik határa?"))
hatar2 = int(input("Mennyi a sorozat másik határa?"))
if hatar1 <= hatar2:
mn = hatar1
mx = hatar2
else:
mn = hatar2
mx = hatar1
szam = mn
while szam <= mx:
print(szam)
szam = szam+diff
Hasonló feladatok
Ebben a témakörben is találsz még feladatokat a példatárból. Ha úgy érzed, oldj meg onnan néhányat a továbblépés előtt. De vigyázz, az itteni feladatokat ajánlott végig megoldani a jövő hétre, hogy felkészült legyél.
A programozási hibákat gyakran nehéz megtalálni, de sokat segít a nyomkövetés. Ennek segítségével a programot megállíthatjuk futás közben, végrehajthatjuk soronként, közben megfigyelhetjük a változók értékeit. Ez azért jó, mert:
- Rögtön észre tudjuk venni, ha épp „elromlott” egy változó: rossz volt a gondolatmenetünk, algoritmusunk, és nem azt tettük bele, amit szerettünk volna.
- Azt is látjuk, ha kódolási hibánk van; ha nem azt a műveletet végzi el a programsor, mint amit szántunk neki. Például mert lefelejtettünk egy zárójelet, tehát kódolási hibánk van.
A nyomkövetés kipróbálásához, megtanulásához tedd a következőket. Először is másold be ezt a programot egy új fájlba:
n = 1
while n <= 10:
print(n, end=" ") # nem kezd új sort
n += 1
print(".")
Mentés után a Shell ablak menüjében kattints a Debug / Debugger
menüpontra. Erre megjelenik egy Debug Control nevű ablak. Ebben pipáld be a [ ] Source
jelölőnégyzetet! Utána
a program ablakában a szokásos Run / Run module
menüpontra kattints.
A program ilyenkor elindult, de még egyelőre meg van akasztva a legelső sor előtt. A Debug Control ablak
Over
gombjának nyomkodásával lehet végrehajtani a következő sort. A befejezett ciklustörzsek után a kimeneten
elkezdenek megjelenni a számok. A forráskódban látszik, melyik az aktuális sor, a szürke sáv mutatja, hol tart épp a végrehajtás. A
Debug Control ablakban pedig (sok jelenleg nem lényeges információ mellett) a változó értéke figyelhető meg:
Kattints még sokszor az Over
gombra, közben figyeld a kimenetet és a Shell ablakot!
Miután kitapasztaltad, válaszolj a nyomkövető használatával az alábbi kérdésekre!
- Mennyi az alábbi programban az
n
változó értéke, amikor a legalsó sorhoz ér a végrehajtás, aprint(".")
-hoz?n = 1 while n <= 10: print(n, end=" ") # nem kezd új sort n += 1 print(".")
- Alább egy program, amely 8 faktoriálisát számítja ki, és 40320-at ír a kimenetre.
Értsd meg a nyomkövető segítségével a program működését! A nyomkövető használatával – újabbszorzat = 1 n = 8 while n > 1: szorzat *= n n -= 1 print(szorzat)
print()
beírása nélkül – mondd meg, hogy mennyi aszorzat
változó értéke, amikor azn
változó éppen3
-ra változott!
Megoldás
A válasz: szorzat = 6720. Mivel a ciklus visszafelé megy, ez a változó nem a faktoriálisok értékeit veszi fel menet közben.
- A következő program Euklidész algoritmusa segítségével határozza meg két szám legnagyobb közös osztóját, jelen esetben az 11220-ét és a 2002-ét, ami 22:
a = 11220
b = 2002
while b > 0:
temp = b
b = a % b
a = temp
print("lnko =", a)
Megint új print()
beírása nélkül: mennyi a b
változó
értéke, amikor az a
épp 374-re változott? Megoldás
Itt: b = 44.
Írj egy programot, amely kér a felhasználótól egy számot, és kirajzol egy + és − jelekből álló szakaszt. Pl. ha a szám 4, akkor a képernyőn a lenti ábra jelenjen meg, vagyis a belsejében 4 db − legyen:
Mekkora legyen a szakasz? 4 +----+
Írd meg a programot előbb úgy, hogy ciklust használsz a – jelek kiírásához!
Aztán próbáld ki, mi történik a print("-" * 4)
sor hatására. Hogy lehetne ezt felhasználni? Írd meg így is a
programot!
Megoldás
Ciklussal:
print("Mekkora legyen a szakasz?")
hossz = int(input())
print("+", end="")
i = 0
while i < hossz:
print("-", end="")
i = i+1
print("+")
Sztring többszörözésével:
print("Mekkora legyen a szakasz?")
hossz = int(input())
print("+", end="")
print("-" * hossz, end="")
print("+", end="")
Még rövidebben:
print("Mekkora legyen a szakasz?")
hossz = int(input())
print("+", "-" * hossz, "+", sep="")
Az előző feladat rajzolást végző programrészéből készíts egy olyan másolatot, amely + és - karakterek helyett | és . karaktereket használ, mint jobb oldalon! Végül pedig, ezt ciklusba téve, írj egy olyan változatot, amelyben egy adott méretű négyzet jelenik meg.
|....|
+----+ |....| |....| |....| |....| +----+
A forráskód szerkesztését kényelmesebb billentyűzeten végezni, mint egérrel. Szinte minden funkció elérhető gyorsbillentyűkön keresztül. Néhány fontosabb:
- Home, End: sor elejére, sor végére ugrás,
- Shift + ↑, ↓, ←, →: forráskódrészlet kijelölése,
- Ctrl + ], Ctrl + [: a kijelölt részlet indentálása (különösen hasznos ennél a feladatnál: amikor egy meglévő kódrészletet szeretnél ciklusba betenni, vagy ciklusból kivenni!),
- Ctrl + C, Ctrl + V: a szokásos másolás és beillesztés,
- Ctrl + Z: „undo”, szerkesztés visszavonása.
Megoldás
Ciklussal:
print("Mekkora legyen a négyzet?")
hossz = int(input())
# Felső sor
print("+", end="")
i = 0
while i < hossz:
print("-", end="")
i = i+1
print("+")
# Közepe
j = 0
while j < hossz:
print("|", end="")
i = 0
while i < hossz:
print(".", end="")
i = i+1
print("|")
j = j+1
# Alsó sor, mint a teteje
print("+", end="")
i = 0
while i < hossz:
print("-", end="")
i = i+1
print("+")
Sztring többszörözésével lehetne rövidebben is.
Írjunk programot, amely kér a felhasználótól egy számot (n), és utána egy akkora háromszöget rajzol a képernyőre „o” betűkből, hogy annak éppen a megadott számú sora van! Például n=3 esetén az itt látható ábra keletkezzen.
o ooo ooooo
Megoldás
A feladat megoldásának kulcsa egy rajz készítése… És annak meghatározása, hogy melyik sorban hány golyó és hány szóköz van. Aki ide eljut, annak nyert ügye van.
- Minden sor egyforma: sok szóköz, aztán sok golyó. A rajzon pötty helyettesíti a kiírandó szóközöket.
- Egy sor kiírása: ciklusban szóköz, ciklusban golyó. Aztán új sor kezdése.
- Ha ez megvan, ezt kell ciklusba tenni.
···o ··ooo ·ooooo ooooooo
Ciklusokkal:
magas = int(input("Milyen magas legyen a kupac?"))
sor = 0
while sor < magas:
# A sorok elejére kellenek szóközök
oszlop = 0
while oszlop < magas-sor-1:
print(" ", end="")
oszlop = oszlop+1
# Utána valamennyi darab o
oszlop = 0
while oszlop < sor*2+1:
print("o", end="")
oszlop = oszlop+1
print()
sor = sor+1
Sztring többszörözésével:
print("Milyen magas legyen a kupac?")
magas = int(input())
sor = 0
while sor < magas:
print(" " * (magas-sor-1) + "o" * (sor*2+1))
sor = sor+1
Hasonló feladatok
Itt mindig az a lényeg, hogy a rajz alapján rájöjj, milyen vezérlési szerkezettel állítható az elő. Ebben a témakörben is találsz még feladatokat a példatárból.
Ha a laborfeladatokkal elkészültél, dolgozz a példatárban lévő feladatokon, a szorgalmi feladatokon, a minta zárthelyin, vagy a házi feladatodon.
Informatikusok próbálják lekódolni az Algoritmusok és gráfok tárgyon tanult algoritmusokat. A félév elején még nem biztos, hogy minden egyszerűen menni fog, de ahogy megismeritek a vonatkozó adatszerkezeteket és nyelvi elemeket, egyre könnyebb lesz. Ezzel két legyet lehet ütni egy csapásra, mert két tantárgyat is gyakoroltok egyszerre.