wiki:paate_3netbeans
Last modified 5 years ago Last modified on 2013-01-20 16:37:00

Pages linking to paate_3netbeans:
k2013/paate_3
k2015/paate/3
k2014/paate/3

Ohjelmointi 2 / Debuggaus NetBeansilla

Oppimistavoiteet

Tässä harjoituksessa opittavat asiat tulevat hyödyksi ohjelman koodaamisessa ja testaamisessa. Itse ohjelman suunnittelun kanssa tällä harjoituksella ei ole mitään tekemistä!

Kirjoita tämä Java-ohjelma: Jarj2.java. Tallenna se nimellä Jarj2.java.

1. Debuggerin käyttö

Kokeillaan Jarj2-ohjelman ajoa rivi kerrallaan NetBeansin debuggerilla.

  1. Vaihda näkymä debug-näkymäksi
    • NetBeans: vaihda vasemmalla olevalta Explorer-ikkunasta Editing-välilehti Debugging-välilehdeksi.
  2. Aja ohjelmaa rivi kerrallaan ([F5] tai [F6], Eclipsessä Run->Debug as->Java Applicaton). Voit myös asettaa koodiin keskeytyskohdan (breakpoint) klikkaamalla koodieditorin vasempaa reunusta haluamasi rivin kohdalta tai näppäimistöllä.
    • NB: [Ctrl-Shift-F8]
  3. Tarkista, että WATCH-ikkuna on näkyvissä
    • NB: Watch-ikkuna on Debugging-välilehden alin ikkuna.
  4. Laita yksi kerrallaan WATCH-ikkunaan muuttujat s1, s2 ja t. Aluksi muuttujien perässä voi olla virheilmoitus jonka pitäisi poistua kun ohjelman suoritus aloitetaan ja muuttujan "elämä alkaa".
    • NB:[Ctrl-Shift-F7].
  5. Katso välillä tulostusruutua
    • NB: Process output koodieditorin alapuolella.
  6. Kokeile uudestaan. NetBeansissa voit käyttää myös kursoriin saakka ajamista (eli siirrä kursori vaikkapa riville s2=t ja paina [F4]).
  7. Siirrä vaihtamisessa suoritettavat lauseet samalle riville: t=s1; s1=s2; s2=t;
    1. Siirry rivin loppuun. ([End])
    2. Poista rivin loppu. ([Del])
    3. Poista seuraava sana. ([Shift-Ctrl-oikea] ja [DEL])
    4. Lisää välilyönti.
  8. Kokeile suoritusta rivi kerrallaan uudelleen, kun ko. lauseet on siirretty.
  1. Kokeile suoritusta rivi kerrallaan käyttämällä nyt näppäintä [F6]. Mitä eroa näppäimeen [F5]?
  2. Lisää ohjelmaan tulostusrivi, joka kertoo ohjelman käyttäjälle mitä ohjelma tekee.
  3. Tallenna ohjelma lopuksi. ([Ctrl-S])

2. Lohkojen käsittely

Harjoitellaan uuden ohjelman kirjoitusta ja leiketaulun käyttöä.

  1. Aloita uusi ohjelma nimeltä Jarj3.java.
    • NB: [Ctrl-N], valitse puusta Java Classes ja Main, Next. Kirjoita Name-kenttään Jarj3 ja valitse puusta työhakemistosi. Paina kolme kertaa Next-nappia ja lopuksi Finish-nappia.
  2. Kopioi pohjaksi edellinen ohjelma Jarj2.java.
    1. Aktivoi Jarj2.java-tiedoston ikkuna (Window-valikko, NB:ssä.
    2. Valitse koko tiedosto ([Ctrl-END] ja [Ctrl-SHIFT-HOME]).
    3. Kopioi tiedosto leikepöydälle ([Ctrl-Ins] tai [Ctrl-C]).
    4. Huomaa, että uuden luokan nimen on oltava Jarj3!
  3. Tarkoituksena on muuttaa ohjelmaa siten, että järjestetäänkin 3 lukua suuruusjärjestykseen (rivit on numeroitu jotta alla voidaan viitata riveihin; numeroita ei missään tapauksessa kirjoiteta!):
  4. LUE ENNEN KIRJOITTAMISTA HUOLELLISESTI ALLA OLEVAT KIRJOITUSOHJEET!
          01 import java.io.*; // tarvitaan tietojen syöttöön
          02 /**Jarj2
          03  * Ohjelma järjestää kolme merkkijonoa aakkosjärjestykseen
          04  * @author
          05  * @version */
          06 public class Jarj3 {
          07
          08   /**Kysyy käyttäjältä merkkijonon annetulla tulosteella.
          09    *  @param prompt lause, joka käyttäjä näkee ennen tietojen syöttöä
          10    *  @return käyttäjän syöttämä merkkijono ilman rivinvaihtoa */
          11   public static String kysy(String prompt) {
          12     System.out.print(prompt);
          13
          14     // Syöttöpyyntö ja vastauksen lukeminen
          15     BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
          16     try {
          17       return in.readLine();
          18       } catch (IOException ex) { return ""; }
          19   }
          20
          21   /**Pääohjelma
          22    * @param args Komentorivillä annetut parametetrit */
          23   public static void main(String[] args) {
          24     String s1,s2,s3,t;
          25     s1 = kysy("Anna 1. merkkijono >");
          26     s2 = kysy("Anna 2. merkkijono >");
          27     s3 = kysy("Anna 3. merkkijono >");
          28
          29     if ( s1.compareTo(s2) > 0 ) {
          30       t = s1; s1 = s2; s2 = t;
          31     }
          32     if ( s1.compareTo(s3) > 0 ) {
          33       t = s1; s1 = s3; s3 = t;
          34     }
          35     if ( s2.compareTo(s3) > 0 ) {
          36       t = s2; s2 = s3; s3 = t;
          37     }
          38     System.out.println("Jonot "+s1+", "+s2+","+s3+".");
          39   }
          40 }
    
  5. Kolmannen luvun lukeminen voidaan kopioida vaikkapa 2. luvun lukemisesta (rivinumerot viittaavat valmiiseen koodiin):
    1. Siirry rivin 26 alkuun. (nuolet ja [Home])
    2. Merkitse lohkon alku. (paina [Shift] pohjaan ja pidä se siellä)
    3. Siirry seuraavan rivin alkuun. (nuoli alas)
    4. Merkitse lohkon loppu. (päästä [Shift] ylös)
    5. Kopioi lohko leikepöydälle. ([Ctrl-Ins] tai [Ctrl-C])
    6. Liitä lohko leikepöydältä. ([Shift-Ins] tai [Ctrl-V], mahd. uudestaan jos rivi ei tullut kahdesti)
    7. Tee riville tarvittavat muutokset.
  6. Vertailut saadaan vastaavasti kopioimalla rivit 29-31 (ed. esim. mukaiset valmiit rivinrot) kahteen kertaan:
    1. Siirry rivin 29 alkuun. (nuolet ja [Home])
    2. Merkitse lohkon alku. ([Shift] pohjaan ja pidä siellä)
    3. Siirry rivin 32 alkuun. ([nuolet alas])
    4. Merkitse lohkon loppu. ([Shift] ylös)
    5. Kopioi lohko leikepöydälle. ([Ctrl-Ins] tai [Ctrl-C])
    6. Liitä lohko leikepöydältä. ([Shift-Ins] tai [Ctrl-V], mahd. uudestaan)
    7. Tee riveille tarvittavat muutokset.
  7. Tee loput tarvittavat muutokset.
  8. Tallenna ohjelma.
  9. Tarkista ajettava tiedosto ja debuggerin tila. Eclipsellä ja NetBeansilla voi olla useampia debug-istuntoja päällä samanaikaisesti. Muista lopettaa Jarj2-ohjelman debuggaus, ennenkuin alat debugata Jarj3-ohjelmaa (muuten debuggeri saattaa käynnistää väärän ohjelman).
    • NB: Debuggausistunnon voi lopettaa pikanäppäimellä [Shift-F5].
  1. Aja ohjelmaa ja tutki toimiiko. Muista, että debuggeria käyttäessä ohjelma pitää käynnistää Run in debugger-komennolla. (NB: [ALT-F5])
  2. Lisää myös s3 WATCH-ikkunaan. Lohkon voi merkitä myös hiirellä. Kokeile sitäkin, mutta muista, että näppäimistö on aina nopeampi ja tarkempi (kun sen kunnolla opettelee)!
  3. Kirjoittamasi koodin voi sisentää automaattisesti valitsemalla halutun alueen ja komennoilla
    • NB: Ctrl-Shift-F tai hiiren oikean napin ponnahdusvalikosta Reformat Code.

3. Luokkametodit (funktiot, aliohjelmat...)

Muokataan edellisessä luvussa kirjoitettua ohjelmaa niin, että merkkijonojen vaihto tehdään omassa aliohjelmassaan (koska Java on oliokieli, aliohjelman tai funktion sijaan virallinen nimitys olisi luokkametodi tai staattinen metodi).

  1. Muokkaa tiedostosta Jarj3.java uusi tiedosto Jarj3a.java: Jarj3a.java
  2. Laita WATCH-ikkunaan muuttujat s1, s2, s3, a, b ja t.
  3. Kokeile ajaa askel kerrallaan käyttäen sekä [F5] että [F6] (tai voi olla [F7] ja [F8]). Mikä on näppäinten välinen ero?
  4. Kommentoi metodista vaihda kaikki rivit, joilla kutsutaan append- tai delete-metodeita. Lisää niiden tilalle seuraavat rivit:
              a = b;
              b = new StringBuffer(t);
    
  5. Tallenna muutettu ohjelma.
  6. Kokeile ohjelman toimintaa askel kerrallaan. Muuttuvatko s1, s2 ja s3 aliohjelman suorituksen aikana kuten edellisellä kerralla?
  7. Poista tai kommentoi viimeksi kirjoittamasi rivit ja palauta alkuperäiset rivit koodiin.
  8. Käännä Jarj3a.java uudelleen ja kokeile vielä kerran suoritusta askel kerrallaan. Mieti, miksi versiot käyttäytyvät eri tavalla.

Lisätietoa Javan metodeista ja parametrinvälityksestä on luentomonisteessa: luku 8.6.5.

4. Taulukot

Miten edellistä ohjelmaa pitäisi muuttaa mikäli haluttaisiin järjestää 4 lukua? Taitaisi jo tulla varsin sotkuiseksi.

  1. Muutetaan ohjelmaa (kirjoita nimelle Jarj3ta.java, käyttäen pohjana Jarj3.java-ohjelmaa) siten, että apuna käytetään taulukkoa: Jarj3ta.java
  2. Aliohjelma vaihda voidaan hakea tiedostosta Jarj3a.java seuraavasti:
    1. Siirry tiedostoon Jarja3a.java.
    2. Merkitse aliohjelma lohkoksi (siirry alkuun ja [Shift] pohjaan, siirry nuolilla loppuun ja [Shift] ylös).
    3. Kopioi lohko leikekirjaan ([Ctrl-Ins] tai [Ctrl-C]).
    4. Siirry tiedostoon Jarj3ta.java.
    5. Liitä lohko leikekirjasta (siirry haluttuun kohtaan ja paina [Shift-Ins] tai [Ctrl-V]).
  3. Edellinen ohjelma ei ehkä ole yhtä selkeä (?) kuin Jarj3.java, mutta lukujen lukumäärä esiintyy ohjelmassa enää vain yhdessä paikassa. Missä?
  4. Tallenna ohjelma.
  5. Poista WATCH-ikkunasta kaikki tarpeeton:
    1. Siirry WATCH-ikkunaan.
    2. Siirry poistettavalle riville.
    3. Poista rivi. ([DEL])
    4. ...
    5. Siirry takaisin editointi-ikkunaan.
  6. Lisää taulukko jonot sekä muuttujat pienin ja tutki WATCH-ikkunaan.
  7. Aja ohjelmaa askel kerrallaan. Toimiiko täsmälleen vastaavasti kuin Jarj3.java?
  8. Muuta ohjelmassa KOKO-muuttujan arvoksi 5 ja kokeile toimintaa.

5. Järjestäminen ja Java-kielen kirjasto

Järjestämisessä voimme Java-kielen tapauksessa käyttää apuna myös valmista Arrays-luokan metodia sort. Rutiinin käyttämistä varten meidän tarvitsee vain kirjoittaa IComparable-rajapinnan toteuttava luokka, joka osaa verrata järjestettävän taulukon kahta alkiota keskenään palauttaen negatiivisen luvun, nollan tai positiivisen luvun sen mukaan, miten verratattavat alkiot suhtautuvat toisiinsa:

  1. Muuta edellinen ohjelma seuraavanlaiseksi ja tallenna nimellä Jarjta.java: Jarjta.java
  2. Aja ohjelmaa askel kerrallaan. Toimiiko?
  3. Laita keskeytyskohta riville
             return o1.compareTo(o2);
    
  4. sekä lisää muuttujat o1 ja o2 WATCH-ikkunaan. Aja ohjelmaa Run in Debugger-käskyllä. Montako kertaa aliohjelmassa käydään?
  5. Kirjoita vielä edellisestä korjaillen seuraava ohjelma nimelle Jarjnum.java:
  6. Ohjelma joka järjestää merkkijonojen sijasta kokonaislukuja, mutta käyttää samaa sort-metodia. Lukujen järjestämistä varten ei tarvita compare-funktiota. Merkkijonon (String) voi muuttaa kokonaisluvuksi esim:
    int luku;
    ...
    luku = Integer.parseInt(s);
    
  7. Aja ohjelmaa rivi kerrallaan. Kokeile luvut-taulukon arvojen muuttamista ajon aikana.
    • NB: Valitse vasemmassa reunassa olevasta Debug-ikkunasta Local Variables. Avaa luvut-muuttuja. Paina hiiren nappia jonkin indeksin kohdalla Value-sarakkeessa. Kirjoita uusi arvo.
  8. Aja ohjelma ja ota aika kauanko ohjelman suoritukseen menee.

6. Tavoite

Edellisistä ohjelmista Jarj3a.java näytti ehkä kaikkein selkeimmältä. Siinä oli kuitenkin se vika, että muuttaminen useamman luvun käsittelyä varten vaatisi suuria muutoksia itse ohjelmaan.

Jarj3ta.java voidaan helposti muuttaa käsittelemään useampaakin lukua. Se ei kuitenkaan ole sellaisenaan erityisen selkeä.

Jatkossa pyritään siihen, että em. ohjelma voitaisiin kirjoittaa muodossa:

    ...
    { /* Pääohjelma */
      Luvut luvut = new Luvut();
      luvut.lue(System.in);
      luvut.jarjesta();
      luvut.tulosta(System.out)
      // tai System.out.println(luvut);
    }

Pääohjelman ja "ylemmän tason" aliohjelmien pitäisi siis olla mahdollisimman selkeitä. Tämä parantaa ohjelman luettavuutta ja ylläpidettävyyttä.