13. hét: állapotgépek
Czirkos Zoltán · 2025.11.26.
Állapotgépekkel és reguláris kifejezésekkel kapcsolatos laborfeladatok.
Felkészülés a laborra:
- Az állapotgépekről szóló előadás megértése.
- A fájlkezelés áttekintése.
- A sztringekről, karakterkódokról tanultak átolvasása.
Írj programot, amely a sys modul sys.stdin.read(1) függvényhívását használva karakterenként olvas be egy szöveget, majd minden beírt karakternek a karakterkódját
kiírja a kimenetére! Ha pedig elfogyott a bemenet, akkor írja ki, hogy „bemenet vége”.
Figyeld meg a program működését:
- Amíg nem nyomsz entert egy beírt sorra, nem ír ki semmit.
- Utána viszont egyszerre a teljes sor karakterkódját. Miért van ez így?
- Hogy lépsz ki a programból? Nem(!!!) Ctrl–C-vel! Hogy adsz neki fájl vége jelet?
- Minek a karakterkódja a 10?
Ilyesmi kell legyen az eredmény:
hello 104 101 108 108 111 10 Bemenet vége.
Megoldás
import sys
while True:
c = sys.stdin.read(1)
if c == "": break
print(ord(c))
print("Bemenet vége.")
Alább az előadás állapotgépes példakódját látod, az ly-számlálót.
import sys
def main():
ALAP = 1
L_VOLT = 2
LL_VOLT = 3
szaml = 0
allapot = ALAP
while True:
c = sys.stdin.read(1)
if c == "":
break
if allapot == ALAP: # szöveg kezdete
if c == "l":
allapot = L_VOLT
elif allapot == L_VOLT: # már volt egy l
if c == "l":
allapot = LL_VOLT
elif c == "y":
szaml += 1
allapot = ALAP
else:
allapot = ALAP
elif allapot == LL_VOLT: # két l volt
if c == "l":
pass
elif c == "y":
szaml += 2
allapot = ALAP
else:
allapot = ALAP
print(szaml, "darab ly volt.")
main()
Rajzold meg a forráskód alapján állapotátmeneti és tevékenységeket tartalmazó táblázatát, vagy választásod szerint az állapotátmeneti gráfot!
Megoldás
| l | y | egyéb | |
|---|---|---|---|
| alap | →l_volt | - | - |
| l_volt | →ll_volt | sz += 1, →alap | →alap |
| ll_volt | - | sz += 2, →alap | →alap |
Indulj ki az előző feladat kódjából!
Rajzolj egy új táblázatot, amelyben teljes egészében módosítod a tevékenységeket. Az új program feladata nem az
ly-ok számlálása, hanem egy „hejesírásreform” végrehajtása. Ennek a beolvasott szöveget majdnem változatlanul
kell kiírnia a kimenetre – azzal a különbséggel, hogy az ly-ok helyett j-t, a dupla
lly-ok helyett jj-t kell kiírnia. Pl. lyuk→juk, gally→gajj, viszont
majom→majom marad, és a kulcs, illetve a hallgat szavak is változatlanok maradnak. (Ezek a
példák fontos állapotátmeneteket és tevékenységeket tesztelnek.)
Megoldás
| l | y | egyéb | |
|---|---|---|---|
| alap | →l_volt | ki: c | ki: c |
| l_volt | →ll_volt | ki: "j" →alap | ki: "l", c →alap |
| ll_volt | ki: "l" | ki: "jj" →alap | ki: "ll", c →alap |
A kiírásokat itt jól meg kell gondolni. Alapállapotban mindent kiírunk, kivétel az l betűt, mert az lehet egy
későbbi ly része. l_volt állapotban bejövő y esetén kiírjuk a j-t; viszont
bejövő egyéb karakter esetén az előző l-t is ki kell írni, és a mostanit is (ilyen szó: kulcs). ll_volt
esetén pedig, ha bármi más jön, akkor az előző ll-t is ki kell írni (ilyen szó: hallgat).
A szövegfájloknál bevett szokás az, hogy a fájl legutolsó karaktere mindig egy újsor (\n) karakter. Ezt azonban sajnos nem mindenhol tartják be (és nem minden szövegszerkesztő tesz így).
Ha esetleg kap a fenti program egy olyan bemenetet, ahol a szöveg 'l' betűre végződik
(tehát nincs újsor, de még mondat vége jel sincs a bemenet végén), akkor hibázik; a kimeneten nem jelenik
majd meg ez a betű.
Emlékezz vissza, mit tanultál az előadáson a programok parancssori futtatásáról, továbbá a fájlból és fájlba átirányításról!
Parancssor gyorstalpaló
A Start menü Futtatás… parancsát választva indítsd el a cmd.exe programot! (Windows 10 esetén:
a Start gombra jobb klikk, és Futtatás, vagy Windows + R.) A továbbiakban a
megjelenő konzolablakban kell dolgozni. A föl-le billentyűkkel kiválaszthatóak a korábban beírt
parancsok, így nem kell egy dolgot többször begépelni.
Egy program indításához csak be kell írni a nevét. Pl.
notepad.exe
A legtöbb konzolos alkalmazás, de gyakran az ablakokat használó programok is, kaphatnak paramétereket. Próbaképp írd be az alábbi sort. Mit tapasztalsz?
notepad szoveg.txt
A mappát (folder) a parancssori parancsok a directory szóból származtatják (a mappák másik neve, magyarul könyvtár). A mappa tartalmának listázása:
C:\Users\111111\> dir
Mappát váltani a chdir paranccsal, vagy ennek rövidebb változatával, a
cd-vel lehet. Lépj egy szinttel feljebb:
C:\Users\111111\> cd ..
Indíts egy parancssort, és futtasd le abból a helyesírásreform programodat! Ehhez operációs rendszertől függően a program nevét
kell megadnod, vagy elé kell írnod azt, hogy python3, esetleg verziótól függően csak annyit, hogy python
(próbáld ki, a te környezetedben melyik működik). Teszteld újra a programod pl. a lyuk és gally szavakkal, utána lépj ki belőle
fájl vége jellel!
Végezd el a fájlból és fájlba átirányítást is! Erre is mutat példát a hivatkozott előadásrészlet. Hozz létre ehhez a jegyzettömbbel egy „ómagyar.txt” nevű fájlt, benne ly-okat tartalmazó szöveggel. Dolgoztasd ezt fel a programoddal, és irányítsd át a kimenetét az „újmagyar.txt” nevű fájlba!
Megoldás
A lényeg:
python3 hejesirasreform.py <ómagyar.txt >újmagyar.txt
Írj programot, amely:
- Kér a felhasználótól egy reguláris kifejezést.
- Aztán beolvassa a szavak.txt fájlt... (Ezt mentsd le a gépedre!)
- ... és csak azokat a sorait írja ki, amire illeszkedett a megadott kifejezés.
Például:
Kérem a regexet: ^..vé$ kávé kővé tűvé
Ne feledd, a szavak beolvasásához szükség lehet a fájl kódolásának megadására: encoding="utf-8" paraméter
az open() függvény számára.
Adj meg reguláris kifejezéseket, amelyekkel kilistázhatod az alábbi szavakat:
- Amelyekben van vicc (pl. vicces, de kaviccsal is)
- Almával kezdődnek (pl. almaecet, de simán alma is)
- Úgy végződnek, hogy hely (pl. táborhely, zabpehely)
- Négy betűsek, és mindkét középső betűjük n (pl. enni).
- Hat betűsek, fru-val kezdődnek (pl. fruska).
- Hosszú ó-val kezdődő és végződő szavak (pl. óceánjáró).
- Két hosszú ssz szerepel bennük (pl. összevisszaság).
- Szerepel bennük kétszer ugyanaz a négybetűs részlet (pl. tisztiszolga, rendszerszerű)
- Hat betűből állnak, kétszer ugyanaz (pl. bonbon)
- Hatbetűs tükörszavak (pl. lappal)
- Hétbetűs tükörszavak (pl. találat)
Megoldás
import re
regex = input("Kérem a regexet: ")
with open("szavak.txt", encoding="utf-8") as f:
for s in f:
s = s.rstrip()
if re.search(regex, s):
print(s)
- Vicc:
vicc - Alma:
^alma - Hely:
hely$ - Enni:
^.nn.$ - Fruska:
^fru...$ - Óceánjáró:
^ó.*ó$ - Összevisszaság:
ssz.*ssz - Tisztiszolga:
(....)\1 - Bonbon:
^(...)\1$ - Lappal:
^(.)(.)(.)\3\2\1$ - Találat:
^(.)(.)(.).\3\2\1$
Adott az alábbi három lehetséges formátum, amelyben időpontokat adhatunk meg:
23:17:06– óra, perc, másodperc, mindegyik két számjeggyel;15h 09m 53s– itt is óra, perc, másodperc, mindegyik két számjeggyel;10:15 AM– itt az óra és a perc két-két számjeggyel. Ez a formátum 12 órás;12:00 AM= éjfél,08:00 AM= reggel 8,12:00 PM= dél,05:00 PM= a délután 5 óra, azaz 17 óra.
Adj meg reguláris kifejezéseket a három formátumhoz! Írj programot, amelyik folyamatosan sorokat olvas be a bemenetről, és megmondja, hogy az első, a második, vagy a harmadik formátumban van megadva az időpont! Ha esetleg egyikben sem (hibás a bemenet), akkor írd ki azt!
Kérem az időpontot: 12:34:45 Első formátum Kérem az időpontot: 05:34 PM Harmadik formátum Kérem az időpontot: 05:34 PMMMM Hibás
Megoldás
import re
while True:
sor = input("Kérem az időpontot: ")
if sor == "":
break
if re.match(r"^\d{2}:\d{2}:\d{2}$", sor):
print("Első formátum")
elif re.match(r"^\d{2}h \d{2}m \d{2}s$", sor):
print("Második formátum")
elif re.match(r"^\d{2}:\d{2} [AP]M$", sor):
print("Harmadik formátum")
else:
print("Hibás")
Módosítsd az előző feladatban megírt reguláris kifejezéseidet úgy, hogy az egyes időpont formátumok esetén az időpontok értelmezéséhez szükséges adatokat egy zárójelezett blokk segítségével kigyűjtöd!
- Az első két formátumban: óra, perc, másodperc számok.
- A harmadik formátumban: óra, perc és az A vagy a P betű.
Írd ki ezeket a kimenetre!
Végül pedig definiálj egy időpont osztályt (óra, perc, másodperc) konstruktorral, és írj függvényt, amelynek paramétere a fenti három formátumok valamelyikékben adott időpont, visszatérési értéke pedig egy időpont objektum!
Fejleszd tovább a labor eleji „hejesírásreform” programot! Tanítsd meg az állapotgépednek, hogy kezelje helyesen
a mondatot kezdő, nagybetűs L karaktert! Rajzold meg az új állapotátmeneti táblázatot!
Hány új állapot kell ehhez? Működik helyesen a programod, ha azt írod bemenetként, Levél?
Vajon kell-e számolnod azzal, hogy mondat elejére két j-t kell írnod?
Írj állapotgépes programot, amely a beírt, csupa kisbetűkből álló szöveget úgy javítja ki, hogy minden mondat elején álló első betűt nagybetűre cseréli!
Megoldás
Mondat végét jelző írásjel után a következő betű nagybetű, de csak akkor, ha szóköz is jött. Figyelni kell, hogy az utána lévő szóköztől nem váltunk kisbetűs módra még! A gép alapállapota a nagybetűsítés, hiszen a bejövő szöveg legelső karaktere biztosan mondat elején van.
| . ! ? | szóköz, \n | egyéb | |
|---|---|---|---|
| nagybetű | ki: c | ki: c | ki: c.upper() →kisbetű |
| kisbetű | ki: c →mondatvége? | ki: c | ki: c |
| mondatvége? | ki: c | ki: c →nagybetű | ki: c →kisbetű |
Ha a laborfeladatokkal elkészültél, dolgozz a példatárban lévő feladatokon, a szorgalmi feladatokon, a minta vizsgán, vagy a házi feladatodon.
Informatikusok próbálják lekódolni az Algoritmusok és gráfok tárgyon tanult algoritmusokat. Ezzel két legyet lehet ütni egy csapásra, mert két tantárgyat is gyakoroltok egyszerre.