Exercise index of this lecture   Alphabetic index   Course home   

Exercises and solutions
De ikke objekt-orienterede dele af Java


3.1   Klassen Brøk  

Programmer videre på klassen Broek, som vi har startet på ovenfor.

Programmer som et minimum de aritmetiske operationer add, subtract, multiply og divide.

Programmer også gerne andre relevante operationer, såsom equals, less-than, osv. Hvis du laver equals metoden bør du erindre mønstret fra en tidligere lektion.


3.2   Omformning af if til switch  

Se på og prøvekør programmet, som omregner procentpoint til karakterer ved skriftlige opgaver. Et komplet Java program er til jeres rådighed:

import cs1.Keyboard;

class IfDemo1 {

public static void main(String[] args){
  
  int procent, karakter;

  System.out.print("Hvormange procent? ");
  procent = Keyboard.readInt();

  if (procent >= 90)
    karakter = 11;
  else if (procent >= 82)
    karakter = 10;
  else if (procent >= 74)
    karakter = 9;
  else if (procent >= 66)
    karakter = 8;
  else if (procent >= 58)
    karakter = 7;
  else if (procent >= 50)
    karakter = 6;
  else if (procent >= 40)
    karakter = 5;
  else if (procent >= 0)
    karakter = 3;
  else karakter = 0; 

  System.out.println(procent + "% svarer til karakteren " + karakter);
  }
}

Vær sikker på, at I forstår det i detaljen. Ville programmet virke, hvis vi foretog testene i omvendt rækkefølge?

Det er åbentbart umuligt at få 13 igennem dette program; Kan man få 0 ved brug af dette program?

Diskuter hvorvidt dette program kan omskrives til brug af Java's switch kontrolstruktur. Begrund jeres svar. Udfør gerne en praktisk øvelse med dette, hvor I afprøver jeres evt. løsning i Java.

Dette program kræver adgang til klassen Keyboard eller tilsvarende (SimpletInput, jf. s 111 i Barnes). Hvis ikke din installation giver dig direkte adgang til denne klasse, ligesom det gøres på cs nettet på Aalborg Universitet, kan du blot placere Keyboard klassen i samme katalog som klassen IfDemo1.

Solution
Programmet beror på den skjulte forudsætning, at procent tallet er mellem 0 og 100. Hvis dette holder, kan man ikke få 0. Hvis man derimod giver programmet et negativt procenttal får man 0. Hvis vi tester tilfældene i omvendt rækkefølge vil programmet ikke virke.

Programmet vil nok være mere klart hvis vi eksplicit tester på intervaller:

  if (procent >= i) && (procent < j) ...;

En Java switch kontrolstruktur udvælger et bestemt tilfælde ud fra et tabelopslag på basis af et heltal eller tegn. Man kan principielt skrive en en switch med 101 tilfælde, som slår karakteren op af procenttallende 100, 99, 98, ..., 0. Dette ville dog være et tåbeligt program, og hvis sproget er implementeret på en uheldig måde, vil den underliggende tabel (hvori der slås op) blive alt for stor. Bedre ville det være at omregne procenttallet p til en størrelse, der kunne bruges som selektor i en switch; Men med denne omregning har vi reelt løst problemet - så det er heller ikke løsningen.

I dette eksempel er det ikke oplagt at bruge en switch kontrolstruktur. Generelt kan vi observere, at en if-then-else kæde er 'mere kraft- og udtryksfuld' end en switch. Det hænger på at switch blot slå op i en underliggende tabel af muligheder, hvorimod en if-then-else kæde gennemfører en række successive tests med vilkårligt komplicerede logiske udtryk


3.3   Break og continue  

Se på programmet på den tilknyttede slide.Programmet er også her:

class HopDemo1 {

static boolean even(int i){
  return (i % 2 == 0);
}

public static void main(String[] args){
  int i, j;

  loop1: for (i=1; i <=10; i=i+1)
    loop2: for(j=1; j <= 12; j=j+1){
      if (even(i)) continue loop1;
      if (even(j)) continue loop2;
      if (j == 7) break loop2;
     
      System.out.println("(" + i + "," + j + ")");
    }
  }  
}

Find ud af hvad programmet udskriver (i det mindste de første 6 talpar, eller indtil du finder et 'mønster').

Kør dernæst programmet. Er der overensstemmelse mellem dit resultat af ovenstående og programmets faktiske output?

Variér iøvrigt gerne på break og continue kommandoerne på forskellig vis. Vær sikker på, at du kan forklare resultaterne af dine forskellige testkørsler.

Solution
Variablen i løber fra 1 til 12 i den ydre løkke. Talparret (1,1) udskrives først. (1,2) udskrives ikke idet loop2 springes over når j er lige. Derimod udskrives (1,3) og videre (1,5). Når j bliver 7 bryder vi den indre løkke med break. Nu bliver i lig med 2, hvilket dog umiddelbart afstedkommer continue loop1. Altså er i nu 3, og talparrene (3,1), (3,3) og (3,5) udskrives. Således fortsættes.

Som man kan overbevise sig om ved at køre programmet udskrives alt i alt følgende:

 (1,1) (1,3) (1,5) (3,1) (3,3) (3,5) (5,1) (5,3) (5,5) (7,1) (7,3)
 (7,5) (9,1) (9,3) (9,5)


3.4   Indlæsning af heltal  

Som det fremgår af lærebogen er indlæsning af tal et noget mere kompliceret problem end blot indlæsning af en tekstlinie. For at indlæse et heltal skal man udtrække cifrene af den indtastede tekststreng (en form for parsning) og beregne tallet. Hvis man synes, at dette er for omstændeligt, kan man bruge et alternativt bibliotek, som indholder en mere direkte 'readInt' metode, f.eks. via klassen Console i kataloget /pack/local-java/lib/corejava/ eller klassen Keyboard fra Lewis og Loftus (2ed).

I denne opgave vil vi, for øvelsens skyld, selv programmere en procedure, som indlæser et heltal fra tastaturet. Dette giver en nyttig indsigt i forskellen mellem at læse tekst og tal. Opgaven går altså ud på at indlæse en række tegn, som danner et heltal, og dernæst konvertere de indlæste tegn til et tal af typen int. Man kan sige, at øvelsen går ud på at programmere operationen parseInt - som Java anvender for at løse opgaven.

Udfyld derfor detaljerne i følgende programskabelon:

/* Læs et tal fra en linie af tegn, og returner det pågældende tegn som en int */

import java.io.*; // for at kunne anvende BufferedReader mv.

class talLaesning {

  //et objekt, kaldet stdin, som tillader os at læse en tekst linie:
  static BufferedReader stdin = new BufferedReader (new InputStreamReader(System.in));

  public static int readInt() throws IOException{
  /* Read an integer from the keyboard, and return it as the result of this function */

     String textLine;
     int tal = 0;
     textLine = stdin.readLine();
  
     // Læs her et tegn fra strengen textLine og konverter tegnet til et tal.
     // Udregn løbende tallet, som hidtil er indlæst, og opbevar det i variablen tal.
     // Det i'te tegn i strengen s læses med s.charAt(i).
     // Iøvrigt er de statiske metoder isDigit og digit i klassen Character
     // sikkert nyttige.

     return tal;
  }

  // hovedprogrammet, som kalder readInt:
  public static void main (String[] ars) throws IOException{
     System.out.println("Indlaes et tal");
     int etTal = readInt();
     System.out.println("Tallet var: " +  etTal);
  }

}
  
Der henvises til klassen Character for funktioner, som aflæser og returnerer egenskaber af et tegn i typen char.

Program skabelonen kan downloades til en fil via følgende link: Skabelon

Solution
Mit program, som løser problemet, er følgende:

/* Læs et tal fra en linie af tegn, og retur det pågældende tegn som en int */

import java.io.*; // for at kunne anvende BufferedReader mv.

class talLaesning {

  //et objekt, kaldet stdin, som tillader os at læse en tekst linie:
  static BufferedReader stdin = new BufferedReader (new InputStreamReader(System.in));

  public static int readInt() throws IOException{
  /* Read an integer from the keyboard, and return it as the result of this function */

     String textLine;
     char nextCifferChar;
     int nextCiffer;
     textLine = stdin.readLine();
     
     int i, tal;
     boolean positive = true;    // the sign of the number
     boolean cifferRead = false; // have we seen the first ciffer
     tal = 0;
     for(i=0; i<textLine.length(); i++){
       nextCifferChar = textLine.charAt(i);
       if (Character.isDigit(nextCifferChar)){
            cifferRead = true;
            nextCiffer = Character.digit(nextCifferChar,10);
            tal = tal * 10 + nextCiffer;
       }
       else if (nextCifferChar == '-' && !cifferRead) {
            positive = !positive;
       }
       else if (nextCifferChar == '+' && !cifferRead) {
	 // just ignore it
       } 
       else System.out.println(nextCifferChar + " er et ulovligt tegn");
     }
     return positive ? tal : -tal;    
  }
  

  public static void main (String[] ars) throws IOException{
     System.out.println("Indlaes et tal");
     int etTal = readInt();
     System.out.println("Tallet var: " +  etTal);
  }

}
  


3.5   Tegning af en regulær polygon  

Klassen Crayon er en simpel klasse - set fra et grænseflade synspunkt - som gør det muligt at lave stregtegninger. Studér først klassens grænseflade, og forstå hvilke tjenester den tilbyder.

Benyt nu klassen Crayon til at skrive et program, som tegner en regulær n-kant (ligesidet trekant hvis n er 3, et kvadrat hvis n er 4, en regulær pentagon hvis n er 5, etc). Indlæs n fra tastaturet, f.eks. via klassen Keyboard.

Dit program skal naturligvis have adgang til klassen Crayon. Hvis dit Java system allerede har adgang til klassen, skal du blot importere klassen eller pakken hvori den forekommer. Hvis ikke, kan du placere Crayon klassen i samme katalog som din egen klasse. Det samme gælder for Keyboard. Dette giver umiddelbart adgang til klasserne fra dit eget program.

På cs nettet findes Crayon klassen i pakken oopcourse.util. Klassen Keyboard findes i cs1 pakken - ligesom det antages i lærebogen.

Solution
Mit program, som løser problemet, er følgende:

import oopcourse.util.*;
import java.awt.*;
import cs1.*;

class CrayonPolygon {

  static Crayon cb = new Crayon(Color.red, 3);

  public final static double EDGE_LENGTH = 50;

  public static void drawPolygon(Crayon c, int degree){
    double angel = 360/degree;
    for(int i = 1; i <= degree; i++){
      cb.move(EDGE_LENGTH);
      cb.turn(angel);
    }
  }

  public static void main(String[] args){
    System.out.print("Hvormange sider i polygonen:");
    int n = Keyboard.readInt();
    cb.jumpto(200,200);
    drawPolygon(cb, n);
  }
}

Her er et link til programmet.


Generated: Monday March 31, 2008, 12:08:13
on the system cs-unix