Arvutiteaduse instituut
  1. Kursused
  2. 2024/25 kevad
  3. Programmeerimise alused (MTAT.03.236)
EN
Logi sisse

Programmeerimise alused 2024/25 kevad

  • Pealeht
  • 1. Sissejuhatus
  • 2. Tingimuslause
  • 3. Tsükkel
  • 4. Järjend ja for-tsükkel
  • 5. Funktsioon
  • 6. Andmevahetus. Lihtne kasutajaliides
  • Loengud
  • Moodle
  • Lahendus
  • Thonny paigaldamine
  • Thonny logide esitamine
  • Silumine
  • Kiireksamist
  • Viited
< eelmine6. nädala sisukordjärgmine >

6.3 Faili kirjutamine

TÜHJA FAILI

Eespool oleme tutvunud mitmete võimalustega, kuidas failist andmeid lugeda. Failid ise on meil varem olemas olnud või oleme need teinud tekstiredaktoriga (ka Thonnyga kui tekstiredaktoriga). Nüüd vaatame, kuidas isetehtud programmiga andmeid faili kirjutada. Selleks pakub võimalusi funktsioon write (ingl kirjuta).

Järgmine programm kirjutab kasutajalt küsitud andmed faili.

nimi = input("Palun sisesta oma nimi: ")
vanus = input("vanus: ")
aadress = input("aadress: ")

f = open("andmed3.txt", "w")
f.write(f"{nimi}\n")
f.write(f"{vanus}\n")
f.write(f"{aadress}\n")
f.close()

Faili kirjutamiseks tuleb funktsioonile open anda ka teine argument väärtusega "w" (nagu write). Kui sellise nimega fail juba eksisteerib, siis open(..., "w") teeb selle tühjaks. Erinevalt funktsioonist print ei tekita funktsioon write automaatselt reavahetusi. Selleks, et saada eri andmeid eri ridadele, lisasime reavahetuse sümboli käsitsi.

Proovime kirjutada programmi, mis küsib kasutajalt kaks failinime. Esimene fail peaks olema juba olemas ja seal peaks olema mingi tekst. Teine fail võiks olla uus. Programmi ülesanne on võtta esimese faili sisu, teisendada see suurtähtedesse ning kirjutada teise faili.

allikafaili_nimi = input("Mis failist info võtta? ")
sihtfaili_nimi = input("Millisesse faili info pannakse? ")

allikafail = open(allikafaili_nimi, encoding="UTF-8")
sihtfail = open(sihtfaili_nimi, "w")

for rida in allikafail:
    sihtfail.write(rida.upper())

allikafail.close()
sihtfail.close()

Programm töötab nii, et ekraanile ei väljastata midagi. Ometi on tegemist võimsa vahendiga - me saame failides olevad andmed teatud muudatustega teise faili kanda. Tähtede suureks muutmine ei ole muidugi midagi eriti võimsat, aga põhimõtteliselt saab nii palju keerulisemaid ja ka vajalikumaid asju teha. Võib-olla mingeid andmeid üldse mitte teise faili lubada!?

Ka faili kirjutamiseks saab määrata kodeeringu, näiteks open(sihtfaili_nimi, "w", encoding="UTF-8").

FAILI JUURDE. TEMPERATUURID VEEBIST FAILI

Eelmistes näidetes avasime selle faili, kuhu kirjutada tahtsime nii, et funktsiooni open teine argument oli "w". Kui fail oli juba olemas, siis tehti see fail enne kirjutamist tühjaks. Kui teine argument on "a", siis kirjutatakse olemasoleva faili lõppu. Kui sellist faili pole, siis see luuakse. Argument "a" tuleb ingliskeelsest sõnast append (lisa).

Järgmises programmis ongi faili avamisel teine argument "a"- kui fail on enne olemas, siis lisatakse ridu selle lõppu. Samuti saab ka siin määrata kodeeringu, näiteks open(faili_nimi, "a", encoding="UTF-8").

Programmi loeb aadressilt http://meteo.physic.ut.ee/ aasta 2024 jaoks iga päeva keskmise temperatuuri ja kirjutab selle faili. Programm töötab umbes pool minutit. Kui võtta vähem kui terve aasta andmed, siis töötaks kiiremini. Programmis kasutatakse kahekordset tsüklit, mille põhjalikum käsitlus jääb sellest kursusest välja.

from urllib.request import urlopen

fail = open("andmed.txt", "a")  # fail avatakse juurde kirjutamiseks
päevad = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
aasta = 2024

for kuu in range(1, 13):  # välimine tsükkel kuude järjenumbrite kaupa
    for päev in range(1, päevad[kuu - 1] + 1):  # sisemine tsükkel päevade kaupa
        # konkreetse päeva andmed
        vastus = urlopen("http://meteo.physic.ut.ee/et/showperiod.php?type=setday&year=" + str(aasta) + "&month=" + str(kuu) + "&day=" + str(päev))
        baidid = vastus.read()
        tekst = baidid.decode()

        otsitav = "<SMALL>keskmine</SMALL><BR><B>"
        algus = tekst.index(otsitav)  # leitakse õige koht
        temp_algus = algus + len(otsitav)  # siit algab temperatuur
        deg = tekst.index(" &deg;")  # siin lõpeb
        temp = tekst[temp_algus:deg]  # viilutades leitakse temperatuur
        # funktsioon rjust paneb ühekohalisele päeva ja kuu järjenumbrile 0 ette, et oleks kahekohaline.
        fail.write(str(päev).rjust(2, "0") + "." + str(kuu).rjust(2, "0") + "." + str(aasta) + ": " + str(temp) + "\n")

        vastus.close()  

fail.close()
print("Andmed kirjutatud faili.")

Valikvastustega enesekontrolliülesanne

Automaatkontrolliga enesekontrolliülesanne

ŠIFREERIMINE

Tegeleme nüüd natuke salakirjadega. Nimelt ei kirjuta me faili mitte sümboli enda, vaid hoopis teise sümboli. Näiteks A asemel kirjutame tähestikus 4 kohta tagapool oleva tähe E. Näiteks on AEG on siis hoopis EIK. Tegemist on nihkešifriga, mis on ajalooliselt tuntud šifreerimisviis. Kui nihe on teada, siis on teksti lihtne käsitsigi dešifreerida, rääkimata arvutiga. Isegi siis, kui nihe pole teada, saab dešifreerimisega suhteliselt hõlpsasti hakkama.

Ühe tähe teiseks nihutamisel oleks mõistlik tähed nummerdada ja siis vastavalt nihke järjekorranumbrile juurde liita või sellest (dešifreerimise korral) lahutada. Väga loomulik oleks näiteks A järjekorranumbriks võtta 1, B korral 2 jne. Seda me siiski ei tee, sest tähtedel ja tegelikult paljudel teistelgi (sealhulgas nähtamatutel) märkidel on sellised järjekorranumbrid juba olemas. Vastava järjekorranumbri saame teada funktsiooniga ord. Katsetage järgmist programmi.

print(ord("A"))
print(ord("a"))
print(ord("ä"))
print(ord("õ"))
print(ord(" "))

Näeme, et täpitähed on meie loomulikust tähestikust hoopis eemal.

Vastupidi jälle funktsiooniga chr saame teada arvule vastava märgi.

print(chr(65))

Proovige ka päris suurte arvudega. Räägime neist pikemalt selle nädala silmaringimaterjalis.

Nüüd aga siis programm, mis kirjutab teksti šifreeritult faili.

def kodeeri(sümbol, nihe):
     return chr(ord(sümbol) + nihe)

def šifreeri(failinimi, nihe):
    f = open(failinimi, "w")
    kiri = input("Sisesta lause ")
    for sümbol in kiri:
        f.write(kodeeri(sümbol, nihe))
    f.close()

failinimi = input("Faili nimi? ")
nihe = int(input("Nihe? "))
šifreeri(failinimi, nihe)
def kodeeri(sümbol, nihe):
     return chr(ord(sümbol) + nihe)

def šifreeri(failinimi, nihe):
    f = open(failinimi, "w")
    kiri = input("Sisesta lause ")
    for sümbol in kiri:
        f.write(kodeeri(sümbol, nihe))
    f.close()

def dešifreeri(failinimi, nihe):
    f = open(failinimi)   
    while True:
        sümbol = f.read(1) # loetakse üks sümbol
        if sümbol == "": # kui enam pole
            break # tsükkel katkestatakse
        print(kodeeri(sümbol, -nihe), end = "")
    f.close()



tegevus = input("Šifreeri (s) / Dešifreeri (d) ")
failinimi = input("Faili nimi? ")
nihe = int(input("Nihe? "))

if tegevus == "s":
    šifreeri(failinimi, nihe)
elif tegevus == "d":
    dešifreeri(failinimi, nihe)
else:
    print("Sellist tegevust pole")

Katsetage šifreerimise programmi.

Nüüd on aga küsimus, kuidas salakiri dešifreerida. Toome siin mõned ideed, mis võivad selles aidata.

  • Funktsioon dekodeeri on funktsioonile kodeeri üsna sarnane. Kui šifreerimisel tuli nihe liita, siis dešifreerimisel tuleb see lahutada.
  • Kui šifreerimisel avati fail kirjutamiseks, siis dešifreerimisel tuleb see avada lugemiseks.
  • Sümbolite ühekaupa käsitlemiseks saab kasutada sellist tsüklit
   
    while True:
        sümbol = f.read(1) # loetakse üks sümbol
        if sümbol == "": # kui enam pole
            break # tsükkel katkestatakse
        print(dekodeeri(?????????), end = "") # reavahetust ei tule

Küsimärgid tuleb asendada vastavalt sellele, kuidas funktsioon dekodeeri tehtud on.


< eelmine6. nädala sisukordjärgmine >
  • Arvutiteaduse instituut
  • Loodus- ja täppisteaduste valdkond
  • Tartu Ülikool
Tehniliste probleemide või küsimuste korral kirjuta:

Kursuse sisu ja korralduslike küsimustega pöörduge kursuse korraldajate poole.
Õppematerjalide varalised autoriõigused kuuluvad Tartu Ülikoolile. Õppematerjalide kasutamine on lubatud autoriõiguse seaduses ettenähtud teose vaba kasutamise eesmärkidel ja tingimustel. Õppematerjalide kasutamisel on kasutaja kohustatud viitama õppematerjalide autorile.
Õppematerjalide kasutamine muudel eesmärkidel on lubatud ainult Tartu Ülikooli eelneval kirjalikul nõusolekul.
Courses’i keskkonna kasutustingimused