Testi

V isti direktorij odzipaj vse datoteke iz testi-tecajna-lista.zip. Poleg običajnih testov boš dobil še tri datoteke. V tecajnica.txt je tečajnica, kakršno dobimo na NLB.

Obvezna naloga

Napiši funkcijo preberi(ime_dat), ki prebere tečajnico v slovar, katerega ključi so valute, vrednosti pa terke s prodajnim in nakupnim tečajem te valute. Če ji podamo kot argument "tecajnica2.txt", vrne {'GBP': (0.8639, 0.8399), 'USD': (1.0748, 1.0508)}.

Napiši funkcijo izpisi(tecajnica, valute), ki (ime je zavajajoče!) vrne niz z lepo oblikovanim "izpisom" podanih valut. Niz mora oblikovan natančno tako, kot zahteva naloga. Če pokličemo `izpisi(tecajnica, ["GBP", "USD", "RUB", "HRK", "HUF"]), mora vrniti niz

GBP......0.8639......0.8399
USD......1.0748......1.0508
RUB.....71.9393.....66.5393
HRK......7.6508......7.4208
HUF....315.8900....307.0900

Napiši funkcijo zapisi(ime_dat, tecajnica), ki ustvari datoteko s podanim imenom (ime_dat) in vanjo zapiše tečajnico v enaki obliki, kot je gornja, za vse valute v podani tecajnica in to v abecednem vrstnem redu.

Datoteka, ki jo izpiše, mora biti točno taka kot datoteka "pravilna.txt". Pazi, da je ne spremeniš: testi v resnici preverjajo, ali je datoteka, ki si jo sestavil, enaka datoteki "pravilna.txt".

Navodilo za delo: znajdi se. Naloge se lahko lotiš z običajnimi metodami nizov (split in podobne), lahko pa uporabiš kakšno knjižnico, ki jo dobimo s Pythonom. Dodatne knjižnice pa so prepovedane (iz preprostega razloga: ne bomo jih nameščali samo za to, da bi testirali vaš program ;).

Rešitev

Branje: odpremo datoteko ter preberemo in vržemo stran prvo vrstico (f.readline()). Nato gremo z zanko for čez datoteko (for vrstica in f). Zdaj pa bomo hitro opravili: v vrstici zamenjamo vejice s pikami, jo razbijemo na kose in vzamemo le zadnje tri, torej vrstica.replace(",", ".").split()[-3:]. Kar dobimo, shranimo kot ime, nakupni, prodajni. V slovar tecajnica pod ključ ime zapišemo terko z vrednostjo nakupni in prodajni, ki ju mimogrede pretvorimo v float.

def preberi(ime_dat):
    f = open(ime_dat)
    f.readline()
    tecajnica = {}
    for vrstica in f:
        ime, nakupni, prodajni = vrstica.replace(",", ".").split()[-3:]
        tecajnica[ime] = float(nakupni), float(prodajni)
    return tecajnica

Izpis: naredimo prazen niz. Sprehodimo se čez vse valute, ki jih je potrebno izpisati. Iz slovarja vzamemo nakupni in prodajni tečaj ter to dodamo primerno oblikovano v niz. Primerna oblika je takšna, da vzamemo najprej ime, nato pa oba tečaja, ki ju poravnamo s piko, na 12 mest, od tega 4 decimalke (:.>12.4f).

def izpisi(tecajnica, valute):
    s = ""
    for valuta in valute:
        nakupni, prodajni = tecajnica[valuta]
        s += "{}{:.>12.4f}{:.>12.4f}\n".format(valuta, nakupni, prodajni)
    return s

Zapis v datoteko: odpremo datoteko in vanjo zapišemo, kar vrne gornja funkcija, pri čemer zahtevamo, da izpiše vse valute, sortirane po abecedi.

def zapisi(ime_dat, tecajnica):
    open(ime_dat, "w").write(izpisi(tecajnica, sorted(tecajnica)))

Dodatna naloga

Bolj uraden vir tečajev je Banka Slovenije. Ta objavlja tečajno listo na strani http://www.bsi.si/_data/tecajnice/dtecbs.xml. Če to stran odprete v brskalniku, jo bo pokazal lepšo, kot je v resnici. V resnici pa je vse to besedilo nabasano v eno samo vrstico, brez presledkov.

Tvoja naloga tokrat ni prebrati datoteko, temveč prebrati to spletno stran in jo zložiti v podoben slovar, kot zgoraj, le da bo pri vsaki valuti navedena le ena vrednost.

Malo pomoči: vsebino spletne strani lahko prebereš z

import urllib.request
xml = urllib.request.urlopen("http://www.bsi.si/_data/tecajnice/dtecbs.xml").read().decode("ascii")

Po tem bo xml niz z vsebino strani. Najboljše, da si ga izpišeš s print, da boš videl(a), kako grd je.

Rešitev

Tole je kar zoprno. Vse skupaj dobimo kot en niz. "Posplitamo" ga po oznaka=", da ga razbijemo na valute. V delčkih, ki jih dobimo, bodo prvi trije znaki vedno ime valute, tisto kar je med prvim znakom > in prvim < pa bo vrednost. Ni težko, je pa grdo.

def preberi_bs():
    import urllib.request
    xml = urllib.request.urlopen("http://www.bsi.si/_data/tecajnice/dtecbs.xml").read().decode("ascii")
    vrstice = xml.split('oznaka="')[1:]
    tecajnica = {}
    for vrstica in vrstice:
        valuta = vrstica[:3]
        vrstica = vrstica[vrstica.index(">")+ 1:vrstica.index("<")]
        tecajnica[valuta] = float(vrstica)
    return tecajnica

Predvsem pa se to ne dela tako. Ta oblika zapisa, xml, služi prav temu, da bi ga bilo lahko brati s programom. In v resnici ga je, le pravi modul potrebujemo. (Za domačo nalogo seveda nisem pričakoval takšne rešitve. Če je kdo rešil na ta, pravi način, pa ni seveda nič narobe.)

def preberi_bs():
    import urllib.request
    from xml.dom import minidom
    bs = minidom.parse(urllib.request.urlopen("http://www.bsi.si/_data/tecajnice/dtecbs.xml"))
    return {tecaj.getAttribute("oznaka"): float(tecaj.childNodes[0].nodeValue)
            for tecaj in bs.getElementsByTagName("tecaj")}
Zadnja sprememba: četrtek, 25. marec 2021, 18.24