(* opk01.h4.p SJ *) program TiliSiirtotehtava; (* Käsitellään TiliSiirtoja, ainakin luetaan ja tulostetaan *) (* Jatketaan tätä vielä myöhemmin *) const ViitePituus = 20; (* sisältää tarkastusnumeron *) TiliNroLoppuPituus = 10; (* tilinumeron loppuosa *) TiliNroAlkuPituus = 6; (* tilinumeron pankkikoodi *) TiliNroErotin = '-'; (* edellisten erotin *) VaihtoSuhde = 5.94573; (* mk/euro *) ViestiRiveja = 4; (* max viestin rivimäärä *) ViestiRivinPituus = 40; (* max viestin rivipituus *) NimenPituus = 30; (* saajan, maksaja, yms nimi *) PvErotin = '.'; (* päiväyserotin tulostettaessa *) type Viite = string[ViitePituus]; Nimi = string[NimenPituus]; Raha = (mk, euro); (* tallennetaan rahasummat reaaliluvuilla, vaikka tarkkuus saattaa vähän kärsiä *) Summa = record mk, euro : real; alkup : Raha; end; (* viestikenttä on _osoitin_ ViestiTietueeseen *) (* ei kaikkein kätevintä, mutta nyt harjoitellaan *) Viesti = ^ViestiTietue; ViestiTietue = record rivit : array[1..ViestiRiveja] of string[ViestiRivinPituus]; kaytossa : 0..ViestiRiveja; end; (* tilinumeron väliviivaa ei talleteta *) TiliNro = record alku : string[TiliNroAlkuPituus]; loppu : string[TiliNroLoppuPituus]; end; (* päiväys *) Paivays = record vuosi, kk, pv : integer; end; (* Viite ja Viesti ovat vaihtoehtoiset, taas harjoituksen vuoksi *) SiirtoTyyppi = (ViiteSiirto, ViestiSiirto); TiliSiirto = record saaja : Nimi; saajantili : TiliNro; maara : Summa; erapaiva : Paivays; maksaja : Nimi; maksajantili : TiliNro; case tyyppi : SiirtoTyyppi of ViiteSiirto : ( viitenro : Viite ); ViestiSiirto : ( viestirivit : Viesti ); end; (* record TiliSiirto *) (* merkkijonot tulostamista ja lukemista varten *) const RahaLyh : array[Raha] of string[10] = ('mk', 'e'); (* ennakkoesittelyt kaikista aliohjelmista *) procedure TulostaTiliSiirto(var ts : TiliSiirto); forward; procedure LueTiliSiirto(var ts : TiliSiirto; var hyvaksytty : boolean); forward; procedure LueTiliNumero(var tn : TiliNro); forward; procedure TulostaTiliNumero(var tn : TiliNro); forward; procedure LueViesti(var v : Viesti); forward; procedure TulostaViesti(v : Viesti); forward; procedure VapautaViesti(var ts : TiliSiirto); forward; procedure LueSumma(var s : Summa); forward; procedure TulostaSumma(s : Summa); forward; procedure LueJono(var jono : string; pituus : integer); forward; procedure LisaaTarkNro(var v : Viite); forward; function ViiteOK(v : Viite) : boolean; forward; function Paivaluku(vuosi, kk : integer) : integer; forward; procedure TulostaPaivaysLyhyt(p : Paivays); forward; procedure TulostaPaivaysPitka(p : Paivays); forward; function LueLuku(kentta : string; alku, loppu : integer) : integer; forward; procedure LuePaivays(var p : Paivays); forward; function Aiempi(var a, b : Paivays) : boolean; forward; procedure PoistaAlkuJaLoppuTyhjeet(var rivi: string); forward; (* --- Kokonaisten tilisiirtojen käsittely --- *) procedure TulostaTiliSiirto(var ts : TiliSiirto); begin end; (* TulostaTulostaTiliSiirto() *) procedure LueTiliSiirto(var ts : TiliSiirto; var hyvaksytty : boolean); begin end; (* LueLueTiliSiirto() *) (* --- Tilinumeroiden käsittely --- *) procedure LueTiliNumero(var tn : TiliNro); begin end; (* LueTiliNumero() *) procedure TulostaTiliNumero(var tn : TiliNro); begin end; (* --- Viestin käsittely --- *) procedure LueViesti(var v : Viesti); begin end; (* LueViesti() *) procedure TulostaViesti(v : Viesti); begin end; (* TulostaViesti() *) procedure VapautaViesti(var ts : TiliSiirto); begin end; (* --- Summien käsittely --- *) procedure LueSumma(var s : Summa); begin end; (* LueSumma() *) procedure TulostaSumma(s : Summa); begin end; (* TulostaSumma() *) (* --- Viitteiden käsittely, 2. harjoituksista --- *) (* Luejono harjoituksista 8, ei nollia lisäksi *) procedure LueJono(var jono : string; pituus : integer); begin end; (* LueJono() *) (* Viitteen laskenta harjoituksesta 9 *) procedure LisaaTarkNro(var v : Viite); begin end; (* LisaaTarkNro() *) (* Viitteen tarkastus harjoitukksesta 10, muutettu tietueelle *) (* v voisi olla muuttujaparametri, jos alkuperäinen palautettaisiin takaisin *) function ViiteOK(v : Viite) : boolean; (* ei var *) begin end; (* ViiteOK() *) (* --- Päiväysten käsittely, esimerkistä alkuesim6.p --- *) (* LueLuku ei ole varsinainen päiväysaliohjelma, mutta sitä tarvitaan *) (* Aivan kaikkia ei tarvita vielä *) (* palauttaa kuukauden päivien määrän *) function Paivaluku(vuosi, kk : integer) : integer; begin case kk of 1, 3, 5, 7, 8, 10, 12 : Paivaluku := 31; 4, 6, 9, 11 : Paivaluku := 30; 2 : if (vuosi mod 4 = 0) and ( (vuosi mod 100 <> 0) or (vuosi mod 400 = 0) ) then Paivaluku := 29 else Paivaluku := 28; end; (* case *) end; (* Paivaluku() *) (* tulostaa päiväyksen, esimerkin vuoksi ei käytetty with-lausetta vaikka olisi voinut *) procedure TulostaPaivaysLyhyt(p : Paivays); begin write(p.pv, '.', p.kk, '.', p.vuosi); end; (* TulostaPaivaysLyhyt() *) (* tulostaa päiväyksen, esimerkin vuoksi ei käytetty with-lausetta vaikka olisi voinut *) procedure TulostaPaivaysPitka(p : Paivays); begin write(p.pv, '. '); case p.kk of 1 : write('tammi'); 2 : write('helmi'); 3 : write('maalis'); 4 : write('huhti'); 5 : write('touko'); 6 : write('kesä'); 7 : write('heinä'); 8 : write('elo'); 9 : write('syys'); 10 : write('loka'); 11 : write('marras'); 12 : write('joulu') end; (* case *) write('kuuta ', p.vuosi); end; (* TulostaPaivaysPitka() *) (* lukee yhden päiväyksen käyttäjältä, käytetään with-lausetta *) procedure LuePaivays(var p : Paivays); begin with p do begin vuosi := Lueluku('vuosi', 1900, 2100); kk := Lueluku('kuukausi', 1, 12); pv := Lueluku('päivä', 1, Paivaluku(vuosi, kk)); end; (* with *) end; (* LuePaivays() *) (* palauttaa toden, jos päiväys a varhaisempi kuin b *) function Aiempi(var a, b : Paivays) : boolean; begin if a.vuosi < b.vuosi then Aiempi := true else if (a.vuosi = b.vuosi) and (a.kk < b.kk) then Aiempi := true else if (a.vuosi = b.vuosi) and (a.kk = b.kk) and (a.pv < b.pv) then Aiempi := true else Aiempi := false; end; (* Aiempi() *) (* lukee käyttäjältä kokonaisluvun alku..loppu, kehotteena kentta *) function LueLuku(kentta : string; alku, loppu : integer) : integer; var luku : integer; begin luku := 0; repeat write('Anna ', kentta, ' : '); readln(luku); if (luku < alku) or (luku > loppu) then writeln('Ei kelpaa ', kentta, 'ksi, pitää olla ', alku, '-', loppu); until (luku >= alku) and (luku <= loppu); LueLuku := luku; end; (* LueLuku() *) (* poistaa rivin alussa ja lopussa olevat tyhjeet, rivi voi siis muuttua *) (* esimerkki 19 *) procedure PoistaAlkuJaLoppuTyhjeet(var rivi: string); begin while Pos(' ', rivi) = 1 do (* poistetaan etutyhjeet *) Delete(rivi, 1, 1); (* hieman tehoton ratkaisu *) while Copy(rivi, Length(rivi), 1) = ' ' do (* tyhjeet pois lopusta *) Delete(rivi, Length(rivi), 1) end; (* PoistaAlkuJaLoppuTyhjeet() *) (* --- Pääohjelma --- *) (* varsin lyhyt, jatketaan myöhemmin *) (* muokkaa, jollet tee kaikkia osia *) var t : TiliSiirto; ok : boolean; begin LueTilisiirto(t, ok); if (ok) then begin (* jätetään yhteys pankkin ottamatta *) TulostaTiliSiirto(t); end; VapautaViesti(t); end.