Tarkastusselostuksia ja mallivastauksia 2. välikokeeseen 4.5.1998: ========================================================================= 1. ========================================================================= Jussi Sarkkinen: Selitä tiiviin täsmällisesti: Yleistä: Kustakin kohdasta oli jaossa yksi piste, yhteensä siis enintään viisi pistettä. Vastausten arvostelussa perusteena pidin käsitteen ymmärtämistä: jos vastauksellaan osoitti sisäistäneensä kysytyn asian, sai yhden pisteen, jos osoitti olevansa asiasta melkein perillä, sai puoli pistettä. Ymmärryksensä saattoi osoittaa monilla muillakin tavoilla kuin seuraavassa olevilla mallivastauksilla. Pelkistä esimerkeistä ja arvauksista ilman perusteluja ei kuitenkaan pisteitä herunut. viittaustyyppi (reference type) Viittaustyyppejä ovat luokkatyypit, taulukkotyypit ja rajapintaluokkatyypit. Viittautyyppisen muuttujan arvo on viite olioon; tällöin esim. kahta viittaustyyppistä muuttujaa vertaillessa vertaillaankin vain sitä, osoittavatko ne samaan olioon. Yleensä viittaustyyppisen muuttuja käsittely täytyykin suorittaa metodeilla. aliluokka (subclass) Aliluokka täydentää, erikoistaa yliluokkansa määrittelyitä. Se periiyliluo- kaltaan kaikki ei-privatet metodit ja kentät, ei kuitenkaan konstruktoreita. Javassa aliluokka voi periä vain yhdeltä yliluokalta; luokalla voi olla kuitenkin useita aliluokkia eikä se ole niistä mitenkään tietoinen. Aliluokkan ilmentymään voidaan käyttää yliluokkansa ilmentymän tilalla, muttei toisinpäin. Kaikki Javan luokat ovat Object-luokan aliluokkia. käännösyksikkö (compilation unit) Käännösyksikkö on tiedosto, joka voi sisältää (tässä järjestyksessä!): package-määreen, joka ilmoittaa mihin pakkaukseen tiedostossa olevat luokat (ja rajapintaluokat) on tarkoitus sijoittaa import-määreitä, jotka ilmoittavat pakkaukset, jotka annetaan käännösyksikön luokkien (ja rajapintaluokkien) käyttöön. luokkien (ja rajapintaluokkien) määrittelyitä Jos tiedoston alussa ei ole package-määrettä, class-tiedostot asetetaan ns. n imettömään pakkaukseen. Se on Java-toteutuksissa yleensä "nykyhakemisto", so. hakemisto, jossa class-tiedosto sijaitsee. Käännösyksikössä voi olla vain yksi luokka, jolle on määritelty näkyvyydeksi public. pakkaus (package) Pakkaus on käytännön ohjelmistotuotannon väline. Javassa class-tiedostot kerätään pakkauksiin; yhteen pakkaukseen on tapana kerätä luokkia, jotka liittyvät jotenkin toisiinsa. Pakkaukset voidaan myös jäsennellä alipakkauksiksi jne. Pakkaus muodostaa oman nimiavaruutensa. Käännösyksikön luokat sijoitetaan pakkaukseen ilmaisulla package pakkaus; Pakkausten toteuttaminen on Javan ulkopuolinen asia; usein yksi pakkaus vastaa yhtä hakemistoa tiedostojärjestelmässä. Pakkaukseen sijoitettuihin luokkiin voidaan viitata joko suoraan muodossa pakkaus.Luokka taikka käyttää import-komentoa tuomaan pakkauksen käännösyksikön luokkien käyttöön. poikkeus (exception) Poikkeukset ovat "poikkeuksellisia tilanteita" kesken ohjelmansuorituksen. Java tarjoaa välineet poikkeusten käsittelyyn; kieleen on määritelty paljon valmiita poikkeuksia ja tarvittaessa poikkeuksia voi laatia myös itse. Kaikkien poikkeuksien yliluokka on Exception. Joihinkin poikkeuksiin ohjelmoijan on varauduttava (checked), jotkin poikkeukset taas oletusarvoisesti kaatavat ohjelman (unchecked). Checked -poikkeuksen mahdollistavaa metodia käyttäessä ohjelmoijan on joko ilmoitettava, että poikkeus voi tulla ("throws", heitetään poikkeus seuraavan tason huoleksi) tai itse käsiteltävä poikkeus "try-catch" -rakenteella. ========================================================================= 2.a ========================================================================= Marko Ullgren: Tehtävän 2a ratkaisu: public class Kilpailija { private int yhteispisteet; private String nimi; public Kilpailija() { this.yhteispisteet = 0; this.nimi = ""; } public void asetaPisteet(int pisteSumma) { this.yhteispisteet = pisteSumma; } public int otaPisteet() { return this.yhteispisteet; } public void asetaNimi(String nimi) { this.nimi = nimi; } public String otaNimi() { return this.nimi; } public boolean isompiNimi(Kilpailija toinen) { return ( this.nimi.compareTo( toinen.otaNimi() ) > 0); } public boolean isommatPisteet(Kilpailija toinen) { return ( this.yhteispisteet > toinen.otaPisteet() ); } } Arvostelu: Pisteytys: Luokan rakenteen, kenttien sekä konstruktorin oikeasta toteutuksesta sai 2 pistettä. Aksessorimetodeista sai 1,5 pistettä, samoin vertailumetodeista 1,5 pistettä. Virheet: Jos kenttien näkyvyysmäärittely puuttui tai se oli jotain muuta kuin private, vähennettiin yksi piste. Jos metodit oli määritelty privateiksi, vähennettiin 1,5 pistettä, jos näkyvyysmäärittely puuttui vähennettiin yksi piste. Metodien määritteleminen static - määreellä luokkakohtaisiksi on paha virhe, josta vähennettiin yhdestä kahteen pisteeseen. Jos merkkijonoja oli vertailtu < ja > operaattoreilla, rankaistiin yhden pisteen vähennyksellä. Jos oli muistanut, että merkkijonojen vertailuun on oma metodinsa. mutta toteutus ontui, nipsaistiin pois puoli pistettä. Pienet virheet compareTo - metodin käytössa katsottiin läpi sormien. ========================================================================= 2.b ========================================================================= Matti Pauna: arvosteluperusteet: - aakkosjärjestämisen tai pistejärjestämisen puuttuminen vähentää 1 ja 1/2 pistettä kumpikin - nimien yksikäsitteisyyden tarkistuksen puuttuminen vähentää 1 pisteen - pienemmät virheet vähentävät 1/2 pistettä virheeltä esimerkkiratkaisu: // Kilpailu.java // 2. välikokeen tehtävän 2b esimerkkiratkaisu, kevät 1998 // Matti Pauna public class Kilpailu { private static void jarjestaNimet(Kilpailija[] taulu) { for (int i=0; i < taulu.length-1; i++) for (int j=i+1; j < taulu.length; j++) if (taulu[i].isompiNimi(taulu[j])) { Kilpailija apu = taulu[i]; taulu[i] = taulu[j]; taulu[j] = apu; } } private static void jarjestaPisteet(Kilpailija[] taulu) { for (int i=0; i < taulu.length-1; i++) for (int j=i+1; j < taulu.length; j++) if (taulu[j].isommatPisteet(taulu[i])) { Kilpailija apu = taulu[i]; taulu[i] = taulu[j]; taulu[j] = apu; } } private static void tulosta(Kilpailija[] taulu) { for (int i=0; i < taulu.length; i++) System.out.println(taulu[i].otaNimi() + "\t" + taulu[i].otaPisteet()); } public static void main(String[] args) { Kilpailija[] kilpailijat = new Kilpailija[20]; for (int i=0; i < kilpailijat.length; i++) { boolean ok; String nimi; int tpisteet, opisteet; do { ok = true; System.out.println("Anna kilpailijan " + (i+1) + " nimi. " + "Ei samaa nimeä kahteen kertaan."); nimi = Lue.rivi(); for (int j=0; j < i; j++) if (kilpailijat[j].otaNimi().equals(nimi)) { System.out.println("Nimi " + nimi + " esiintyy jo. " + "Anna uusi"); ok = false; break; } } while (!ok); do { System.out.println("Anna kilpailijan " + (i+1) + " oikeellisuuspisteet (0-50). "); opisteet = Lue.kluku(); if (opisteet < 0 || opisteet > 50) System.out.println("Pisteet eivät kelpaa. Anna uudet."); } while (opisteet < 0 || opisteet > 50); do { System.out.println("Anna kilpailijan " + (i+1) + " tyylipisteet (0-50). "); tpisteet = Lue.kluku(); if (tpisteet < 0 || tpisteet > 50) System.out.println("Pisteet eivät kelpaa. Anna uudet."); } while (tpisteet < 0 || tpisteet > 50); kilpailijat[i] = new Kilpailija(); kilpailijat[i].asetaNimi(nimi); kilpailijat[i].asetaPisteet(opisteet+tpisteet); } jarjestaNimet(kilpailijat); System.out.println("\nKilpailijat aakkosjärjestyksessä\n"); tulosta(kilpailijat); jarjestaPisteet(kilpailijat); System.out.println("\nKilpailijat paremmuusjärjestyksessä\n"); tulosta(kilpailijat); } } ========================================================================= 3. ========================================================================= Kari Vasko: Tehtävässä 3 pyydettiin selittämään täsmällisen tarkasti mitä tarkoittaa luokan lataaminen ja olion luonti. Jos kysymykseen vastasi luvussa 4.2 esitetyllä tarkkuudella, sai täydet kuusi pistettä. Täten täydet pisteet sai melko vähäisellä kirjoittamisella. Alla on minimaalinen vastaus, jolla sai kuusi pistettä: suora lainaus luvun 4.2 kappaleesta "Luokan lataaminen ja olion luonti". **************************************************************************** Kun suoritetettava ohjelma viittaa ensimmäisen kerran johonkin luokkaan, tuo luokka ladataan (load) muistiin. Tällöin luokan staattinen kalusto asetetaan alkutilaan: luokkamuuttujat saavat alkuarvonsa, mahdolliset staattiset alustuslohkot suoritetaan. Aina kun suoritettava ohjelma luo olion eli luokan ilmentymän new-operaatiolla, tuon olion oma kalusto asetetaan alkutilaan: ilmentymän muuttujat saavat alkuarvonsa ja jokin konstruktori suoritetaan (nimenomaan tässä järjestyksessä!). **************************************************************************** Pisteitä annettiin siten, että sekä luokan lataamisesta että olion luonnista pisteitä oli jaossa kumpaisestakin 3 pistettä (3+3). Seuraavassa muutamia yleisimpiä virheitä/puutteita, joita ilmeni vastauksissa: - Olion luonnissa ei mainita konstruktorin kutsua - Konstruktorin kutsu väitetään tapahtuvaksi ennen ilmentymä- muuttujien alkuarvojen asettamista. - Luokan lataaminen väitetään tapahtuvaksi aina kun olio luodaan. - Staattisista alustuslohkoista ei ole mainintaa. Luokan lataamisen selittämisessä tosin riitti, jos mainitsi, että staattiset rakenteet/kalusto asetetaan alkutilaan. Sen ei riittänyt, jos mainitsi ainoastaan luokan staattisten attribuuttien/kenttien alustuksen. Ja muutama vähemmän yleinen: - Olion luonti tapahtuu pääohjelman kehoitteesta. - Luokan lataaminen tarkoittaa luokan luomista; sen metodien ohjelmointia. ========================================================================= 4. ========================================================================= Asko Saura: Johdatus ohjelmointiin Asko Saura K98 2. välikoe 22.5.1998 Tehtävä 4 Arvosteluperusteet (max. pisteet 5) -Miinuksia: (lähtökohta 5 p, min 2 p) -1½ konstruktori taikka olio väärinymmärretty puuttuva ohjelman osa, kuvattu pseudokoodina tai muuten, esim. lukee vain joka toisen rivin. -1 väärä SyoTdston käyttö ei esitellä muuttujia pikkuvirhe algoritmissa käsitevirhe: ohjelma -½ kielioppivirhe staattinen viittaus ilmentymämuuttujaan +Plussia: (lähtökohta 0 p, max 1,5 p) +1 algoritmin oikea idea (ihmiseksi/pseudokoodina) +½ oikea Lue-luokan käyttö oikea SyoTdsto-luokan käyttö joku lukeva toisto-algoritmi En ottanut pisteitä pois siitä, jos tulostaa rivi.toCharArray()-taulukon println:llä (tuplarivinvaihdot...). Yleisin virhe oli sekvenssi: String s; s=null; s.jotain()...NullPointerException Konstruktorivirheitä oli aika vähän, I think. /* Johdatus ohjelmointiin K98 * 2. Välikoe tehtävä 4 * Malliratkaisu - asaura * Tulostaa tiedoston ne rivit, joilla annettu merkki on ensimmäisenä. */ public class ListaaRuudulleValitut { public static void main(String[] args) { System.out.print("Syötä tiedoston nimi : "); System.out.flush(); SyoTdsto tdsto = new SyoTdsto(Lue.rivi()); System.out.print("Syötä tulostettavien rivien aloitusmerkki :"); System.out.flush(); char merkki = Lue.merkki(); String rivi = tdsto.lue(); // luetaan eka rivi talteen while ( rivi != null ) { if (rivi.charAt(0) == merkki) System.out.println(rivi); rivi = tdsto.lue(); } } }