Materjalid koostas ja kursuse viib läbi
Tartu Ülikooli arvutiteaduse instituudi programmeerimise õpetamise töörühm
< eelmine | 8. OSA sisukord | järgmine > |
8.2 Suurem programminäide
Oleme eelnevalt tutvunud mitmesuguste võimalustega, mida programmide koostamisel saab kasutada. Programmid ei ole seni olnud väga pikad. Nüüd vaatleme veidi pikemat programmi, kus on nii varasemast tuttavaid asju, aga ka mõned sellised, millest veel juttu pole olnud.
Selles peatükis vaatleme ja täiendame ühte suuremat praktilist koodinäidet. Kas oskate alloleva koodi kohta vastata järgmistele küsimustele?
- Mis programmiga on tegemist?
- Milliseid andmestruktuure siin kasutatakse?
- Kuidas võivad sellises programmis kasuks tulla regulaaravaldised?
Programmi edukaks käivitamiseks on vaja ka tekstifaili: https://courses.cs.ut.ee/MTAT.TK.006/2018_fall/uploads/Main/sonastik.txt
Sõnastiku fail on veidi modifitseeritud variant Eesti Keele Instituudi poolt jagatavast failist.
# -- PROGRAMMI 1. OSA - FUNKTSIOON TUTVUSTUS() -- def tutvustus(): print("Inglise-eesti sõnastik (" + str(len(inglise_sõnad)) + " sõna)") print("'v' - välju") print("'a' - abi") # -- PROGRAMMI 2. OSA - FAILI SISSELUGEMINE -- f = open('sonastik.txt', encoding='UTF-8') inglise_sõnad = [] eesti_sõnad = [] rida = f.readline() while rida != '': sõnad = rida.split('\t') inglise_sõna = sõnad[0].strip().lower() eesti_sõna = sõnad[1].strip().lower() inglise_sõnad.append(inglise_sõna) eesti_sõnad.append(eesti_sõna) rida = f.readline() f.close() # -- PROGRAMMI 3. OSA - FUNKTSIOONI RAKENDAMINE JA OTSIMINE -- tutvustus() while True: otsing = input('Sisesta otsitav ingliskeelne sõna: ') otsing = otsing.lower() if otsing == 'v': break elif otsing == 'a': tutvustus() elif otsing in inglise_sõnad: print('Inglise keeles: ' + otsing) otsitava_sõna_indeks = inglise_sõnad.index(otsing) print('Eesti keeles: ' + eesti_sõnad[otsitava_sõna_indeks]) else: print('Sellist sõna pole!')
PROGRAMMIKOOD
Järgnevalt on esitatud sama programmikood koos kommentaaridega, et täpsemalt mõista, mida iga programmirida teeb:
# -- PROGRAMMI 1. OSA - FUNKTSIOON TUTVUSTUS() -- # Defineerime funktsiooni, mis trükib ekraanile programmi tutvustuse ja sõnastikus olevate sõnade arvu def tutvustus(): print("Inglise-eesti sõnastik (" + str(len(inglise_sõnad)) + " sõna)") print("'v' - välju") print("'a' - abi") # -- PROGRAMMI 2. OSA - FAILI SISSELUGEMINE -- # Avame faili 'sonastik.txt', mis on kodeeringus UTF-8 f = open('sonastik.txt', encoding='UTF-8') # Kõik sõnad sorteerime listidesse vastavalt keelele inglise_sõnad = [] eesti_sõnad = [] # Loeme failist esimese rea rida = f.readline() # Loeme failist ridu nii kaua, kuni neid jätkub while rida != '': # Jagame rea tükkideks tabulaatori (TAB) kohalt (Pythonis '\t') sõnad = rida.split('\t') # Rea esimene pool (enne tabulaatorit) on ingliskeelne sõna # strip() eemaldab tühikud ja reavahetused sõne algusest ja lõpust inglise_sõna = sõnad[0].strip().lower() # Rea teine pool (pärast tabulaatorit) on eestikeelne sõna eesti_sõna = sõnad[1].strip().lower() # Lisame ingliskeelse ja eestikeelse sõna vastavatesse listidesse inglise_sõnad.append(inglise_sõna) eesti_sõnad.append(eesti_sõna) # Loeme sisse järgmise rea, pärast seda hakkab tsükkel otsast peale rida = f.readline() # Sulgeme faili f.close() # -- PROGRAMMI 3. OSA - FUNKTSIOONI RAKENDAMINE JA OTSIMINE -- # Rakendame funktsiooni tutvustus() tutvustus() # Küsime kasutajalt sõne, otsime sellele vaste ning väljastame selle # Seda teeme lõpmatu tsükliga, mida katkestame õiges kohas käsuga 'break' while True: # Küsime kasutajalt sõna otsing = input('Sisesta otsitav ingliskeelne sõna: ') # Kui kasutaja sisestatud sõnas on suurtähti, siis nüüd teeme need väikseks otsing = otsing.lower() # Kui kasutaja sisestab 'v', siis lõpetame tsükli if otsing == 'v': # Katkestame tsükli tegevuse, programmi täitmist jätkatakse tsükli lõpust break # Kui kasutaja sisestab 'a', siis rakendame funktsiooni tutvustus() elif otsing == 'a': tutvustus() # Kui kasutaja sisestatud sõna on listis 'inglise_sõnad', siis otsime sõnale vaste ning väljastame selle elif otsing in inglise_sõnad: print('Inglise keeles: ' + otsing) # Leiame, mis indeksiga kohal on 'otsing' listis 'inglise_sõnad otsitava_sõna_indeks = inglise_sõnad.index(otsing) # Vaste on samal kohal listis eesti_sõnad print('Eesti keeles: ' + eesti_sõnad[otsitava_sõna_indeks]) # Kui ükski eelnevatest tingimustest ei ole tõene, siis sõnastikus sellist sõna ei leidu else: print('Sellist sõna pole!')
PROGRAMMI LÜHIKIRJELDUS
Nagu programmist on võimalik välja lugeda, on tegemist inglise-eesti sõnastikuga. Programmi käivitamisel loetakse sõnastiku read tekstifailist mällu ning seejärel saab teha sõnadele päringuid. Sõnastikuna on kasutatud tekstifaili, mis on UTF-8 kodeeringus (kättesaadav ülaltpoolt).
Programmi käivitamisel avaneb vaade:
Esmalt loeb programm mälusse sõnastiku. Lõik sõnastikust näeb välja niimoodi:
computer software tarkvara, arvutitarkvara
Nagu näha, eristuvad eestikeelsed sõnaseletused ingliskeelsest väljendist sellepoolest, et need on eraldatud tabulaatori ehk taandemärgiga (kirjutatakse Pythonis "\t" või '\t'). See tähendab, et iga rida tähistab uut sissekannet sõnastikus. Lugedes faili reakaupa sisse, saame iga rea puhul eristada ingliskeelsed märksõnad ja eestikeelsed vasted nende vahel oleva taande abil. Selleks kasutame funktsiooni split niimoodi: sõnad = rida.split('\t')
. Siin muutuja rida on sõne, mis sisaldab ühte rida failist. Võime mõelda, et split tükeldab antud sõne tükkideks nii, et esimene tükk on see, mis oli enne tabulaatorit ja teine tükk see, mis tuli pärast tabulaatorit.
Seega sisaldab esimene tükk ingliskeelset mõistet ja teine tükk peaks olema eestikeelne vaste sellele. Kui seda teame, siis saame eesti- ja ingliskeelsed mõisted sorteerida. Mõistete hoidmiseks kasutame andmestruktuuri, mille nimi on list (seda sai ka eelmise nädala materjalides põgusalt mainitud). List erineb teistest meile tuntud andmestruktuuridest nagu arv (int või float) ja sõne (str) selle poolest, et sinna saab salvestada mitu väärtust (infokildu) korraga. See on justkui paberite virn, kus iga listis salvestatud väärtus on üks paber. Igal paberil ehk väärtusel on ka oma indeks ehk järjekorranumber (nagu ikka programmeerimises kombeks, algab loendamine 0-st). Listis olevaid väärtusi kutsutakse selle listi elementideks ning need kirjutatakse nurksulgude ("[" ja "]") vahele. Tühja listi saame tekitada näiteks sellise omistuslausega eesti_sõnad = []
: kuna nurksulud on tühjad, siis pole selles listis ühtegi elementi.
Saladuskatte all võime öelda, et funktsioon split, millega rida tükeldasime, tagastab samuti listi. Ütlesime, et esimene tükk sisaldab ingliskeelset mõistet ning teine eestikeelset, kuid tegelikult need tükid ongi listi elemendid. Seega tagastatakse spliti toimel meile sõnedest koosnev list, mille esimeseks elemendiks on ingliskeelne mõiste ning teiseks elemendiks eestikeelne vaste.
Nüüd salvestame ingliskeelse mõiste muutujasse inglise_sõna ning selle käigus kasutame ka sõnemeetodeid strip ja lower. Esimene neist eemaldab sõne otstest kõik tühikud ja reavahetused, teine muudab kõik tähed sõnes väiketähtedeks. Samamoodi toimime ka eestikeelse vastega.
Listi lõppu saab elemente lisada käsuga append, näiteks eesti_sõnad.append(eesti_sõna)
lisab listi nimega eesti_sõnad muutuja eesti_sõna väärtuse, milleks on loomulikult sõne. Oluline on, et append lisab elemendi just listi lõppu, mitte suvalisse kohta.
Viimase tegevusena tsüklis loeme sisse uue rea failist: rida = f.readline()
. Sellega saab muutuja rida endale väärtuseks sõne, mis sisaldab järgmist rida antud failist. Kui tekstifailis järgmist rida ei ole (fail on lõppenud), siis saab eelneva käsu abil muutuja rida väärtuseks tühja sõne ehk "" või ''. Sellest tulebki tsükli jätkamistingimus: kui rida väärtus ei ole tühi sõne, siis tsükliga jätkatakse ehk loetakse järgmine rida.
Niimoodi saamegi kogu faili loetud ja lõpuks on meil listid eesti_sõnad ja inglise_sõnad, mis sisaldavad vastavaid mõisteid. Tuleks märgata, et listides on elemendid täpselt samas järjekorras - see tähendab, et eestikeelsele mõistele, mis asub listis eesti_sõnad indeksil 1, vastab ingliskeelne mõiste, mis on listis inglise_sõnad indeksiga 1. Seega on kokkusobivate mõistete indeksid võrdsed.
Nüüd algab programmiosa, mis tegeleb ka kasutajaga suhtlemisega.
Esmalt väljastatakse eelnevalt defineeritud funktsiooni rakendamise teel sissejuhatav tekst. Seejärel küsitakse kasutajalt otsitav ingliskeelne sõna ning teisendatakse selle tähed väiketähtedeks. Siis kontrollitakse, kas kasutaja sisestas tähe "v": kui ta seda tegi, siis väljutakse tsüklist käsuga break. Kui kasutaja sisestatud sõne oli midagi muud, siis kontrollitakse, kas tegemist oli tähega "a" (sel juhul väljastatakse jällegi sissejuhatav abitekst).
Kui kasutaja ei sisestanud "a" ega "v", siis kontrollime, kas ta sisestus on üks listi inglise_sõnad elementidest. Seda kontrollitakse võtmesõnaga in: otsing in inglise_sõnad
tagastab True, kui inglise_sõnad sisaldab elementi, mille väärtus on võrdne muutuja otsing väärtusega, vastasel juhul tagastatakse False. Kui eelnev tingimus on täidetud, siis leidub meil sõnastikus see sõna, mida kasutaja soovis. Kui see tingimus täidetud ei ole, siis minnakse tingimuslause else-harru ning väljastatakse vastav teade.
Oluline on märgata, et tingimuslauses täidetakse alati täpselt üks haru. Kui üks tingimustest on tõene, siis täidetakse see haru, kui aga ükski tingimus tõene pole, siis täidetakse else-haru.
Soovitame programm ühe korra veel üle vaadata ja mõelda läbi, kas saite aru, kuidas kõik töötab.
< eelmine | 8. OSA sisukord | järgmine > |