wiki:k2015/demot/demo10
Last modified 3 years ago Last modified on 2015-03-21 21:26:01

Demot » Demo 10, 23.3.2015

English version

Palautus NETTIDEMOWWW-ohjelmalla. Tähdellä (*) merkitty ne tehtävät, jotka ehdottomasti kannattaa tehdä.

Itsearvio A1 (0p mutta pakollinen)

Jollet tehnyt jo maanantain demopalautuksessa, niin täytä edellisen (esim. demo1:n arvion demo 2 kerralla) kerran itsearviolomake: arvio.txt (lataa ja muokkaa) ja palauta NettiDemoWWW:hen nimellä A1 tiedosto arvio.txt tai jos täytät käsin paperille demon aikana etkä jaksa kirjoittaa koneelle, niin ota kuva tai skannus paperista ja paluta arvio.X (missä X on joku seuraavista: pdf, jpg, png).

Testaaminen

Kaikki "Järkevästi" testattavissa olevat ohjelmat (merkitty T) testattava automaattitestillä (JUnit tai ComTest). Jos testaa GUI-ohjelmia esim Lift-kirjastolla saa merkitä yhden lisäbonuspisteen. NettiDemoWWW:hen tämä "tilitetään" palauttamalla tiedosto guitest.txt johon kirjoitetaan mitkä tehtävä on testattu ja vähän mielipiteitä testaamisesta.

Ville V1

Tee JHAVEPOP tehtävistä 10-16 yhteensä 4 tehtävää sekä 17 ja 18.
Palautus kuten Ville tehtävissä, eli tiedosto ville.txt johon vähän tilitystä siitä mitä oppi ja mielellään copy/pastena ne lisätyt rivit. Jos serveri sattuu olemaan toimimattomalla päällä, niin kirjoita itse sinne Ville.txt-tiedostoon ne rivit, mitä kuvittelet tarvittavan tehtävän vastaukseksi. Jos kirjoittettua koodia pitää korjata, niin:

  1. Setup
  2. Visualize
  3. Korjaa koodia
  4. OK
  5. steppaile
  6. jos väärin, jatka 1)

Yhdenkin rivin silmukat pitää laittaa lausesulkuihin, siis ei:

  while ( q.next != null ) q = q.next; 

vaan

  while ( q.next != null ) { 
      q = q.next; 
  }

Vinkkejä

Tarvittaessa katso vinkkejä

Tehtävä 1. Tiedoston numerointi

Kirjoita Java-ohjelma joka tulostaa tiedoston sisällön siten, että kunkin rivin alkuun tulee rivinumero kahdella numerolla ja kustakin rivistä tulostetaan korkeintaan 40 merkkiä (T). Esimerkiksi koe.txt

123456789012345678901234567890123456789012345678901234567890
Kissa istuu puussa
ja ihmettelee
mualiman menoa

tulostuisi:

/* 01 */ 1234567890123456789012345678901234567890
/* 02 */ Kissa istuu puussa
/* 03 */ ja ihmettelee
/* 04 */ mualiman menoa

Tiedosto/IO testejä varten katso malliksi aikaisempien demojen vastauksia sekä monisteen lukua 15.2.7 Tiedostoja käsittelevien ohjelmien testaaminen.

Tehtävä 2. Tiettyjen rivien tulostaminen tiedostosta

Kirjoita ohjelma, joka kysyy käyttäjältä tiedoston nimen (luo tiedosto itse) ja tulostaa tiedostosta kaikki ne rivit jotka alkavat ** (T).

Tehtävä 3*. Laske tiedoston kirjainten esiintymät

Kirjoita ohjelma, joka lukee tiedoston (tietovirtoja käyttäen) ja tulostaa lopuksi kuinka monta kertaa mikäkin aakkosten kirjain esiintyi tiedostossa ('A'='a'). Vihje: Mieti ensin mitä itse tekisit jos joutuisit moisen homman tekemään, eli esimerkiksi kertomaan tästä demopaperista monestiko mikäkin kirjain esiintyi. (T)

Tehtävä 4*. Dynaamisen taulukon koon kasvatus

Lisää esimerkkiin dynaaminen/TaulukkoGen.java automaattinen taulukon koon kasvatus, mikäli alkuperäisen varatun taulukon koko käy liian pieneksi (T).

Tehtävä 5. Taulukon klooni

Lisää luokkaan dynaaminen/TaulukkoGen.java metodi clone(), joka luo syväkopioinnilla kloonin oliosta. Lisää testiä varten tarvittava poista metodi kopioimalla demo9:n vastauksista. Koska nyt taulukossa on olioita, pitää poista metodissa korvata

lauseen osa
   taulukko[luku] != n
koodilla tyyliin:
   !alkiot[luku].equals(n) 

Syväkopiointi tarkoittaa sitä, että olio on kopio toisesta oliosta, mutta niillä ei ole yhteisiä viitteitä, vaan kaikki viitatutkin oliot on syväkopioitu (paitsi Javan tapauksessa immutable luokkia ei tarvitse kopioida). ComTest-testi clone -metodille (käytä mallivastauksen Int-luokkaa, tarkista onko toString erottimena välilyönti vaiko pilkku ja korjaa sen mukaan):

   * <pre name="test">
   * #THROWS CloneNotSupportedException 
   * #import demo.d9.Int;
   *  TaulukkoGen<Int> luvut = new TaulukkoGen<Int>();
   *  luvut.lisaa(new Int(0)); luvut.lisaa(new Int(2));
   *  luvut.lisaa(new Int(99));
   *  TaulukkoGen<Int> taul = luvut.clone();
   *  luvut.toString() === " 0 2 99";
   *  taul.toString()  === " 0 2 99";
   *  luvut.get(1).set(3);
   *  luvut.toString() === " 0 3 99";
   *  taul.toString()  === " 0 2 99";
   *  luvut.lisaa(new Int(2)); luvut.lisaa(new Int(5)); 
   *  luvut.lisaa(new Int(2)); luvut.lisaa(new Int(6));
   *  luvut.toString() === " 0 3 99 2 5 2 6";
   *  taul.toString()  === " 0 2 99";
   *  taul.get(3).intValue() === 2; #THROWS IndexOutOfBoundsException
   *  luvut.poista(new Int(2)); 
   *  luvut.toString() === " 0 3 99 5 6";
   *  taul.toString()  === " 0 2 99";
   * </pre>

Yksinkertaisimmassa ratkaisussa luokan esittelyn voi muuttaa rajoitettuun geneerisyyteen:

public class TaulukkoGen<TYPE extends Int> implements Cloneable 

jolloin siihen voi tallentaa vain Int -luokan olioita tai sen jälkeläisiä. Pitääkö jotakin vielä muuttaa luokassa Int? Tällöin taulukon luonti pitää olla niin, että Object:in sijasta luodaan alustavasti Int:

alkiot = (TYPE[])new Int[koko]; 

HUOM! Jos käytät rajattua geneerisyyttä, pitää kaikki testit muuttaa Integer-luokasta em tavalla Int-luokkaan.

Tehtävä 6. Linkitetyn listan kuva

Seuraavana esimerkki linkitetyn listan käytöstä (vrt. luennolla tehty muutos dynaaminen/Taulukko.java tietorakenteeseen: dynaaminen/LinLista.java. Piirrä kuva tietorakenteesta kun pääohjelmassa ollaan menossa rivillä "PIIRRÄ KUVA".

package demo;
import fi.jyu.mit.ohj2.*;
/**
 * Esimerkki linkitetystä listasta,
 * @author Vesa Lappalainen
 * @version 1.0, 15.03.2003
 */
public class Koulu {

  public static class Oppilas {
    private String nimi;
    private double keskiarvo;
    private Oppilas seuraava;

    public Oppilas(String nimi, double keskiarvo) {
      this.nimi = nimi; this.keskiarvo = keskiarvo;
    }

    public String toString() {
      return Mjonot.fmt(nimi,-22) + " keskiarvo: " +
                  Mjonot.fmt(keskiarvo,5,2);
    }
  }

  private String luokka;
  private int oppilaita;
  private Oppilas ensimmainen;
  private Oppilas viimeinen;

  public Koulu(String luokka) { this.luokka = luokka; }

  public void lisaa(Oppilas oppilas) {
  }

  public void tulosta(OutputStream os)  {
    PrintStream out = new PrintStream(os);
  }

  public void poistaKaikki() {
  }

  public static void main(String[] args)  {
    Koulu luokka = new Koulu("1b");

    luokka.lisaa(new Oppilas("Ankka Aku",5.0));
    luokka.lisaa(new Oppilas("Ankka Tupu",7.0));
    luokka.lisaa(new Oppilas("Hiiri Mikki",9.0));

    luokka.tulosta(System.out);  // PIIRRÄ KUVA
    luokka.poistaKaikki();
    luokka.tulosta(System.out);
  }
}

Seuraavat tehtävät liittyvät tuohon Koulu.java ohjelmaan. Valmis ComTest testi nettiversiossa tai JUnit-testiohjelma demo/d10/test/KouluTest.java.

Tehtävä 7*. Lisääminen linkitettyyn listaan

Täydennä metodi lisaa (T).

Tehtävä 8*. Linkitetyn listan läpikäynti

Täydennä metodi tulosta (tulostaa luokan omat tiedot ja kaikkien oppilaiden tiedot, käyttää metodia Oppilas.toString()) (T)

Tehtävä B1-2 Listan alkio

Muuta Koulu.java -esimerkin rakenne sellaiseksi, että luokka Oppilas ei sisällä viitettä seuraavaan, vaan on erikseen luokkaa ListanAlkio, jossa on Oppilas -viite ja viite seuraavaan alkioon. Näin luokasta saadaankin luokka, jolla voi tallentaa mitä tahansa objekteja. Pääohjelma ei saa muuttua (T).

Tehtävä B3 Linkitetyn listan iteraattori

Lisää Koulu.java-esimerkkiin metodi iterator ja siis myös oma Iterator-luokka. Katso mallia esim: TaulukkoIter.java tai vaiheen 6 Jasenet.java. (T)

Tehtävä G1-2 Listan kääntäminen

Kirjoita Koulu.java:n luokaan Koulu metodi kaanna, joka kääntää linkitetyn listan päinvastaiseen järjestykseen. (T)

Tehtävä G3-4 Ajan ottaminen

Suunnittele ja toteuta luokka StopWatch jolla voidaan helposti ottaa väliaikoja ja loppuaikoja ja jolla voidaan kysyä aika eri yksiköissä (ms, s, /kierros). Katso tarve esim: https://korppi.jyu.fi/list-archive/ohj05k/0050.html. Toinen esimerkki: Nopeustesti.java. Ajan voi ottaa myös:

System.currentTimeMillis()