Helsingin yliopisto / Tietojenkäsittelytieteen laitos / Ohjelmoinnin jatkokurssi
Copyright © 2009 Arto Wikla. Tämän oppimateriaalin käyttö on sallittu vain yksityishenkilöille opiskelutarkoituksissa. Materiaalin käyttö muihin tarkoituksiin, kuten kaupallisilla tai muilla kursseilla, on kielletty.

4. harjoitukset 23.-27.11.2009

Aiheita: kirjastoluokka, "todellista" ohjelmointia, ...

  1. Toteuta kirjastoluokkana kuormitetut metodit muotoiltuun tulostukseen. Metodit
    public static void tulostaVasen(arvo, int kentänLeveys)
    public static void tuostalOikea(arvo, int kentänLeveys)
    
    tulostavat arvon kenttään jonka leveys on kentänLeveys. Parametri arvo voi olla int, String, char- tai boolean. Metodeista ensimmäinen tulostaa arvon kentän vasempaan laitaan, jälkimmäinen oikeaan. Metodit eivät vaihda riviä! Jos arvo on kenttää leveämpi, kenttää laajennetaan, arvoa ei katkaista (Tämä on turvallisempaa kuin katkaisu! Miksi?)

    Havainnollista metodien käyttöä pääohjelmalla.

  2. & 13.
    [Huom: Tämän tehtävän ratkaisu - itse kirjoitettavien ohjelmarivien määrä - on paljon lyhyempi kuin tehtävänanto! :-]
    Javassa on valmiitakin välineitä joukon esittämiseen. Mutta kuten jo nähtiin, tällaisten dynaamisilta vaikuttavien välineiden toteuttaminen itse - omin käsin - on hyvin opettavaista. Tehtävässä 6 & 7 tutustuttiin "vaihtelevanmittaisen" merkkijonon toteuttamiseen. Puutteena tuon tyypin dynaamisuudessa oli kiinteä yläraja pisimmälle mahdolliselle merkkijonolle. Tuokin puute korjataan nyt joukon toteutuksessa: Tälläkin kertaa rakenteen elementit, nyt kokonaisluvut, talletetaan taulukon alkuun, ja käytössä olevien alkioiden lukumäärä muistetaan muuttujan avulla. Mutta nyt menetelläänkin siten, että jos uusi alkio ei enää mahtuisi taulukkoon, luodaan uusi isompi taulukko, jonka alkuun ensin kopioidaan vanhan taulukon sisältö ja vasta sitten toteutetaan lisäysoperaatio. Joukolle varatun taulukon oletuskoko löytyy julkisesta luokkavakiosta Kokonaislukujoukko.KAPASITEETTI. Jos lisäysoperaatio joutuu luomaan suuremman taulukon, oletusarvoisesti uusi taulukko on Kokonaislukujoukko.OLETUSKASVATUS-vakion verran suurempi kuin vanha taulukko. Kuormitetuin konstruktorein oletusarvoja voidaan muuttaa.

    Luokan Kokonaislukujoukko määrittely alkakoon seuraavasti:

        public class Kokonaislukujoukko {
    
          public final static int KAPASITEETTI=10,  // Vertaa tehtävään 6 & 7!
                                  OLETUSKASVATUS =10;  // Kerralla otettavan lisätilan oletusmäärä.
    
          private int kasvatuskoko;     // Kerralla otettavan lisätilan määrä.
    
          private int[] taulukko;       // Joukon luvut säilytetään taulukon alkupäässä. 
          private int alkioiden_määrä;  // Tyhjässä joukossa alkioiden_määrä on nolla. 
    
          public Kokonaislukujoukko() {
            taulukko = new int[KAPASITEETTI];
            kasvatuskoko = OLETUSKASVATUS;
            alkioiden_määrä = 0;
          }
    
          public Kokonaislukujoukko(int kapasiteetti) {
            // Annetaan oma kapasiteetti.
            // Muista tarkistaa parametrin kelvollisuus!
            // ... 
          }
    
          public Kokonaislukujoukko(int kapasiteetti, int kasvatuskoko) {
            // Annetaan oma kapasiteetti ja kasvatuskoko.
            // Muista tarkistaa parametrien kelvollisuus!
            // ...
          }
          // ...
    
    Ohjelmoi luokkaan ainakin aksessorit

    Suunnittele aksessorien toiminta myös mahdollisessa virhetilanteessa. Päätä itse kolmen ensiksi luetellun aksessorin mahdollisen palautusarvon tyyppi, so. void, boolean, int, ...

    Käyttöesimerkki: ("Testipääohjelma" täydennettynä; kokeile Kokonaislukujoukko-toteutustasi tällä!)

        ...
        Kokonaislukujoukko x = new Kokonaislukujoukko();
    
        System.out.println("Joukko on: " +x); // {}
    
        x.lisää(57);
        x.lisää(-32);
        x.lisää(12);
        System.out.println("Joukko on: " +x); // {57, -32, 12}
    
        x.lisää(57); // on jo, ei lisätä!
        System.out.println("Joukko on: " +x); //  {57, -32, 12}
    
        x.lisää(60);
        System.out.println("Joukko on: " +x); // {57, -32, 12, 60}
    
        System.out.println("Joukon koko on " + x.koko()); // 4
    
        int[] taulukkona = x.toIntArray();
        for (int alkio: taulukkona)
          System.out.print(alkio + ", ");
        System.out.println();                // 57, -32, 12, 60,
    
        if (x.kuuluu(12))
          System.out.println("12 kuuluu joukkoon");  // tämä!
        else
          System.out.println("12 ei kuulu joukkoon");
    
        x.poista(12);
        System.out.println("Joukko on: " +x); // {57, -32, 60}
    
        if (x.kuuluu(12))
          System.out.println("12 kuuluu joukkoon");
        else
          System.out.println("12 ei kuulu joukkoon"); // tämä!
    
        x.poista(48);
        System.out.println("Joukko on: " +x); // {57, -32, 60}
    
        x.poista(60);  // {57, -32}
        x.poista(57);  // {-32}
        x.poista(-32); // {}
    
        x.poista(23);  // {}
    
    Vihjeitä ja ajatuksia:

  1. Ohjelmoi joukko-operaatioiden toteutukseksi kirjastoluokka JoukkoOperaatio, joka sisältää ainakin seuraavat kirjastometodit: Kokonaislukujoukko-luokan aksessoreita käyttäen ohjelmonnin ei pitäisi olla kovin työlästä. Erityisesti tarvitset toIntArray()-aksessoria joukon alkioiden läpikäymiseen. Muut aksessorit helpottavat ohjelmointia. Havainnollista näiden kirjastometodien käyttöä esimerkkiohjelmalla, joka perustuu komentotulkin käyttöön. Huomaa ettei komentotulkkilogiikka välttämättä edellytä switch-lauseen käyttämistä.
    Käyttöesimerkkejä:
      Kokonaislukujoukko a, b, c, d, e;
      a = new Kokonaislukujoukko();
      b = new Kokonaislukujoukko();
      // ....  a:han ja b:hen viedään kaikenlaisia lukuja
      c = yhdiste(a, b);
      d = leikkaus(a, b);  
      e = erotus(a, b); 
      a = yhdiste(d, leikkaus(b, c));
      // ...
    

  2. Täydennä luokkaa Kokonaislukujoukko seuraavilla joukko-operaatioilla: Kokonaislukujoukko-luokan muita aksessoreita käyttäen ohjelmonnin ei pitäisi olla kovin työlästä. Erityisesti tarvitset toIntArray()-aksessoria joukon alkioiden läpikäymiseen. Muut aksessorit helpottavat ohjelmointia. Havainnollista uusien aksessorien käyttöä esimerkkiohjelmalla, joka perustuu komentotulkin käyttöön. Kannattaa muokata tämä versio edellisen tehtävän versiosta. Opettavaista!
    Käyttöesimerkkejä:
      Kokonaislukujoukko a, b, c, d, e;
      a = new Kokonaislukujoukko();
      b = new Kokonaislukujoukko();
      // ....  a:han ja b:hen viedään kaikenlaisia lukuja
      c = a.yhdiste(b);
      d = a.leikkaus(b);  
      e = a.erotus(b); 
      a = d.yhdiste(b.leikkaus(c));
      // ...
    


Takaisin harjoitussivulle.