Materiaalin copyright © Arto Wikla. Materiaalia saa vapaasti käyttää itseopiskeluun. Muu käyttö vaatii luvan.

Ohjelmoinnin jatkokurssi: harjoitukset s2010: 1/6 (1.11.-5.11.)

(Muutettu viimeksi 3.11.2010, sivu perustettu 27.10.2010.)

Nämä harjoitukset liittyvät oppimateriaalin luvun V Ohjelmointitekniikkaa: taulukoita, etsimistä, järjestämistä alilukuihin 7, 8, 9, 11 ja 12.

Harjoitustehtävien otsikoilla on värikoodaus: Vihreät tehtävät on syytä tehdä joka tapauksessa. Värittämättömiä ei ole ihan pakko tehdä, mutta nekin ovat hyvin hyödyllisiä ja myös vaikuttavat pisteisiin. Keltaiset tehtävät ovat vähän haastavampia. Nekin lasketaan mukaan harjoituspisteitä määrättäessä, mutta ilmankin niitä harjoituksista voi saada maksimipisteet.

Huom: Jokaisen ohjelmatiedoston alkuun on kirjoitettava kommenttina harjoituskerta, tehtävän numero ja tekijän nimi tyyliin:

// 1. harjoitukset, tehtävä 1.3, Oili Opiskelija

Huom: Ohjaajien eli pajamestarien sivulta löytyy hienoja testauksen apuvälineitä tehtävien tekemisen avuksi!

Olioita taulukossa

Opiskelija.java, vaihe 1

Luokan Opiskelija määrittely alkaa seuraavasti:

public class Opiskelija {

  private String etunimi;
  private String sukunimi;
  private int koepisteet;       // saa olla vain 0-36
  private int harjoituspisteet; // saa olla vain 0-24

  public Opiskelija(String etunimi, String sukunimi) {
    this.etunimi = etunimi;
    this.sukunimi = sukunimi;
    this.koepisteet = 0;
    this.harjoituspisteet = 0;
  }
  //---------------------------
  public String getEtunimi() {
    return this.etunimi;
  }
  public String getSukunimi() {
    return this.sukunimi;
  }
  public int getPistesaalis() {
    return this.koepisteet + this.harjoituspisteet;
  }
  //---------------------------
  ...
}

Täydennä luokkamäärittelyä metodein

Havainnollista luokan ilmentymien käyttöä.

Opiskelija.java, vaihe 2

Opiskelija-olioille määritellään järjestys seuraavasti:

  1. Sukunimien String-vertailun antama "aakkosjärjestys" on ensisijainen järjestysperuste.
  2. Jos sukunimet ovat samat, järjestyksen määrää etunimien String-vertailun tulos.

Täydennä Opiskelija-luokkaa metodilla public int compareTo(Opiskelija verrattava), joka vertaa this-opiskelijaa parametriopiskelijaan. Metodi palauttaa arvon -1, jos this-opiskelija edeltää verrattava-opiskelijaa, arvon +1 päinvastaisessa tapauksessa. Jos opiskelijat ovat kaikilta tiedoiltaan samat, metodi palauttaa arvon 0. String-olioiden vertailussa tyydytään siis siihen "aakkosjärjestykseen", jonka String-luokan compareTo-metodi määrittelee.

Havainnollista vertailun toimintaa.

Kurssitulokset.java, vaihe 1

Luokkaa Opiskelija voidaan käyttää seuraavaan tapaan taulukon alkiotyyppinä:

Ohjelmarivi

Opiskelija[] opiskelijat = new Opiskelija[9];

asettaa muuttujan arvoksi yhdeksänalkioisen taulukon, jonka alkiot voivat saada arvokseen Opiskelija-olioita. Tämän jälkeen esimerkiksi lause

opiskelijat[6] = new Opiskelija("Pekka", "Puupää");

asettaa taulukon seitsemännen alkion arvoksi sellaisen Opiskelija-olion, jolle

opiskelijat[6].getEtuimi() 

on arvoltaan "Pekka" ja

opiskelijat[6].getPistesaalis()

on alkuarvoltaan 0

Laadi sovellus, joka pyytää opiskelijoiden tiedot ja tulostaa kurssin tulokset syöttöjärjestyksessä

Toteuta tietojen kysely ja tulostaminen yksityisinä luokkametodeina, "pääohjelman pikku apulaisina".

Tulostuksen ulkoasu on seuraavanlainen:

Hopo, Hessu               31  1
Ankka, Aku                42  3
Juonio, Jussi             50  5
Mainio, Matti             50  5
Puupää, Pekka             40  3
Lipponen, Pekka	           5  0
Ankka, Taavi              42  3
Vemmelsääri, Väiski       46  4
Hirmuinen, Harald         39  2

Kurssitulokset.java, vaihe 2

Kehittele edellisen tehtävän ohjelmaa siten, että kurssin tulokset kirjoitetaan opiskelijoiden nimen mukaisessa järjestyksessä.

Käytä järjestämisessä vertailun välineenä Opiskelija-luokan metodia compareTo.

Toteuta myös järjestäminen yksityisenä luokkametodina, "pääohjelman pikku apulaisena".

Tulostuksen ulkoasu on nyt seuraavanlainen:

Ankka, Aku                42  3
Ankka, Taavi              42  3
Hirmuinen, Harald         39  2
Hopo, Hessu               31  1
Juonio, Jussi             50  5
Lipponen, Pekka            5  0
Mainio, Matti             50  5
Puupää, Pekka             40  3
Vemmelsääri, Väiski       46  5

Kurssi.java

Toteuta luokka Kurssi käyttäen piilossa pidettynä tietorakenteena Opiskelija-taulukkoa:

Toteuta sitten edellinen tehtävä käyttäen luokkaa Kurssi.

Huomaa miten tässä asiat hoidellaan edellistä tapaa "oliohenkisemmin". Edellinen tehtävä on myös vaivaton toteuttaa, jos ensin ohjelmoi tämän tehtävän!

Oikeasti Kurssi-luokkaan varmaan ohjelmoitaisiin monia muitakin kurssikirjanpidon kannalta hyödyllisiä aksessoreita.

Opiskelijan etsintää

Laajenna Kurssi-luokkaa metodilla

Esittele laajennuksen toimintaa. Kokeile myös voitko muuttaa haetun opiskelijan koe- ja harjoituspistemäärää? Miksi tämä toimii/ei toimi?

Mieti onko etsiOpiskelija järkevä metodi vai olisiko Kurssilla parempi olla erikoistuneempia metodeja tyyliin:

public int opiskelijanArvosana(String etunimi, String sukunimi)
public void muutaOpiskelijanKoepisteitä(String etunimi, String sukunimi, int uusiPistemaara) 

Taulukko oliossa

Kun jokin ohjelmointikielen väline vaikuttaa helppokäyttöiseltä ja joustavalta, kyseessä on se, että joku on toteuttanut eli ohjelmoinut, tuon helppouden! Eikä se välttämättä ole ollut helppoa...

Luokassa String on monenlaisia välineitä merkkijonojen käsittelyyn. Kerran luotu String-olio tunnetusti ei kuitenkaan voi koskaan muuttua – String-oliot ovat kerran synnyttyään muuttumattomia, "immutaabeleita".

Tässä tehtäväsarjassa toteutetaan vaiheittain merkkijonoluokka MyString muutettavien merkkijononojen toteutukseksi. Tehtävienn ratkaisemisessa on pyrittävä välttämään roskienkerääjän ylensyöttämistä. Itse asiassa Java-APIssa on olemassa luokat StringBuilder ja StringBuffer muutettavien merkkijonojen käsittelyyn, mutta asioiden tekeminen omin käsin on opettavaista!

MyString, vaihe 1

MyString-luokka kapseloi sisäänsä merkkitaulukon, jonka alkuosassa säilytetään esitettävää merkkijonoa. Luokan määrittely alkaa seuraavasti:

public class MyString {

  public static final int MAKSIMIPITUUS = 100; // pisin mahdollinen merkkijono
                                               // näkyy kaikkialle: MyString.MAKSIMIPITUUS

  private char[] mjono; // merkkijononon esitys char-taulukkona
  private int pituus;   // montako alkioita mjono:n alusta on käytössä
  ...                   // eli ensimmäisen käyttämättömän indeksi
}

Määrejono public static final määrää, että kenttä MAKSIMIPITUUS näkyy kaikkialle, että se liittyy luokkaan, ei olioon, ja että sen arvoa ei voi muuttaa. Tällaiset nimetyt vakiot on tapana kirjoittaa isoin kirjaimin.

Toteutetaan ensin seuraava hyvin nysä API:

Kokeile ja esittele MyStringin käyttöä pienellä ohjelmalla.

MyString, vaihe 2

Täydennä MyStringin toteutusta seuraavilla välineillä:

Kokeile ja esittele kehitellyn MyStringin käyttöä pienellä ohjelmalla.

MyString, vaihe 3

Täydennä MyStringin toteutusta seuraavilla välineillä:

Kokeile ja esittele kehitellyn MyStringin käyttöä pienellä ohjelmalla.

MyString, vaihe 4

Täydennä MyStringin toteutusta String-luokasta tutuin aksessorein compareTo ja indexOf(char).

Poiketen String luokan compareTo-metodista riittää, että MyStringin compareTo-metodi palauttaa vain jonkin arvoista -1, 0 tai 1.

Kokeile ja esittele kehitellyn MyStringin käyttöä pienellä ohjelmalla.

MyString, vaihe 5

Täydennä MyStringin toteutusta String-luokasta tutulla aksessorilla indexOf(MyString).

Kokeile ja esittele kehitellyn MyStringin käyttöä pienellä ohjelmalla.