581326-3 Java-ohjelmointi, koe 25.6.2003/AW (Avoin yliopisto) Tehtävä 3 Arvostelu: Heikki Lindholm Yksi mahdollinen ratkaisuhahmotelma: --------------------------------------------------------------------------------------------------- public class PoistaTyhjatRivit { public static void main(String[] args) { // tarkistetaan komentoriviparametrien kelvollisuus if (args.length != 2) { System.out.println("Epäkelvot komentoriviparametrit!"); System.out.println("Käyttö: PoistaTyhjatRivit syottotied tulostied"); System.exit(0); } // avataan syöttötiedosto // SyottoTiedosto:n luonti saattaa aiheuttaa poikkeuksen try { SyottoTiedosto syote = new SyottoTiedosto(args[0]); } catch (Exception e) { System.out.println("Syöttötiedoston avaaminen epäonnistui."); System.out.println("Virheen kuvaus:\n"+e.toString()); System.exit(0); } // avataan tulostiedosto // TulosTiedosto hoitaa itse virhetilanteet TulosTiedosto tulos = new TulosTiedosto(args[1]); String rivi; // luetaan ja käsitellään syöttötiedosto rivi kerrallaan // SyottoTiedosto.readLine saattaa aiheuttaa poikkeuksen // huom! yleensä try-catch lohko haluttaisiin tehdä mahd. // pieneksi, jotta olisi selvää, mikä siellä saattaa aiheuttaa // poikkeuksen - ettei poikkeuksia tule napattua odottamattomista // lähteistä. Tässä isohko try-catch lohko kuitenkin vielä menettelee try { while ((rivi = syote.readLine()) != null) { // käydään rivi merkki merkiltä alusta loppuun // läpi ja tutkitaan löytyykö muita kuin välilöyntejä boolean tyhja = true; for (int i = 0; i < rivi.length; i++) { // jos löytyy yksikin ei-välilöynti, rivi ei ole tyhjä if (rivi.charAt(i) != ' ') { tyhja = false; break; // poistutaan silmukasta samantien } } // jos rivi ei ole tyhja, kirjoitetaan se tulostiedostoon // (oletetaan, että kirjoitaRivi lisää rivin päätemerki(t)) if (!tyhja) tulos.kirjoitaRivi(rivi); } } catch (Exception e) { System.out.println("Virhe luettaessa syöttötiedostoa."); System.out.println("Virheen kuvaus:\n"+e.toString()); System.exit(0); } System.out.println("Valmista tuli."); } } --------------------------------------------------------------------------------------------------- Vaihtoehtoisia tapoja tutkia, onko rivi tyhjä: - muutetaan rivi merkkitaulukoksi ja käydään se läpi charAt:n käytön sijaan - String.trim() poistaa rivin alusta ja lopusta tyhjät merkit. Jos rivi.trim().length == 0, niin rivi on tyhja - lasketaan välilyönnit ja tutkitaan, onko niitä rivin pituuden verran, esim.: int valeja = 0; for (int i = 0; i < rivi.length; i++) { if (rivi.charAt(i) == ' ') valeja++; } if (valeja == rivi.length) riviOnTyhja = true; * ratkaisuhahmotelman tapa lienee näistä tehokkain, trim:n käyttö lyhyin ja välilyöntien laskenta tehottomin Arvostelu: tehtävästä sai enimmillään 17 pistettä - Poikkeukset 6p * -6p, jos poikkeuksia ei käsitelty ollenkaan * -3p, jos vain toinen poikkeuksista huomioitu * -3p, jos poikkeukset "käsitelty" siten, että main heittää kaikki poikkeukset - Komentoriviparametrit 3p * -1p, jos parametrien määrää ei tarkistettu (ts. ohjelma sellainen, että väärä käyttö aiheuttaisi ArrayIndexOutOfBounds poikkeuksen) * -3p, jos ei ollenkaan käytetty parametreja - Pääsilmukan toteutus 8p * -6p, jos ei tarkistettu yhtään mitään (ei rivi.length == 0 eikä välilyöntejä) * -4p, jos ei tarkistettu koostuuko rivi pelkistä välilyönneistä (tai tyhjämerkeistä) * -2p, pienemmistä virheistä (esim. ratk. näyttää melkein oikealta, mutta ei ihan toimisi) * -1p, vielä pienemmät virheet (esim. tulostiedostoon tulostetaan muokattuja rivejä (trim)) Kommentit vastauksista: - yllättävän hyvin osattu yleisesti ottaen. Useimmat tiesivät mitä komentoriviparametrit tarkoittavat, muistivat ottaa poikkeukset kiinni ja osasivat tehdä järkevän tarkistuksen rivin tyhjäksi toteamiseksi - yleisimpiä virheitä olivat * komentoriviparametrien käyttö ilman niiden määrän tarkistusta * toisen (yleensä lueRivi()) aiheutuvan poikkeuksen käsittelyn unohtaminen