Helsingin yliopisto / Tietojenkäsittelytieteen laitos / Java-ohjelmointi / Copyright © 2002 Arto Wikla.

581325-0 Java-ohjelmointi, koe 18.12.2002/AW

Kirjoita jokaisen vastauspaperisi alkuun kurssin nimi ja kokeen päivämäärä sekä nimesi, henkilötunnuksesi ja allekirjoituksesi. Kirjoita jokainen vastaus omalle konseptiarkilleen!
Tässä kokeessa saa poikkeuksellisesti käyttää "lunttilappua". Sen koko saa olla enintään A4.

  1. "Mä en kerta kaikkiaan enää kestä noita sun puheitasi 'abstrakteista luokista' ja 'rajapintaluokista'!" Näin parahti ystäväsi kuunneltuaan intoiluasi Javan hienouksista. Ystäväsi hallitsee Java-kielen muuten oikein hyvin - jopa luokat ja luokkien hierarkiat ovat hänelle tuttuja - mutta nuo mainitut välineet herättävät hänessä vain asiantuntematonta ärtymystä. Auta ystävääsi ymmärtämään, mistä oikein on kysymys ja mihin noita välineitä voi käyttää. Laadi siis asiasta kirjallinen selitys, joka tietenkin sisältää myös valaisevia ohjelmaesimerkkejä (enimmäispituus 1 konseptiarkki, so. 4 sivua). Vastauksen arvioinnissa otetaan huomioon selostuksen ajateltu lukija. Älä siis kirjoita tarkastajalle, joka jo tuntee asian, kirjoita tuolle ystävälle!
                                                                (17 pistettä)
    

  2. Tarina muodostuu yhdestä tai useammasta String-tekstirivistä. Jokaisella tarinalla on yksikäsitteinen koodinumero, joka ei koskaan voi muuttua, eikä millään muulla tarinalla voi koskaan olla samaa koodia. Kerran luodun tarinan sisältöä ei myöskään voi muuttaa.

    1. Ohjelmoi tarinan toteutukseksi luokka Tarina, jossa kaikki tietorakenteet ovat luonnollisestikin private, ja jossa on julkiset välineet (konstruktori ja aksessorit):
      • public Tarina(String[] rivit) luo Tarina-olion ja sen yksikäsitteisen koodinumeron
      • public int mikäOnTarinanKoodi()
      • public int mikäOnTarinanPituus(), so. rivien lukumäärä
      • public String mikäOnTarinanRivi(int i) palauttaa arvonaan tarinan rivin, jonka numero on i
      • public void tulostaTarina() tulostaa koko tarinan rivinumeroilla varustettuna
      • public Tarina koosta(Tarina toinen) palauttaa arvonaan uuden Tarina-olion, jossa tarina muodostuu this-tarinasta, jonka perään on liitetty parametrina annettu toinen tarina.

    2. KommentoituTarina on kuin Tarina, mutta tavallisesta tarinasta poiketen kommentoidun tarinan mihin tahansa tekstiriviin voi liittyä tekstikommentti. Jokaiseen riviin ei toki tarvitse liittyä kommenttia. Eikä välttämättä yhteenkään! Toteuta KommentoituTarina luokan Tarina aliluokkana. Ohjelmoi uudelleen vain tarvittavat osat:
      • public KommentoituTarina(String[] rivit) luo KommentoituTarina-olion, jossa mitään riviä ei vielä ole kommentoitu
      • public void liitäKommentti(String kommentti, int rivi) liittää annetun kommentin tarinan annettuun riviin, mahdollinen vanha kommentti korvataan tällä uudella
      • public String mikäOnKommentti(int rivi) palauttaa arvonaan tarinan i:nnen rivin kommentin (tai arvon null, jos riviin ei liity kommenttia)
      • public void tulostaKommentit() tulostaa rivinumeroin kaikki ei-tyhjät kommentit, so. kommenttiluettelon
      • public KommentoituTarina koosta(KomentoituTarina toinen) palauttaa arvonaan uuden KommentoituTarina-olion, jossa tarina muodostuu this-tarinasta, jonka perään on liitetty parametrina annettu toinen tarina. Uusi kommentoitu tarina saa tietenkin myös vanhojen tarinoiden kommentit!
    Huom: Muista varautua myös mahdollisiin virhetilanteisiin.
                                                                (18 pistettä)
    

  3. Käytössäsi on char-arvoista eli merkeistä muodostuvan tiedoston lukemiseen luokka Merkkitiedosto. Luokalla on konstruktori Merkkitiedosto(String tiedostonNimi). Parametrina annetaan syöttötiedoston nimi. Merkkejä luetaan ilmentymämetodilla public char lueMerkki(). Tiedoston loppumisen metodi ilmaisee palauttamalla arvonaan ns. "null-merkin" eli merkkivakion '\u0000'. Kun siis metodin palauttama merkki on yhtä suuri kuin vakio '\u0000', tiedosto on loppu. Rivin loppumisen metodi lueMerkki ilmaisee palauttamalla arvonaan merkin '\n'.

    Luokassa Merkkitiedosto ei ole varauduttu poikkeuksiin! Konstruktorin ja aksessorin kutsuja joutuu siis itse käsittelemään poikkeukset!

    1. Toteuta luokka Rivitiedosto luokan Merkkitiedosto avulla. Rivitiedosto-luokalla on konstruktori Rivitiedosto(String tiedostonNimi).

      Rivitiedosto-olion avulla tiedostoa voidaan lukea (tuttuun tapaan) riveittäin. Kukin rivi saadaan siis String-oliona, jossa ei ole mukana merkkitiedostossa esiintyvää rivin loppumerkkiä '\n'.

      Rivitiedoston rivit luetaan aksessorilla public String lueRivi(), joka palauttaa arvonaan tiedoston seuraavan rivin.

      Kun tiedosto on loppu, lueRivi palauttaa arvon null.

      Poikkeukset pitää käsitellä luokassa Rivitiedosto siten, että sen ilmentymien käyttäjän ei tarvitse kantaa niistä huolta: Jos Merkkitiedosto-olion luonti epäonnistui, lueRivi()-metodi palauttaa alusta alkaen arvon null. Jos lueMerkki()-metodin kutsu johtaa poikkeukseen, lueRivi()-metodi palauttaa arvon null. Rivitiedosto-olion käyttäjälle siis alunperin rikkinäinen tai kokonaan puuttuva tiedosto näyttää tiedostolta, jossa ei ole lainkaan rivejä Kesken kaiken rikkoutuva tiedosto näyttää vain loppuvan.

      Huom: Riittää että Rivitiedosto käsittelee Merkkitiedoston aiheuttamat poikkeukset vain kaikkein yleisimmällä tasolla, Exception-poikkeuksina.

    2. Ohjelmoi Rivitiedostoa käyttäen sovellus, joka laskee käyttäjän antaman tiedoston rivien lukumäärän.

    Huom: Luokka Merkkitiedosto siis on käytettävissä, älä ihmeessä sitä enää ohjelmoi!

                                                                (18 pistettä)
    
Onnea kokeeseen & Hauskaa Joulua!