Sivun sisältö voi vielä muuttua!
Nämä harjoitukset liittyvät oppimateriaalin lukuihin 8 – 11.
Kaikki harjoitustehtävät on syytä tehdä. Jotkin tehtävät on merkitty keltaisella värillä. Ne ovat ehkä hieman muita haastavampia. Ilman niitäkin harjoituksista voi saada maksimipisteet, mutta ne lasketaan silti mukaan harjoituspisteitä määrättäessä – ne voivat siis korvata joitakin haasteettomampia tehtäviä tms. Mutta ennen kaikkea noista keltaisista tehtävistä sitä vasta oppiikin!
Huom:
// 5. harjoitukset, tehtävä 2.2, Oili Opiskelija
Ensimmäisen viikon tehtävässä 4.4 ohjelmoitiin MyString-luokkaan MyString-olioiden järjestyksen määräävä metodi
public int compareTo(MyString verrattava)
Kerro kääntäjällekin, että MyString-olioille on totetutettu tällainen vertailtavuus. Kertominen tapahtuu ilmoittamalla luokan otsikossa, että luokka toteuttaaa rajapintaluokan Comparable<MyString>.
Tämän jälkeen kääntäjä sallii MyString-olioita käsiteltävän yleiskäyttöisillä työkaluilla, jotka on ohjelmoitu osaamaan käyttää kaikkia olioita, joiden luokka toteuttaa rajapintaluokan Comparable. (Vrt: Juustotehdas osaa lypsää kaikkia eläimiä, joiden luokka totetuttaa rajapintaluokan Lypsava.)
Java-APIn Collections-luokka tarjoaa koko joukon yleiskäyttöisiä kirjastometodeita (eli julkisia luokkametodeita), joilla mitä tahansa järjestyksen omaavien olioiden kokoelmia voidaan käsitellä.
"Omata järjestys" siis tarkoittaa juuri sitä, että olion luokka toteuttaa rajapintaluokan Comparable.
Collections-luokka löytyy pakkauksesta java.util.
Huomaa, että rajapintaluokka Collection on ihan eri asia kuin luokka Collections, etsi siis juuri tuo jälkimmäinen! Älä myöskään häkelly metodien kummallisista otsikoista – "kummallisuudet" liittyvät Javan ns. geneerisiin tyyppeihin.
Kokoelmiksi (Collection) Javassa kutsutaan monia erilaisia valmiita tietojoukkojen esittämiseen laadittuja luokkia. Tuttu esimerkki on ArrayList. Juuri tällaisten kokoelmaolioiden käsittelyyn Collections-luokka välineitä tarjoaa. Esimerkkejä kirjaston välineistä: binarySearch, max, min, sort.
Kokeile seuraavaa:
import java.util.Collections; ... ArrayList<MyString> nimet = new ArrayList<MyString>(); MyString beepeli = new MyString("Beepeli"); MyString yypeli = new MyString("Yypeli"); MyString aapeli = new MyString("Aapeli"); nimet.add(beepeli); nimet.add(yypeli); nimet.add(aapeli); System.out.println("Nimet alkuperäisessä järjestyksessä:"); for(MyString nimi: nimet) { System.out.println(nimi); } Collections.sort(nimet); System.out.println("Nimet järjestyksessä:"); for(MyString nimi: nimet) { System.out.println(nimi); }
Tulostuksen pitäisi näyttää seuraavalta:
Nimet alkuperäisessä järjestyksessä: Beepeli Yypeli Aapeli Nimet järjestyksessä: Aapeli Beepeli Yypeli
Tässä tehtävässä on paljon luettavaa (ja toivottavasti ymmärrettävää!) ja varsin vähän ohjelmointia...
Aika usein Ohjelmoinnin perusteet -kurssin kokeessa on ollut seuraavanlainen tehtävä:
Toteuta seuraava arvauspeli vuorovaikutteisena eli keskustelevana ohjelmana: Aamuisin ohjelmalle syötetään jokin määrä merkkijonoja missä järjestyksessä tahansa; olkoot nämä merkkijonot onnensanoja. Sama onnensana saa esiintyä useamminkin kuin kerran. Onnensanojen syötön päättää sana "loppu", joka ei itse ole onnensana.
Päivän mittaan pelaajat käyvät sitten arvaamassa sanoja. Jos pelaaja onnistuu arvaamaan jonkin onnensanan, ohjelma onnittelee pelaajaa. Jos pelaaja epäonnistuu, ohjelma esittää valittelunsa. Ohjelman suoritus päättyy, kun arvatuksi sanaksi syötetään "loppu". Tällöin ohjelma tulostaa oikeiden ja väärien arvausten määrän. Tehokkuussyistä sanojen hakeminen taulukosta on ohjelmoitava binäärihakua käyttäen.
Jatkokurssilaisena pääset helpommalla! Totetuta siis peli vaaditulla tavalla, mutta käytä hyväksesi Collections-kirjaston välineitä. Sanat esitetään MyString-oliona. Muista miten edellä mainittiin muutama esimerkki kirjaston välineistä: binarySearch, max, min, sort. Älä siis niitä tällä kertaa itse ohjelmoi.
Huom: Käytä siis tuota pyydettyä binarySearch-kirjastometodia, älä contains-aksessoria. Jälkimmäinen ei nimittäin toimi ilman lisätoimia! Selitystä alla.
Käyttöesimerkki (tietokone tässä kursiivilla):
Syötä onnensanat. Sana "loppu" lopettaa. kissa koira amuletti panda loppu Arvaa onnensana. Sana "loppu" lopettaa. lusikka Voi ei! koira Onnea! amuletti Onnea! loppu Oikeita: 2 Vääriä: 1
Miksi contains ei toimi:
Luennoja kävi pajassa ja panikoi, kun yksi opiskelija ei
saanut contains-aksessoria toimimaan. Panikoi syyttä,
koska ei tuota tehtävässä pyydettykään!
On silti ehkä opettavaista kuulla, miten metodin saisi toimimaan
MyString-sisältöiselle kokoelmaoliolle.
Tämä ei kuitenkaan kuulu koealueeseen:
Kokoelmaolioiden (esim. ArrayList) contains-metodi
ei toimi oikein, ellei MyString-luokkaan lisää perityn
equals-metodin syrjäyttävää metodia.
Lisää siis MyString-luokkaan vaikkapa seuraava:
Jo alkaa Lyyti kirjoittaa! :-)
Selitystä:
public boolean equals(Object toinen) {
return this.compareTo((MyString)toinen) == 0;
}
Kokonaislukujoukkojen järjestys määräytyköön joukkojen mahtavuuden eli alkiolukumäärän perusteella. Muokkaa jostakin IntJoukko-luokan toteutuksestasi Comparable-järjestyvä luokka JarjestyvaIntJoukko ja havainnollista joukkojen järjestyvyyttä pienellä sovelluksella.
Luennoilla ja kurssimateriaalin luvussa 6 (aliluku 7) vertailtiin pikajärjestämistä ja lisäysjärjestämistä ohjelmalla VertaileLisQuick.java (nanosekuntiversio: VertaileLisQuickB.java).
Olisi kiinnostavaa tietää, ovatko Javan Collections-luokan ohjelmoineet ammattilaiset osanneet tehdä paremman järjestämisalgoritmin kuin kurssilla tavattu ihan perusmuotoinen pikajärjestäminen.
Ja sehän selvitetään! Muokkaa mittausohjelmaa siten, että sillä vertaillaan pikajärjestämistä ja Collections.sort-metodia. Pikajärjestäminen järjestää tavallisen int[]-taulukon, kirjastometodi vastaavansisältöisen ArrayList-olion.
Syötteiden lukemisen välineitä voidaan toteuttaa monenlaisella logiikalla. Pojimmiltaan kaikki ohjelmalle tarjottu syöte on pelkkää bittivirtaa. Yleensä ohjelmoijalle on onneksi tarjolla välineitä, joilla lukuoperaatioita voidaan kirjoittaa korkeammalla abstraktiotasolla: luetaan tavuja, merkkejä, rivejä, lukuja, ...
Lukemisen välineitä voidaan kutsua tyypitetyiksi, jos ohjelmoija voi/saa ilmaista, minkä tyyppisen tiedon hän haluaa lukea. Esimerkki tällaisesta on vaikkapa Javan Scanner-luokan tarjoama välineistö: nextInt, nextDouble, ...
Tyypitetyssä lukemisessa virheisiin voidaan suhtautua kahdella tavalla: Yksi tapa on antaa tyypiltään virheellisen syötteen keskeyttää ohjelman toiminta. Esimerkiksi kokonaisluvuksi kelpaamaton syöte aiheuttaa virhetilanteen, poikkeuksen, joka päättää ohjelman suorituksen ellei ohjelmoija itse sieppaa poikkeusta ja käsittele tapausta. Juuri tähän tapaan toimii Scanner-olio.
Toinen mahdollisuus on tehdä lukuoperaatioista sellaisia, että "virheitä ei voi tulla" – ainakaan tavanomaisissa virhetilanteissa. Esimerkiksi lukujen lukeminen voidaan tehdä sitkeäksi: lukuoperaatio itse väsymättä pyytelee kunnollista syötettä kunnes/jos viimein saa sellaisen. Tässäkin strategiassa jotkin vakavat virheet saattavat johtaa ohjelman suorituksen keskeyttämiseen, mutta sekin voidaan ehkä tehdä ymmärrettävämmin kuin Java-ohjelmissa oletusarvoisesti tapahtuu.
Rakennellaan vaiheittain kirjastoluokka Shell standardisyöttövirran turvalliseen tyypitettyyn lukemiseen.
Toteuta luokka Shell, jolla voi lukea stardardisyöttövirran rivejä yksi kerrallaan.
APIn lähtökohta:
Shell on syytä toteuttaa Scanner-olioa käyttäen. Riviksi kelpaa millainen merkkijono tahansa; Scannerin tapa lukea rivejä soveltuu siis sellaisenaan. Scannerin InputStream-parametrinen konstruktorikaan ei aiheuta poikkeuksia. Mutta metodi nextLine voi epäonnistua kahdella tavalla:
NoSuchElementException - if no line was found IllegalStateException - if this scanner is closed
Vuorovaikutteisessa ohjelmassa ensinmainittu poikkeus aiheutuu, kun käyttäjä kirjoittaa ohjelmalle tiedostonlopun (Linux ctrl-d, Windows ctrl-z). Ensinmainittu poikkeus ei tällä kertaa ole virhetilanne, ks. metodin selitys. Varaudu kuitenkin toiseen poikkeukseen antamalla selkeä virheilmoitus ja lopettamalla ohjelman suoritus.
String rivi = Shell.kysyString("Anna rivi: "); // Sama toisin: System.out.print("Anna rivi: "); rivi = Shell.kysyString(""); // vaiteliaana: rivi = Shell.kysyString(""); //... while (true) { // "1.5-kertainen" toisto rivi = Shell.kysyString(""); if (rivi == null) // <<<<< toiston lopetus! break; System.out.println(rivi); } ...
Esimerkin suoritus (käyttäjä tässä kursiivilla):
Anna rivi: kissantassu Anna rivi: pallo mehukatti piimä piimä aurinkokuningas aurinkokuningas [Linuxin ctrl-d tai Windowsin ctrl-z]
Täydennetään Shell-luokkaa kokonaislukujen lukemisen taidolla.
API-täydennys:
Ei ole kokonaisluku!Jos syöte ei kelpaa kokonaisluvuksi, metodi toistaa pyyntönsä.
Ohjelmaesimerkki:
int luku = Shell.kysyInt("Anna kokonaisluku! "); System.out.println("Lukusi oli " + luku); int luku = Shell.kysyInt(""); System.out.println("Lukusi oli " + luku); luku = Shell.kysyInt("Paljonko on tusina? "); if (luku != 12) System.out.println("Väärin!");
Käyttöesimerkki:
Anna kokonaisluku! Mörkö Ei ole kokonaisluku! Anna kokonaisluku! 4008 Paljonko on tusina? Mörkö Ei ole kokonaisluku! Paljonko on tusina? 13 Väärin!
Huomaa että kokonaisluvun lukeminen kannattaa toteuttaa siten, että koko syöttörivi käsitellään. Muuten saattaa tulla tuttuja(?) synkronointiongelmia. Lue siis tarjokas Stringinä. Salli myös ylimääräiset alku- ja loppuvälilyönnit.
Neuvo: Käytä luentomateriaalin luvussa 11 esiteltyjä välineitä Integer.parseInt(...) ja trim().
Täydennetään luokkaa Shell rajoitetulla välillä olevien kokonaislukujen lukemisen taidolla. Kuormitetaan yhä lisää metodia kysyInt.
API-täydennys:
throw new IllegalArgumentException("Tyhjä lukualue!");
Ohjelmaesimerkki:
int luku = Shell.kysyInt(1, "Anna positiivinen kokonaisluku! "); System.out.println(luku); luku = Shell.kysyInt("Anna ei-positiivinen kokonaisluku! ", 0); System.out.println(luku); luku = Shell.kysyInt(-100, "Anna luku väliltä -100-100! ", 100); luku = Shell.kysyInt(12, "böö! ", 6);
Esimerkki ohjelmanpätkän suorituksesta:
Anna positiivinen kokonaisluku! Mörkö Ei ole kokonaisluku! Anna positiivinen kokonaisluku! -123 Anna positiivinen kokonaisluku! 123 123 Anna ei-positiivinen kokonaisluku! 1 Anna ei-positiivinen kokonaisluku! 0 0 Anna luku väliltä -100-100! 123 Anna luku väliltä -100-100! -99 -99 Exception in thread "main" java.lang.IllegalArgumentException: Tyhjä lukualue! at TiesMika.main(TiesMika.java:15)
Täydennetään Shell-luokkaa vielä desimaalilukujen lukemisen taidolla.
API-täydennys:
Ohjelmaesimerkki:
double luku = Shell.kysyDouble("Anna luku! "); luku = Shell.kysyDouble("Mikä on lieriön korkeus? "); luku = Shell.kysyDouble("Miten kaukana on pitkällä? ");
Käyttöesimerkki:
Anna luku! Mörkö Ei ole desimaaliluku! Anna luku! -123.4 Mikä on lieriön korkeus? Mörkö Ei ole desimaaliluku! Mikä on lieriön korkeus? 3.14 Miten kaukana on pitkällä? 123.456e+10
Neuvo: Käytä luentomateriaalin luvussa 11 esiteltyjä välineitä Double.parseDouble(...) ja trim().
Tämä tehtäväsarja on luontevinta tehdä käyttöjärjestemän komentotulkki-ikkunassa. Jos välttämättä haluat käyttää NetBeans-ympristöä tässäkin sarjassa, ohjeet löytyvät tästä: NetBeans-projektien ajaminen komentotulkista.
Laaditaan joukko ohjelmia, jotka suodattavat (filtteröivät) tai muokkaavat standardisyöttövirtaa tavalla tai toisella erilaiseksi standarditulosvirraksi. Näitä ohjelmia voi toki suorittaa näppäimistöltä ja näytöltä, mutta niiden pääasiallinen käyttötarkoitus liittyy tiedostojen käsittelyyn uudelleenohjauksen avulla.
Ohjelma laskee tiedoston merkkien määrän. Mukaan ei lasketa rivinvaihtomerkkejä. Ohjelman ainoa tuloste on yksi kokonaisluku.
Siis: Ohjelma lukee standardisyöttövirrasta rivejä ja kirjoittaa standarditulosvirtaan luettujen rivien lukumäärän.
Käyttöesimerkki (tässä merkki $ esittää komentotulkin kehoitemerkkiä eli "promptia"):
$ java LaskeMerkit eka toka [Linuxin ctrl-d tai Windowsin ctrl-z] 7 $ java LaskeMerkit < tiedosto.txt 49876 $
Ohjelma muokkaa tiedostosta sellaisen, jossa kaikki pienet kirjaimet on muutettu suuriksi. Menettelyllä voi olla käyttöä, kun etsitään tekstimassasta sanoja piittaamatta siitä, onko ne kirjoitettu isoin vai pienin kirjaimin.
Siis: Ohjelma lukee standardisyöttövirrasta rivejä ja kirjoittaa standarditulosvirtaan lukemansa rivit sellaisina, joissa kaikki pienet kirjaimet on korvattu isoilla kirjaimilla.
Luokassa String on kelpo väline homman vaivattomaan hoiteluun.
Käyttöesimerkki:
$ java Suurenna Ei tätä nyt ihan tähän ole tarkoitettu. EI TÄTÄ NYT IHAN TÄHÄN OLE TARKOITETTU. [Linuxin ctrl-d tai Windowsin ctrl-z] $ java Suurenna < koe.txt TÄMÄ KAIKKI TULEE TUOSTA TIEDOSTOSTA! $ java Suurenna < koe.txt > isokoe.txt $
Ohjelma suodattaa pois kaikki rivit, joilla ei esiinny komentoriviparametrina annettua merkkijonoa. Jos ohjelma käynnistetään ilman komentoriviparametria, se antaa esimerkin mukaisen virheilmoituksen.
Siis: Ohjelma lukee standardisyöttövirrasta rivejä ja kirjoittaa standarditulosvirtaan ne ja vain ne rivit, joilla esiintyy annettu merkkijono.
Käyttöesimerkki:
$ java SuodataRiveja Virhe: komennolle pitää antaa suodatinsana! $ java SuodataRiveja kissa kissa kävelee. kissa kävelee. Kissa kävelee. Koira kävelee. Kaikissa tapauksissa. Kaikissa tapauksissa. moi vaan [Linuxin ctrl-d tai Windowsin ctrl-z] $ java SuodataRiveja kissa < teos.txt > kissateos.txt $
Ohjelma muokkaa syötteestä sellaisen version, jossa joka rivin alkuun lisätään rivinumero, kaksoispiste ja välilyönti.
Siis: Ohjelma lukee standardisyöttövirrasta rivejä ja kirjoittaa standarditulosvirtaan kaikki luetut rivit siten, että kunkin rivin alkuun lisätään rivinumero, kaksoispiste ja välilyönti.
Käyttöesimerkki:
$ java RiveilleNumerot Päivää! 1: Päivää! abc 2: abc [Linuxin ctrl-d tai Windowsin ctrl-z] $ java RiveilleNumerot < koe.txt 1: eka rivi 2: .... 3: kolkku 4: eikä muuta $ java RiveilleNumerot < tiedosto.txt > n_tiedosto.txt $
Ohjelma laskee tiedoston eräiden merkkiluokkien prosentuaalista osuutta tiedoston kokonaismerkkimäärästä komentoriviparametrin ohjaamalla tavalla:
Välilyöntejä, sarkaimia, rivin loppuja, ym. "white spacea" ei tässä laskennassa oteta mukaan kokonaismerkkimäärään.
Ohjelman ainoa tuloste on kokonaislukuna ilmaistu prosenttiluku.
Jos ohjelma käynnistetään ilman komentoriviparametria tai parametri on virheellinen, ohjelma antaa esimerkin mukaisen virheilmoituksen.
Käyttöesimerkki:
$ java VokKonsMuu Komentoriviparametri (v, k tai e) puuttuu! $ java VokKonsMuu ö Komentoriviparametri (v, k tai e) puuttuu! $ java VokKonsMuu v abc defg hij [Linuxin ctrl-d tai Windowsin ctrl-z] 30 $ java VokKonsMuu v < MinaOlliJaOrvokki.txt 67 $
Tehdään konkreettista kirjallisuudentutkimusta: Tutkitaan Juhani Ahon romaania Rautatie (Rautatie.txt) ja Mark Twainin teosta Huckleberry Finn (HuckleberryFinn.txt).
Käytä edellä tehtyjä välineitä ja luennolla esiteltyä ohjelmaa LaskeRivit.java. Laadi niistä komentoputkia seuraavia tutkimuksia varten.
Huomaa että teostiedostot ovat suoraan Gutenberg-projektin tarjoamassa muodossa. Jos haluat luotettavia tutkimustuloksia, tiedostoista kannattaa editoida pois turhat osat.
Edellä tehtiin yksittäisiä pieniä ohjelmia kirjallisuudentutkimuksen tarpeisiin. Nyt toteutetaan työkalu, jolla tutkija voi ehkäpä vaivattomammin tutkia tekstejä.
Voit pyrkiä uudelleenkäyttämään toteuttamiesi työkalujen algoritmeja tässä tehtävässä sillä kauhistellulla copy-and-paste-tekniikalla. Mutta odotahan vaan, mitä seuraa...
Toteuta komentotulkkilogiikalla tekstilaboratorio, joka tarjoaa seuraavat palvelut:
Nykytiedosto on siis laboratorion keskeinen käsite. Tämä tiedosto on tutkimuksen ja käsittelyn kohteena.
Käyttöesimerkki:
$ java Tekstilaboratorio Ei tiedostoa. 1 lue 2 tallenna 3 lopeta 1 Mikä? KesayonAjatelma.txt Ei löydy tiedostoa KesayonAjatelma.txt Ei tiedostoa. 1 lue 2 tallenna 3 lopeta 1 Mikä? KesayonUnelma.txt Tiedosto: KesayonUnelma.txt 1 lue 2 tallenna 3 lopeta 4 Virheellinen komento! Tiedosto: KesayonUnelma.txt 1 lue 2 tallenna 3 lopeta 3 Tiedostoa ei ole tallennettu. Lopetetaanko silti? (k=kyllä) EI! Tiedosto: KesayonUnelma.txt 1 lue 2 tallenna 3 lopeta 2 Millä nimellä talteen? SyysyonUnelma.txt SyysyonUnelma.txt on jo olemassa. Korvataanko se? (k=kyllä) k Tiedosto: SyysyonUnelma.txt 1 lue 2 tallenna 3 lopeta 3 $
Lisää laboratorioon komento merkkejä, joka laskee ja tulostaa nykytiedoston merkkien määrän. Mukaan ei lasketa rivinvaihtomerkkejä.
Käyttöesimerkki:
$ java Tekstilaboratorio Ei tiedostoa. 1 lue 4 merkkejä 2 tallenna 3 lopeta 1 Mikä? Rautatie.txt Tiedosto: Rautatie.txt 1 lue 4 merkkejä 2 tallenna 3 lopeta 4 189233 Tiedosto: Rautatie.txt 1 lue 4 merkkejä 2 tallenna 3 lopeta 3 $
Lisää laboratorioon komento Operaatio suurenna, joka muokkaa nykytiedostosta sellaisen, jossa kaikki pienet kirjaimet on muutettu suuriksi.
Huomaa että nykytiedostoa muokattaessa ohjelman on syytä luoda tilapäinen aputiedosto, joka on syytä poistaa ohjelman loppuessa. Alkuperäisiä tiedostoja ei tietenkään saa muuttaa.
Käyttöesimerkki:
$ java Tekstilaboratorio Ei tiedostoa. 1 lue 4 merkkejä 2 tallenna 5 suurenna 3 lopeta 1 Mikä? Rautatie.txt Tiedosto: Rautatie.txt 1 lue 4 merkkejä 2 tallenna 5 suurenna 3 lopeta 5 Tiedosto: Rautatie.txt 1 lue 4 merkkejä 2 tallenna 5 suurenna 3 lopeta 3 $
Lisää laboratorioon komento suodata, joka poistaa nykytiedostosta kaikki rivit, jotka eivät sisällä annettua merkkijonoa.
Huomaa että nykytiedostoa muokattaessa ohjelman on syytä luoda tilapäinen aputiedosto, joka tietenkin ohjelman suorituksen päättyessä on poistettava.
Käyttöesimerkki:
$ java Tekstilaboratorio Ei tiedostoa. 1 lue 4 merkkejä 2 tallenna 5 suurenna 3 lopeta 6 suodata 1 Mikä? Rautatie.txt Tiedosto: Rautatie.txt 1 lue 4 merkkejä 2 tallenna 5 suurenna 3 lopeta 6 suodata 6 Anna suodatinsana! kissa Tiedosto: Rautatie.txt 1 lue 4 merkkejä 2 tallenna 5 suurenna 3 lopeta 6 suodata 3 $
Lisää laboratorioon komento numeroi, joka muokkaa nykytiedostoa siten, että joka rivin alkuun lisätään rivinumero, kaksoispiste ja välilyönti.
Huomaa että nykytiedostoa muokattaessa ohjelman on syytä luoda tilapäinen aputiedosto, joka tietenkin ohjelman suorituksen päättyessä on poistettava.
Käyttöesimerkki:
$ java Tekstilaboratorio Ei tiedostoa. 1 lue 4 merkkejä 7 numeroi 2 tallenna 5 suurenna 3 lopeta 6 suodata 1 Mikä? Rautatie.txt Tiedosto: Rautatie.txt 1 lue 4 merkkejä 7 numeroi 2 tallenna 5 suurenna 3 lopeta 6 suodata 7 Tiedosto: Rautatie.txt 1 lue 4 merkkejä 7 numeroi 2 tallenna 5 suurenna 3 lopeta 6 suodata 3 $
Lisää laboratorioon komento vokaali, joka tutkii ja ilmoittaa nykytiedoston vokaalien, konsonanttien ja erikoismerkkien prosentuaaliset osuudet. Välilyöntejä, sarkaimia, rivin loppuja, ym. "white spacea" ei tässä laskennassa oteta mukaan kokonaismerkkimäärään.
Käyttöesimerkki:
$ java Tekstilaboratorio Ei tiedostoa. 1 lue 4 merkkejä 7 numeroi 2 tallenna 5 suurenna 8 vokaali 3 lopeta 6 suodata 1 Mikä? Teos.txt Tiedosto: Teos.txt 1 lue 4 merkkejä 7 numeroi 2 tallenna 5 suurenna 8 vokaali 3 lopeta 6 suodata 8 54 % vokaaleja 29 % konsonantteja 7 % erikoismerkkejä Tiedosto: Teos.txt 1 lue 4 merkkejä 7 numeroi 2 tallenna 5 suurenna 8 vokaali 3 lopeta 6 suodata 3 $
Kahdessa erilaisesessa kirjallisuudentutkimuskaluston toteutustavassa on paljon yhteistä. Ja copy-paste-ohjelmointi ei ole kovin tyylikästä.
Kehittele jokin tapa, ohjelman rakenne, ohjelman arkkitehtuuri, jolla voit toteuttaa molemmat palvelut jouttumatta uudelleenkirjoittamaan tai kopioimaan samaa ohjelmakoodia sinne tänne.
Hahmottele arkkitehtuurisi myös Javan luokkakaluston avulla ihan konkreettisina luokkina ja muina rakenteina. Varsinaiset algoritmien toteutukset voit tähän luurankoon jättää tekemättä
Tai jos teet ensin tämän tehtävän, 2. ja 4. tehtäväsarjan tekeminen voi olla helppoa... ;-)