/** * Ohjelmoinnin jatkokurssi, syksy 2009, 4. harjoitukset, tehtävä 11 * * Kirjastoluokka muotoiltuun tulostukseen. * * @author Sami Nikander * @author Janne Salo * @author Taru Itäpelto */ public final class Muotoilija { // final: kirjastoluokkaa ei ole tarkoitus periyttää private Muotoilija() {} // private: kirjastoluokasta ei ole tarkoitus tehdä ilmentymiä /** * Tulostaa Stringin vasemmalle tasattuna. Mahdollinen * loppuosa kenttää täytetään välilyönneillä. Tämä on perusmetodi, jota * hyödynnetään muissa vasemmalle tasaavissa metodeissa. */ public static void tulVas(String arvo, int leveys) { // varsinainen teksti System.out.print(arvo); // loppukentän täyttö for (int i = arvo.length(); i < leveys; i++) System.out.print(' '); } /** * Tulostaa Stringin oikealle tasattuna. Mahdollinen alkuosa kenttää * täytetään välilyönneillä. Tämä on perusmetodi, jota * hyödynnetään muissa oikealle tasaavissa metodeissa. */ public static void tulOik(String arvo, int leveys) { // alkukentän täyttö for (int i = 0; i < (leveys - arvo.length()); i++) System.out.print(' '); // varsinainen teksti System.out.print(arvo); } //------------- TulVas, kuormitetut metodit ------------ public static void tulVas(int arvo, int leveys) { tulVas(arvo + "", leveys); // int Stringiksi, tuttu temppu! } public static void tulVas(char arvo, int leveys) { tulVas(arvo + "", leveys); } public static void tulVas(boolean arvo, int leveys) { tulVas(arvo + "", leveys); } //------------- TulOik, kuormitetut metodit ------------ public static void tulOik(int arvo, int leveys) { tulOik(arvo + "", leveys); } public static void tulOik(char arvo, int leveys) { tulOik(arvo + "", leveys); } public static void tulOik(boolean arvo, int leveys) { tulOik(arvo + "", leveys); } public static void main(String[] args) { System.out.println("Ohjelma demonstroi yhtä tapaa käyttää luokan tulostusmetodeja. \n" + "Kuten esimerkistä näkyy, taulukon sarakkeet sotkeutuvat, \n" + "jos kenttiin tulostetaan liian pitkiä arvoja, mutta arvot\n" + "tulostuvat kuitenkin oikein.\n\n"); String[] otsikot = { "Kuukausi", "Ruoka", "Vaatteet", "Harrastukset", "OV", "Lumisadetta", "Lempimerkki" }; int[] leveys = { 12, 6, 9, 14, 3, 13, 12 }; String[] kuukausi = { "Tammi", "Helmi", "Maalis", "Huhti", "Touko", "Kesä", "Heinä", "Elo", "Syys", "Loka", "Marras", "Joulu" }; int[] ruoka = { 290, 300, 280234324, 320, 330, 300, 299, 322, 330, 274, 230, 350 }; int[] vaatteet = { 2, 10, 0, 0, 0, 18, 5, 0, 0, 12, 0, 34 }; int[] harrastukset = { 25, 5, 120, 0, 34, 90, 23, 120, 4, 95, 23, 40 }; int[] opintoviikot = { 3, 4, 3, 3, 3, 3423453, 3, 4, 3, 2, 3, 3 }; boolean[] lumikuuroja = { true, true, true, false, false, true, false, false, false, false, false, false }; char[] lempimerkki = { '%', 'h', '.', '-', '*', '!', '@', 'g', '5', '?', '=', 'Ä' }; System.out.println("Oikealle tasattuna:\n"); //Tulostetaan sarakeotsikot for (int i = 0; i < otsikot.length; ++i) { Muotoilija.tulOik(otsikot[i], leveys[i]); System.out.print('|'); } System.out.println();// vaihdetaan riviä //Tulostetaan viiva otsikoiden alle for (int i = 0; i < leveys.length; ++i) { for (int j = 0; j < leveys[i] + 1; ++j) { System.out.print("-"); } } System.out.println();// vaihdetaan riviä // Tulostetaan loput taulukosta for (int i = 0; i < kuukausi.length; ++i) { Muotoilija.tulOik(kuukausi[i] + "kuu", leveys[0]); System.out.print('|'); Muotoilija.tulOik(ruoka[i], leveys[1]); System.out.print('|'); Muotoilija.tulOik(vaatteet[i], leveys[2]); System.out.print('|'); Muotoilija.tulOik(harrastukset[i], leveys[3]); System.out.print('|'); Muotoilija.tulOik(opintoviikot[i], leveys[4]); System.out.print('|'); Muotoilija.tulOik(lumikuuroja[i], leveys[5]); System.out.print('|'); Muotoilija.tulOik(lempimerkki[i], leveys[6]); System.out.print('|'); System.out.println();// vaihdetaan riviä } System.out.println("\n\nVasemmalle tasattuna:\n"); //Tulostetaan sarakeotsikot for (int i = 0; i < otsikot.length; ++i) { Muotoilija.tulVas(otsikot[i], leveys[i]); System.out.print('|'); } System.out.println();// vaihdetaan riviä //Tulostetaan viiva otsikoiden alle for (int i = 0; i < leveys.length; ++i) { for (int j = 0; j < leveys[i] + 1; ++j) { System.out.print("-"); } } System.out.println();// vaihdetaan riviä // Tulostetaan loput taulukosta for (int i = 0; i < kuukausi.length; ++i) { Muotoilija.tulVas(kuukausi[i] + "kuu", leveys[0]); System.out.print('|'); Muotoilija.tulVas(ruoka[i], leveys[1]); System.out.print('|'); Muotoilija.tulVas(vaatteet[i], leveys[2]); System.out.print('|'); Muotoilija.tulVas(harrastukset[i], leveys[3]); System.out.print('|'); Muotoilija.tulVas(opintoviikot[i], leveys[4]); System.out.print('|'); Muotoilija.tulVas(lumikuuroja[i], leveys[5]); System.out.print('|'); Muotoilija.tulVas(lempimerkki[i], leveys[6]); System.out.print('|'); System.out.println();// vaihdetaan riviä } } } /* HUOM: Tämä on vapaaehtoista lisämateriaalia, joka ei kuulu kurssin sisältöön! Lue tämä vain jos haluat perehtyä Javan autoboxing-piirteeseen tarkemmin! Ohessa vaihtoehtoinen ratkaisu, joka käyttää autoboxing-piirrettä. Siitä kerrotaan hieman verkkomateriaalin luvussa 5.3. kohdassa "Vähän geneerisyydestä, hyvin vähän...". Autoboxingin käyttö lyhentää tässä koodia, mutta tekee toimintalogiikasta vaikeaselkoisemman. Vai tekeekö? Kaikki ylläolevat metodit voisi korvata seuraavilla kahdella Object-tyyppisen parametrin saavalla metodilla. Esimerkiksi jos metodia tulVas tai tulOik kutsutaan int-arvolla, Java "käärii" arvon automaattisesti Integer-olioon. Integer on alkeistyypin int luokkavastine, josta luodut oliot edustavat yksittäisiä int-arvoja. Koska metodien tulVas ja tulOik arvoparametri on määritelty Object-tyyppiseksi, voi metodeita kutsua millä tahansa olioarvoilla, kuten Integer-arvoilla. Metodin sisällä oleva toString -kutsu muuntaa nämä olioarvot merkkijonoiksi. Nämä metodit osaavat tulostaa muotoillusti kaikki Javan alkeistyypit (myös short, long, double, float...) ja lisäksi kaikki sellaiset tyypit, joiden toString-metodi ei tuota rivinvaihtoja. public static void tulVas(Object arvo, int leveys) { String s = arvo.toString(); System.out.print(s); for (int i = s.length(); i < leveys; i++) System.out.print(' '); } public static void tulOik(Object arvo, int leveys) { String s = arvo.toString(); for (int i = 0; i < (leveys - s.length()); i++) System.out.print(' '); System.out.print(s); } */ } /* * * Teht. 12 & 13 & 15 * */ public class Kokonaislukujoukko { public final static int KAPASITEETTI=10, // Vertaa tehtävään 6 & 7! OLETUSKASVATUS =10; // Kerralla otettavan lisätilan määrä. private int[] taulukko; // Joukon luvut säilytetään taulukon alkupäässä. private int kasvatuskoko; // (vrt. edell. teht. 6 & 7) private int alkioiden_määrä; // Tyhjässä joukossa alkioiden_määrä on nolla. public Kokonaislukujoukko() { taulukko = new int[KAPASITEETTI]; kasvatuskoko = OLETUSKASVATUS; alkioiden_määrä = 0; } public Kokonaislukujoukko(int kapasiteetti) { if (kapasiteetti > 0) taulukko = new int[kapasiteetti]; else // virhetilanteessa käytetään oletuskokoa taulukko = new int[KAPASITEETTI]; kasvatuskoko = OLETUSKASVATUS; alkioiden_määrä = 0; } public Kokonaislukujoukko(int kapasiteetti, int kasvatuskoko) { if (kasvatuskoko > 0) this.kasvatuskoko = kasvatuskoko; else // virhetilanteessa käytetään oletuskokoa this.kasvatuskoko = OLETUSKASVATUS; if (kapasiteetti > 0) taulukko = new int[kapasiteetti]; else // virhetilanteessa käytetään oletuskokoa taulukko = new int[KAPASITEETTI]; alkioiden_määrä = 0; } // ... public boolean lisää(int luku) { if (this.kuuluu(luku)) // on jo, ei lisätä! return false; if (alkioiden_määrä == taulukko.length) // pitää kasvattaa taulukko = teeSuurempiTaulukko(taulukko); taulukko[alkioiden_määrä] = luku; ++alkioiden_määrä; return true; } public boolean poista(int luku) { int poistettavanIndeksi = this.etsi(luku); if (poistettavanIndeksi == -1) // ei ole, ei poisteta! return false; // poistetaan tiivistämällä taulukon loppuosaa for (int i=poistettavanIndeksi; i "); while(lukija.hasNextInt()){ int luku = lukija.nextInt(); joukko.lisää(luku); } if(joukko.koko()>0){ lukija.nextLine(); //tyhjennetään puskuri!!! } //luetaan mahdollinen lopetuskomento String rivi = lukija.nextLine(); komento = 'ö'; //jos ensimmäinen merkki on virheellinen if(rivi.length()==1){ komento = rivi.charAt(0); } if(komento != 'l') System.out.println("Virheellinen komento!"); }while(komento != 'l'); return joukko; } public static void main(String[] args){ System.out.println("Tervetuloa käyttämään Kokonaislukujoukon joukko-operaatiota."); //luetaan joukot a ja b Kokonaislukujoukko a = lueJoukko("a"); Kokonaislukujoukko b = lueJoukko("b"); //Tulostetaan käyttäjälle luetut joukot System.out.println("Luetut joukot:"); System.out.println("Joukko a:"+a.toString()); System.out.println("Joukko b:"+b.toString()); //ja luodaan joukot c, d ja e, sekä tulostetaan ne käyttäjälle Kokonaislukujoukko c, d, e; c = a.yhdiste(b); System.out.println("Joukkojen a ja b yhdiste (joukko c):"+c.toString()); d = a.leikkaus(b); System.out.println("Joukkojen a ja b leikkaus (joukko d):"+d.toString()); e = a.erotus(b); System.out.println("Joukkojen a ja b erotus (joukko e):"+e.toString()); a = d.yhdiste(b.leikkaus(c)); System.out.println("Joukkojen a ja b leikkauksen sekä joukkojen b ja c leikkauksen yhdiste:"+a.toString()); } } /* * * * Teht. 14 * */ /** * Joukko-operaatioita tarjoava kirjastoluokka * @author Taru Itäpelto * */ // final määre: ei sallita perintää public final class JoukkoOperaatio { private JoukkoOperaatio(){} //ilmentymien luonnin esto /** * Palauttaa arvonaan joukon, joka sisältää kaikki a:n ja b:n alkiot */ public static Kokonaislukujoukko yhdiste(Kokonaislukujoukko a, Kokonaislukujoukko b){ //käytetään Kokonaislukujoukko-luokan toIntArray -metodia ja haetaan molempien //joukkojen alkiot kokonaislukutaulukkoina int[] alkiotA = a.toIntArray(); int[] alkiotB = b.toIntArray(); //tulosjoukko Kokonaislukujoukko yhdisteJoukko = new Kokonaislukujoukko(); //lisätään joukon a alkiot for(int alkio: alkiotA){ yhdisteJoukko.lisää(alkio); } for(int alkio: alkiotB){ yhdisteJoukko.lisää(alkio); } return yhdisteJoukko; } /** * Palauttaa arvonaan joukon, joka sisältää täsmälleen kaikki alkiot, jotka * kuuluvat sekä joukkoon a että joukkoon b */ public static Kokonaislukujoukko leikkaus(Kokonaislukujoukko a, Kokonaislukujoukko b){ //käytetään Kokonaislukujoukko -luokan toIntArray -metodia ja haetaan //toisen joukon alkiot kokonaislukutaulukkona // - helpottaa alkioiden läpikäyntiä int[] alkiotA = a.toIntArray(); //tulosjoukko Kokonaislukujoukko leikkausJoukko = new Kokonaislukujoukko(); //käydään ensimmäisen joukon alkiot läpi for(int alkio: alkiotA){ //jos alkio kuuuluu myös joukkoon B, lisätään se tulosjoukkoon if(b.kuuluu(alkio)){ leikkausJoukko.lisää(alkio); } } return leikkausJoukko; } /** * Palauttaa arvonaan joukon, joka sisältää kaikki a:n alkiot, jotka eivät kuulu joukkoon b */ public static Kokonaislukujoukko erotus(Kokonaislukujoukko a, Kokonaislukujoukko b){ //alkiot kokonaislukutaulukkona int[] alkiotA = a.toIntArray(); //tulosjoukko Kokonaislukujoukko erotusJoukko = new Kokonaislukujoukko(); //käydään kaikki alkiot läpi for (int alkio: alkiotA){ //jos alkio ei kuulu joukkoon B, lisätään se tulosjoukkoon if(!b.kuuluu(alkio)){ erotusJoukko.lisää(alkio); } } return erotusJoukko; } } /* * * Testiluokka * */ import java.util.Scanner; public class JoukkoOperaatioKäyttis { private static Scanner lukija = new Scanner(System.in); /* * Metodi joukon alkioiden kyselemiseen. Mukavuussyistä mukana * nimiparametri. Oikeasti sitä ei tarvita mihinkään muuhun kuin * tulostukseen =) */ private static Kokonaislukujoukko lueJoukko(String nimi){ Kokonaislukujoukko joukko = new Kokonaislukujoukko(); System.out.println("Anna joukon "+nimi+" alkiot ('l' lopettaa):"); char komento; do{ System.out.println("alkio> "); while(lukija.hasNextInt()){ int alkio = lukija.nextInt(); joukko.lisää(alkio); } if(joukko.koko()>0){ lukija.nextLine(); //tyhjennetään puskuri!!! } //luetaan mahdollinen lopetuskomento String rivi = lukija.nextLine(); komento = 'ö'; //jos ensimmäinen merkki on virheellinen if(rivi.length()==1){ komento = rivi.charAt(0); } if(komento != 'l') System.out.println("Virheellinen komento!"); }while(komento != 'l'); return joukko; } public static void main(String[] args){ System.out.println("Tervetuloa käyttämään joukko-operaatiota."); //luetaan joukot a ja b Kokonaislukujoukko a = lueJoukko("a"); Kokonaislukujoukko b = lueJoukko("b"); //Tulostetaan käyttäjälle luetut joukot System.out.println("Luetut joukot:"); System.out.println("Joukko a:"+a.toString()); System.out.println("Joukko b:"+b.toString()); //ja luodaan joukot c, d ja e, sekä tulostetaan ne käyttäjälle Kokonaislukujoukko c, d, e; c = JoukkoOperaatio.yhdiste(a, b); System.out.println("Joukkojen a ja b yhdiste (joukko c):"+c.toString()); d = JoukkoOperaatio.leikkaus(a, b); System.out.println("Joukkojen a ja b leikkaus (joukko d):"+d.toString()); e = JoukkoOperaatio.erotus(a, b); System.out.println("Joukkojen a ja b erotus (joukko e):"+e.toString()); a = JoukkoOperaatio.yhdiste(d, JoukkoOperaatio.leikkaus(b, c)); System.out.println("Joukkojen a ja b leikkauksen sekä joukkojen b ja c leikkauksen yhdiste:"+a.toString()); } }