*/** * Ohjelmoinnin jatkokurssi syksy 2009 * 6. harjoitusten malliratkaisut */ // Tehtävä 21: kts. http://www.cs.helsinki.fi/u/wikla/Ohjelmointi/Sisalto/5/PoiLuk.html#9 /////////////////////////////////////////////////////////////////////////// // Java-ohjelmointi, Helsingin yliopisto, Tietojenkäsittelytieteen laitos // Harjoitustehtävän 21 esimerkkiratkaisu syksyllä 2009 // Arto Wikla 28.11.2006 // Aki Reijonen 6.12.2009 //------------------------------------------------------------------------- // Ohjelma ohjelma EtsiSanaa etsii merkkijonoa tekstitiedostosta. Ohjelmalle // annetaan tekstitiedoston nimi komentoriviparametrina. Etsittävän merkkijonon // ohjelma kysyy käyttäjältä. Komentoriviparametrin ja tiedoston puuttumisesta // annetaan virheilmoitus. Ohjelma tulostaa kuvaruudulle rivinumeroin ne // tiedoston rivit, joihin sisältyy haettava merkkijono. /////////////////////////////////////////////////////////////////////////// import java.io.*; // Arto Wikla 28.11.2006 import java.util.Scanner; public class EtsiSanoja { private static Scanner lukija = new Scanner(System.in); public static void main(String[] args) { if (args.length != 1 ) { System.out.println("Komentorivillä on annettava tiedosto, josta etsitään!"); return; // >>>>> ohjelma päättyy <<<<<< } // Syöttötiedoston luontimetodi luoSyöttötiedosto(...) (ks. alla!) // käsitteleee itse poikkeukset ja antaa tarvittaessa // virheilmoituksen. Metodi palauttaa null, jos luonti ei onnistu. while (true) { // Luetaan syöttötiedosto joka kerta uudelleen, olisi myös voitu // lukea kerran rivettäin esim. ArrayList -olioon // ja tämän jälkeen hakea sieltä. Scanner tiedosto = luoSyöttötiedosto(args[0]); if (tiedosto==null) return; // >>>>> ohjelma päättyy <<<<<< System.out.println("Mitä merkkijonoa etsitään tiedostosta "+args[0]+"?"); String sana = lukija.nextLine(); // tyhjä rivi lopettaa if (sana.length() == 0) { break; } System.out.println("Etsitään: " + sana); int riviNro = 0; while (tiedosto.hasNextLine()) { String rivi = tiedosto.nextLine(); ++riviNro; if (rivi.indexOf(sana) != -1 ) System.out.println(riviNro +": " + rivi); } tiedosto.close(); } } //------ Apumetodi syöttötiedoston luontiin ------------------------------ private static Scanner luoSyöttötiedosto(String nimi) { try { // Annetaan Scannerille käytettävä merkistö, sillä // muutoin käytetään järjestelmän oletusmerkistöä ja se ei välttämättä // vastaa syötetiedostossa käytettävää. // Esimerkkitiedostot kuten Rautatie.txt ovat ISO-8859-1 -muodossa // joten käytetään sitä. Tämä rivi pitäisi vaihtaa, mikäli halutaan lukea // eri muodossa olevia tekstitiedostoja (esim. UTF-8). return new Scanner(new File(nimi), "ISO-8859-1"); } catch (FileNotFoundException e) { System.out.println("Tiedostoa " + nimi + " ei löydy!"); return null; } } } /////////////////////////////////////////////////////////////////////////// // Java-ohjelmointi, Helsingin yliopisto, Tietojenkäsittelytieteen laitos // Harjoitustehtävän 23a esimerkkiratkaisu syksyllä 2009 // Arto Wikla 28.11.2006 // Aki Reijonen 6.12.2009 //------------------------------------------------------------------------- // // Ohjelma JaaKahdeksi jakaa tekstitiedoston kahdeksi siten että // parilliset // rivit menevät yhteen tiedostoon, parilliset toiseen. // Ohjelma saa tiedostonimet komentoriviparametreina. /////////////////////////////////////////////////////////////////////////// import java.io.*; // Arto Wikla 28.11.2006 import java.util.Scanner; public class JaaKahdeksi { public static void main(String[] args) { if (args.length != 3 ) { selitäOhjelmanOikeaKäyttö("Tarvitaan kolme parametria!"); return; // >>>>> ohjelma päättyy <<<<<< } // Tiedostojen luontimetodit käsittelevät poikkeukset ja antavat // itse virheilmoitukset. Palauttavat null, jos luonti ei onnistu. // Onko syöttötiedostoa? Scanner jaettava = luoSyöttötiedosto(args[0]); if (jaettava==null) return; // >>>>> ohjelma päättyy <<<<<< // Onnistuuko tulostustiedostojen luonti? PrintWriter parittomat = luoTulostiedosto (args[1]); PrintWriter parilliset = luoTulostiedosto (args[2]); if (parittomat==null || parilliset==null) return; // >>>>> ohjelma päättyy <<<<<< while (jaettava.hasNextLine()) { parittomat.println(jaettava.nextLine()); if (jaettava.hasNextLine()) parilliset.println(jaettava.nextLine()); } jaettava.close(); parittomat.close(); parilliset.close(); } //---------------------------------------------------------------------------- private static Scanner luoSyöttötiedosto(String nimi) { try { return new Scanner(new File(nimi), "ISO-8859-1"); } catch (FileNotFoundException e) { selitäOhjelmanOikeaKäyttö("Tiedostoa " + nimi + " ei löydy!"); return null; } } //----------------------------------------------------------------------------- private static PrintWriter luoTulostiedosto(String nimi) { File tulTd = new File(nimi); if (tulTd.exists()) { selitäOhjelmanOikeaKäyttö("Tiedosto " + nimi + " on jo olemassa!"); return null; // >>> metodi voi päättyä jo tähän <<< } try { // käytetään samaa merkistöä kaikkialla return new PrintWriter(tulTd, "ISO-8859-1"); } catch(UnsupportedEncodingException e) { System.out.println("PrintWriter ei tue haluttua merkistöä!"); return null; } catch(FileNotFoundException e) { // !!!!!! selitäOhjelmanOikeaKäyttö("Tiedoston " + nimi + "luonnissa on jokin ongelma!"); return null; } } //---------------------------------------------------------------------------- private static void selitäOhjelmanOikeaKäyttö(String ilmoitus) { System.out.println( "\n>>>> " + ilmoitus +" <<<<<\n" + "Ohjelma käynnistetään komennolla:\n" + " java JaaKahdeksi jaettava.txt parittomat.txt parilliset.txt \n" + "Syöttötiedoston on oltava olemassa. Tulostustiedostot eivät saa olla olemassa." ); } } //Tehtävä 23b: //=========== /////////////////////////////////////////////////////////////////////////// // Java-ohjelmointi, Helsingin yliopisto, Tietojenkäsittelytieteen laitos // Harjoitustehtävän 23b esimerkkiratkaisu syksyllä 2009 // Arto Wikla 28.11.2006 // Aki Reijonen 6.12.2009 //------------------------------------------------------------------------- // Ohjelma YhdistaKahdesta yhdistää kaksi tekstitiedostoa yhdeksi siten, // että joka toinen rivi otetaan toisesta, joka toinen toisesta. Jos jompi // kumpi syöttötiedosto loppuu ennen toista, pidemmän rivit kopioidaan // sellaisenaan yhdistettyyn tiedostoon. // Ohjelma saa tiedostonimet komentoriviparametreina. // /////////////////////////////////////////////////////////////////////////// import java.io.*; // Arto Wikla 28.11.2006 import java.util.Scanner; public class YhdistaKahdesta { public static void main(String[] args) { if (args.length != 3 ) { selitäOhjelmanOikeaKäyttö("Tarvitaan kolme parametria!"); return; // >>>>> ohjelma päättyy <<<<<< } // Tiedostojen luontimetodit käsittelevät poikkeukset ja antavat // itse virheilmoitukset. Palauttavat null, jos luonti ei onnistu. // Onko syöttötiedostoja? Scanner eka = luoSyöttötiedosto(args[0]); Scanner toka = luoSyöttötiedosto(args[1]); if (eka==null || toka==null) return; // >>>>> ohjelma päättyy <<<<<< // Onnistuuko tulostustiedoston luonti? PrintWriter yhdistetty = luoTulostiedosto (args[2]); if (yhdistetty==null) return; // >>>>> ohjelma päättyy <<<<<< while (eka.hasNextLine() || toka.hasNextLine()) { if (eka.hasNextLine()) yhdistetty.println(eka.nextLine()); if (toka.hasNextLine()) yhdistetty.println(toka.nextLine()); } eka.close(); toka.close(); yhdistetty.close(); } //---------------------------------------------------------------------------- private static Scanner luoSyöttötiedosto(String nimi) { try { return new Scanner(new File(nimi), "ISO-8859-1"); } catch (FileNotFoundException e) { selitäOhjelmanOikeaKäyttö("Tiedostoa " + nimi + " ei löydy!"); return null; } } //----------------------------------------------------------------------------- private static PrintWriter luoTulostiedosto(String nimi) { File tulTd = new File(nimi); if (tulTd.exists()) { selitäOhjelmanOikeaKäyttö("Tiedosto " + nimi + " on jo olemassa!"); return null; // >>> metodi voi päättyä jo tähän <<< } try { // käytetään samaa merkistöä kaikkialla return new PrintWriter(tulTd, "ISO-8859-1"); } catch(UnsupportedEncodingException e) { System.out.println("PrintWriter ei tue haluttua merkistöä!"); return null; } catch(FileNotFoundException e) { // !!!!!! selitäOhjelmanOikeaKäyttö("Tiedoston " + nimi + "luonnissa on jokin ongelma!"); return null; } } //---------------------------------------------------------------------------- private static void selitäOhjelmanOikeaKäyttö(String ilmoitus) { System.out.println( "\n>>>> " + ilmoitus +" <<<<<\n" + "Ohjelma käynnistetään komennolla:\n" + " java YhdistaKahdesta eka.txt toka.txt yhdistetty.txt \n" + "Syöttötiedostojen on oltava olemassa. Tulostustiedostoa ei saa olla olemassa." ); } } //////////////////////////////////////////////////////////////////////// import java.io.*; // Arto Wikla 29.11.2005 /////////////////////////////////////////////////////////////////////////// // Java-ohjelmointi, Helsingin yliopisto, Tietojenkäsittelytieteen laitos // Harjoitustehtävän 24 esimerkkiratkaisu syksyllä 2009 // Arto Wikla 29.11.2005 // Aki Reijonen 6.12.2009 //------------------------------------------------------------------------- // Luokka SananSeuraajat määrittelee tietorakenteen, johon talletetaan // pareja (sana, sanaluettelo). Konstruktori ja aksessorit: // // public SananSeuraajat() konstruoi tyhjän SananSeuraajat-olion. // // public void lisääSanalleSeuraaja(String sana, String seuraaja) // lisää sanalle seuraajan. Jos sanaa (ensimmäinen parametri) ei jo ole // tietorakenteessa, se lisätään ja sen ensimmäiseksi seuraajaksi tulee // parametrina annettu seuraaja. Jos sana jo löytyi, sen seuraajaksi // lisätään seuraaja, ellei jälkimmäinen parametri jo kuulu sanan // seuraajien listaan. // // public ArrayList mitkäSeuraavatSanaa(String sana) // palauttaa arvonaan String-vektorin joka sisältää sanan seuraajat. // Ellei sanaa löydy, metodi palauttaa arvon null. // // public String toString() // palauttaa arvonaan koko tietorakenteen merkkijonona. metodi käyttää // hyväkseen toteutusrakenteen (Hashtable>()) // omaa toString()-metodia. Se on tarkoitettu vain testauksen avuksi, // ei "tuotantokäyttöön". /////////////////////////////////////////////////////////////////////////// import java.util.*; // Arto Wikla 29.11.2005 class SananSeuraajat { private HashMap> seuraajat; public SananSeuraajat() { seuraajat = new HashMap>(); } public void lisääSanalleSeuraaja(String sana, String seuraaja) { if (!seuraajat.containsKey(sana)) { // uusi avain! ArrayList seuraajia = new ArrayList(); seuraajia.add(seuraaja); seuraajat.put(sana, seuraajia); } else { // vanha avain ArrayList seuraajia = seuraajat.get(sana); if (!seuraajia.contains(seuraaja)) // Lisätään seuraajia.add((seuraaja)); // Sillä sipuli kiitos } // viitesemantiikan! } public ArrayList mitkäSeuraavatSanaa(String sana) { return seuraajat.get(sana); // null jos sanaa ei löydy! } public String toString() {return seuraajat.toString();} } import java.io.*; import java.util.Scanner; /////////////////////////////////////////////////////////////////////////// // Java-ohjelmointi, Helsingin yliopisto, Tietojenkäsittelytieteen laitos // Harjoitustehtävän 28 esimerkkiratkaisu syksyllä 2009 // Arto Wikla 29.11.2005 // Aki Reijonen 6.12.2009 //------------------------------------------------------------------------- // Ohjelma TutkiSanojenSeuraajat lukee tekstitiedoston ja selvittää // tiedoston kaikkien sanojen välittömät seuraajasanat. Sanoiksi" lasketaan // kaikki Scanner-luokan next()-metodin antamat String-oliot. Ohjelma // tarjoaa palvelun sanojen seuraajien kyeselemiseen. /////////////////////////////////////////////////////////////////////////// public class TutkiSanojenSeuraajat { private static Scanner lukija = new Scanner(System.in); public static void main(String[] args) throws FileNotFoundException { // --- Kysytään syöttötiedosto System.out.println("Minkä tiedoston sanojen seuraajat haluat tutkia?"); String tiedostonNimi=lukija.nextLine(); File tiedosto_olio = new File(tiedostonNimi); if (!tiedosto_olio.exists()) { System.out.println("Tiedostoa "+ tiedostonNimi +" ei löydy!"); return; // keskeytetään kaikki! } Scanner syöttötiedosto = new Scanner(tiedosto_olio, "ISO-8859-1"); // --- Kerätään sanojen seuraajat: SananSeuraajat assosiaatiot = new SananSeuraajat(); String edellinen = ""; // Scanner.next() lukee oletuksena välilyönnillä erotettuja arvoja // Näin sanat saadaan kätevästi talteen if (syöttötiedosto.hasNext()) //ensimmäinen sana ei ole minkään sanan seuraaja edellinen = syöttötiedosto.next(); while (syöttötiedosto.hasNext()) { String sana = syöttötiedosto.next(); // System.out.println(sana); assosiaatiot.lisääSanalleSeuraaja(edellinen, sana); edellinen = sana; } syöttötiedosto.close(); // Tulostetaan koko rakenne (testipiirre): System.out.println(assosiaatiot); // --- Tarjotaan kyselypalvelu: while (true) { // lopetetaan tyhjään sanaan!! System.out.println("Minkä sanan seuraajat haluat tietää? Tyhjä lopettaa."); String sana = lukija.nextLine(); if (sana.length()==0) break; // >>>>>>>>>>> lopetuskohta <<<<<<<<<<<<< System.out.println(assosiaatiot.mitkäSeuraavatSanaa(sana)); } } }