Ukeoppgaver 5:  21. - 25. sep (INF1000 - H?st 2009)

Filer (kap. 3.5 - 3.7; 3.10 - 3.11); og tekster (kap. 6.1 - 6.9)

M?l
F? ?velse i innlesing og utskrift til fil, og bruk av tekststrenger.

Oppgaver til teoritimen

  1. Innlesing og utskrift til fil:  (eksempel side 50 i l?reboka)
    (a) Ta utgangspunkt i f?lgende program, fra side 50 i l?reboka, som skriver fire typer verdier til skjerm (tegn, linje, heltall, og desimaltall), og endre programmet slik at utskriften g?r til en fil i stedet.  Kall utfilen "minfil.txt".
    import easyIO.*;
    
    class Utskrift {
        public static void main(String[] args) {
    	Out skjerm = new Out();
    	skjerm.outln('A');
    	skjerm.outln("Canis familiaris betyr hund");
    	skjerm.outln(15);
    	skjerm.outln(3.1415, 2); // Bruk to desimaler
        }
    }
    
    Hint: Utskrift til fil vha. easyIO programmeres p? samme m?te som utskrift til skjerm, bare at man i tillegg angir filnavnet ? f.eks. new Out("minfil.txt"), ? og lukker filen til slutt (utfil.close()).  Navnet p? forbindelsen skjerm b?r ogs? endres for ? gj?re det tydelig at man skriver til en utfil.

    (b) Utvid programmet slik at det ogs? leser innholdet i filen som ble opprettet i del (a), lagrer det i fire passende variabler (den f?rste skal v?re av typen char, osv.), og skriver til slutt verdiene i variablene ut p? skjerm.  Hint: Innlesing fra fil programmeres som innlesing fra tastatur, men man m? i tillegg angi filnanvet ? f.eks. new In("minfil.txt").


  2. Lese/skrive en fil tegn for tegn:  (kap. 3: side 54, og oppg. 7 side 71)
    (a) Lag et program som leser inn en fil og kopierer innholdet over til en annen fil.  Filen skal leses inn et tegn av gangen vha. inChar().  Du kan ta utgangspunkt i programmet vist under, fra side 54 i l?reboka, som leser en fil et tegn av gangen, men skriver innholdet i filen ut p? skjermen (i stedet for til en annen, nyopprettet fil).  Endre klassenavnet til Kopi, og utvid programmet slik at det ber bruker taste inn filnavnene for de to filene (original og kopi).
    import easyIO.*;
    
    class Tegnleser {
        public static void main(String[] args) {
    	In innfil = new In("minfil.txt");
    	int antall = 0;
    
    	while (!innfil.endOfFile()) {
    	    char tegn = innfil.inChar();
    	    System.out.print(tegn);
    	    antall++;
    	}
    	System.out.println("Antall tegn: " + antall);
        }
    }
    

    (b) Ta utgangspunkt i programmet vist ovenfor, og endre det slik at det skriver ut tegnene fra den innleste filen til skjerm, men med alle sm? bokstaver konvertert til store bokstaver.  F?lgende setninger viser hvordan man kan konvertere innholdet i en char-variabel c til store eller sm? bokstaver:
    char c = ’x’;
    char c2 = Character.toUpperCase(c);
    char c3 = Character.toLowerCase(c);
    

    (c) N?r man skriver artikler kan det v?re grenser for hvor mange ord de kan inneholde.  Lag et program som teller antall ord i en fil.  Filnavnet kan du be bruker taste inn n?r programmet starter.  Lag deretter en annen utgave av programmet som tar filnavnet fra f?rste kommandolinjeargument args[0].  "Kommandolinjeargumenter" er evt. tilleggs-ord som bruker angir i selve java-kommandolinjen n?r hun kj?rer programmet.  For eksempel, hvis bruker starter programmet med f?lgende kommando:
    > java AntallOrd fil.txt xx
    
    ...s? putter Java de to siste tilleggs-ord i arrayen String args[] (som vi har sett ?verst i alle programmene v?re til n? uten ? bruke det).  I dette tilfellet vil Java s?rge for at args[0] f?r verdien "fil.txt" n?r programmet starter, og args[1] f?r verdien "xx".


  3. Lese/skrive en fil linje for linje:  (eksempel side 55 i l?reboka)
    (a) Studér f?lgende program, fra side 55 i l?reboka, som leser en fil en linje av gangen, og skriver den ut p? skjermen med linjenummer foran i hver linje.  Endre programmet slik at det i stedet for ? skrive ut alle linjene bare skriver ut en melding til slutt om hvor mange linjer og hvor mange tegn filen inneholder.  For ? telle antall tegn kan du bruke en variabel som summerer verdiene av linje.length()
    import easyIO.*;
    
    class Linjeleser {
        public static void main(String[] args) {
    	In innfil = new In("minfil.txt");
    	int linjenummer = 0;
    
    	while (!innfil.endOfFile()) {
    	    String linje = innfil.readLine();
    	    linjenummer++;
    	    System.out.println(linjenummer + " " + linje);
    	}
        }
    }
    

    (b) Ta utgangspunkt i programmet vist ovenfor, og endre det slik at det skriver ut linjene p? skjerm, men med alle sm? bokstaver konvertert til store bokstaver.  F?lgende setninger viser hvordan man kan konvertere bokstavene i en String-variabel til store bokstaver:
    String s = "Jeg ER 18 ?r";
    String s2 = s.toUpperCase();
    // N? er s2 tekststrengen "JEG ER 18 ?R"
    


  4. Lese to arrayer fra fil:  kap. 5, oppg. 3 (side 97)
    Lag et program som skal behandle data om vekten til elevene i en skoleklasse.  Det er 27 elever i klassen.  Dataene ligger p? fil slik:
    Jens 52
    Marit 43
    ...
    
    (a) Les dataene inn i to arrayer: en navnearray (String) og en vektarray (int).
    (b) La programmet finne h?yeste og laveste vekt og skrive ut navn og vekt p? disse.
    (c) La programmet beregne gjennomsnittsvekten i klassen.

    Hint: Se eksemplet p? side 60 i l?reboka under "// Fil til array".  I del (c) kan du bruke gjennomsnitts-metoden fra oppgave 8. forrige uke:
    Metode med array som inn-parameter: kap. 7, oppg. 3 (side 134)
    Lag en metode double gjennomsnitt(int[] a) som summerer alle elementene i heltallsarrayen a, og som returnerer (det aritmetiske) gjennomsnittet av verdiene i a.


  5. Tekster: Hva blir skrevet ut? 
    import easyIO.*;
    class Tekster {
        public static void main(String[] args) {
    	 Out skjerm = new Out();
    
    	 String s1 = "hei";
    	 String s2 = "Java";
    	 String[] navn = { "Rune", "Martin", "Guro", null };
    
    /* a */  skjerm.outln(navn.length + s1.length());
    
    /* b */  skjerm.outln(3.1415 + "" + 'x');
    
    /* c */  skjerm.outln("" + false);
    
    /* d */  skjerm.outln("" + ! "abc".equals("abc"));
    
    /* e */  skjerm.outln("heia" == (s1 + "a"));
    
    /* f */  skjerm.outln("heia".equals(s1 + s2.charAt(1)));
    
    /* g */  skjerm.outln(s1.equals("h" + navn[0].charAt(3) + 'i'));
    
    /* h */  skjerm.outln(navn[1].substring(1));
    
    /* i */  skjerm.outln(navn[1].substring(1, 4));
    
    /* j */  skjerm.outln(s2.replace('a', 'i'));
    
    /* k */  skjerm.outln(navn[1].indexOf("tin"));
    
    /* l */  skjerm.outln(navn[2].indexOf("tin"));
    
    /* m */  skjerm.outln("A".compareTo("A"));
    
    /* n */  if (s1.compareTo("zz") < 0) skjerm.outln("s1 alfabetisk foran");
    
    /* o */  skjerm.outln(navn[2].toUpperCase());
    
    /* p */  if ("hei p? deg".startsWith(s1)) { skjerm.outln("ja"); }
    
    /* q */  int x = Integer.parseInt("123"); skjerm.outln(x + 1);
    
        }
    }
    


  6. Ord baklengs:  kap. 6, oppg. 3(a), (side 115)
    Lag et program som skriver ut teksten ?Agnes i senga? baklengs.  Hint: Bruk en for-l?kke som teller nedover.


Oppgaver til terminaltimen

  1. Filer og tekster:
    (De samme oppgavene som for teoritimen, punkt 1. til 4.).  Kontrollér at filene blir laget riktig ved ? skrive kommandoen:  more filnavn.txt  p? kommandovinduet (Linux/Mac), eller:  type filnavn.txt  (Windows).  Disse kommandoene viser n?v?rende innhold i den angitte filen.


  2. Lukking av filer:  kap. 3, oppg. 5 (side 71)
    Programmet under er ment ? skulle skrive setningen ?En fugl i h?nden er bedre enn ti p? taket.?  til en fil med navn ?ordtak.txt?, men noe mangler, slik at resultatet blir en tom fil.  Finn feilen!
    import easyIO.*;
    
    class Ordtak {
        public static void main (String[] args) {
            Out utfil = new Out("ordtak.txt");
            utfil.outln("En fugl i h?nden er bedre enn ti p? taket.");
        }
    }
    


  3. Tallsiffer-oversetting:  kap. 6, oppg. 7 og 8 (side 116)
    (a) Lag et program som oversetter fra tallsiffer til tekst slik at f.eks. 3 blir oversatt til "tre".  Programmet skal kunne oversette alle 10 sifre (fra 0 til 9).  Hint: Bruk en array med tekstene "null", "en", "to", osv.
    (b) Lag et program som oversetter fra tekst til tall.  Programmet skal be brukeren skrive inn et tall mellom null og ni (med bokstaver), og skrive ut tilsvarende siffer. Hint: Bruk arrayen fra del (a).


  4. Gj?r ferdig obligatorisk oppgave 2. 


  5. Ekstraoppgave: Flere metoder
    Fullf?r f?lgende program, som viser bruk av metoder.  Angi ogs? hva programmet skriver ut.
    import easyIO.*;
    
    class Metoder {
        public static void main(String[] args) {
            TestMetoder tm = new TestMetoder();
            tm.start();
        }
    }
    
    class TestMetoder {
        In tast = new In();
        Out skjerm = new Out();
    
        void start() {
    	// Kaller en enkel metode:
    	metode1();
    
    	// Kaller en metode med én inn-parameter:
    	skrivTredoblet(123);
    
    	// Leser to tall fra tastatur, og overf?rer de til en metode
    	// som finner og skriver ut det h?yeste av de to tall:
    	skjerm.out("Skriv to tall (f.eks. 7 4): ");
    	int tall1 = tast.inInt();
    	int tall2 = tast.inInt();
    	finnH?yesteAv2(tall1, tall2);
    
    	// Kaller en metode som multipliserer de samme to tall lest
    	// inn ovenfor, og returnerer resultatet hit.
    	int resultat = multipliser( /* Fyll inn resten. . . */ );
    	skjerm.outln("Resultat multiplisert: " + resultat);
    
    	// Metode med array som inn-parameter:
    	double[] verdier = { 0, -3, 5, 10, -20, -7.7, 1.2, -0.01 };
    	//int antNeg = finnAntallNegativeTall(verdier);
    	//skjerm.outln("Arrayen verdier[] har " + antNeg + " negative tall.");
    	// <- Ta bort "//" i de to linjene over.
        }
    
        void metode1() {
    	skjerm.outln("Dette er metode1");
        }
    
        void skrivTredoblet(int x) {
    	int tredoblet = x * 3;
    	skjerm.outln("Tredoblet resultat = " + tredoblet);
        }
    
        void finnH?yesteAv2(int a, int b) {
    	// Hva mangler her?
    	// . . .
    
    	skjerm.outln("H?yest av de to tall er:" /* . . . */ );
        }
    
        int multipliser( /* Fyll inn resten. . . */) {
    	// . . .
    
    	return  0 ; // . . . Erstatt 0 med resultatet av x ganger y.
        }
    
        // Skriv metoden "finnAntallNegativeTall" her, som har en array med
        // double-verdier som inn-parameter, finner ut hvor mange av verdiene
        // i arrayen er negative tall, og returnerer det antallet (som en int).
    
        // . . .
    }
    


  6. Ukens n?tt: Sudoku hjelpeprogram
    (a) Lag et program som leser inn en Suduko-oppgave fra fil og lagrer de forh?ndsutfylte tallene i en 2-dimensjonal array.  Deretter g?r programmet i en l?kke som sp?r brukeren om et rad- og et kolonnenummer (i omr?det 1-9, eller 0 for ? avslutte).  Programmet skal s? svare brukeren med hvilke tall (1-9) som er mulige kandidater for plassering i den angitte rad/kolonne-plassen, ved ? finne ut hvilke av sifrene 1-9 ikke er allerede brukt i samme rad, kolonne, eller 3×3-omsluttende boks. 

    Input-filen er p? 9 linjer, med 9 tall per linje adskilt med mellomrom, og hvor 0 angir plassene som ikke har forh?ndsutfylt siffer i Sudoku-oppgaven.  Her er et eksempel p? en slik fil (med middels vanskelig oppgave).  Finn gjerne andre oppgaver fra aviser eller nettet. 
    6 0 7 0 0 0 0 8 0
    0 0 0 1 0 4 0 7 0
    0 0 5 0 0 8 0 3 0
    8 0 0 3 0 0 7 0 0
    4 0 0 5 0 6 0 0 8
    0 0 1 0 0 2 0 0 6
    0 8 0 4 0 0 5 0 0
    0 9 0 2 0 3 0 0 0
    0 7 0 0 0 0 1 0 3
    
    (b) Utvid deretter programmet slik at det g?r gjennom alle ikke-utfylte ruter (i stedet for ? be brukeren taste en), og for de rutene som bare har ett kandidatsiffer setter du sifferet inn i arrayen.  Gjenta prosessen med de gjenv?rende ikke-utfylte ruter helt til to p?f?lgende gjennomkj?ringer ikke finner nye tall ? sette inn.  Skriv ut resultatbrettet til slutt.


L?sningsforslag

Her kan du finne l?sningsforslag til disse oppgavene.


Kommentarer om dette oppgavesettet kan du sende til josek [at] ifi.uio.no