Anteckningar från föreläsning 5

Detta är den programkod vi skrev -- anteckningarna är gjorda bara för att vara ett stöd för minnet för dem som var där, och därför inte nödvändigtvis fullständiga eller ens sammanhängande. Betydligt mer hjälp finns att hämta i kompendiet.

OH-bilder finns här.

Mer om strängar

Vi började där vi slutade förra veckan, med strängar, och löste följande två uppgifter:

class CountVowels {

    public static void main(String[] args) {
        new CountVowels().run();
    }

    String vowels = "aouåeiyäö";

    void run() {
        String message = Keyboard.nextLine("Ange text: ");
        System.out.print("Antal vokaler: ");
        System.out.println(numberOfVowels(message));
        System.out.print("Utan vokaler: ");
        System.out.println(withoutVowels(message));
        System.out.println(numberOfVowels(withoutVowels(message)));
    }

    int numberOfVowels(String text) {
        int count = 0;
        for (int k = 0; k < text.length(); k++) {
            if (isVowel(text.charAt(k))) {
                count++;
            }
        }
        return count;
    }

    boolean isVowel(char ch) {
        ch = Character.toLowerCase(ch);
        if (vowels.indexOf(ch) >= 0) {
            return true;
        }
        return false;
    }

    String withoutVowels(String text) {
        StringBuilder sb = new StringBuilder();
        for (int k = 0; k < text.length(); k++) {
            char ch = text.charAt(k);
            if (!isVowel(ch)) {
                sb.append(ch);
            } else {
                sb.append('_');
            }
        }
        return sb.toString();
    }
}

Mer om loopar

Härefter pratade vi lite om olika slags loopar:

Vi löste denna på två sätt ‐ först med en vanlig while-sats:

class Looping {

    public static void main(String[] args) {
        new Looping().run();
    }

    void run() {
        Die d1 = new Die();
        Die d2 = new Die();
        int count = 0;
        d1.roll();
        d2.roll();
        while (d1.getNbrOfSpots() != d2.getNbrOfSpots()) {
            d1.roll();
            d2.roll();
            count++;
        }
        System.out.println(count);
    }
}

Ett problem här är att vi måste kasta de båda tärningarna redan innan vi går in i loopen. Ett alternativ är att använda do-while-loopen:

class Looping {

    public static void main(String[] args) {
        new Looping().run();
    }

    void run() {
        Die d1 = new Die();
        Die d2 = new Die();
        int count = 0;
        do {
            d1.roll();
            d2.roll();
            count++;
        } while (d1.getNbrOfSpots() != d2.getNbrOfSpots());
        System.out.println(count);
    }
}

Därefter talade vi om 'eviga' loopar, och sätt att avbryta dem:

class LoopAgain {

    public static void main(String[] args) {
        new LoopAgain().run();
    }

    void run() {
        int sum = 0;
        while (true) {
            int value = Keyboard.nextInt("Ange tal: ");
            if (value < 0) {
                break;
            }
            sum += value;
        }
        System.out.println(sum);
    }
}

Att formatera utskrifter

System.out.printf-satsen är överkurs, men den kan vara bra att känna till:

class Printing {

    public static void main(String[] args) {
        new Printing().run();
    }

    void run() {
        System.out.println(1 + 2 + " = " + 1 + 2);
        System.out.printf("%4d = %4d\n", 1+2, 1+2);
        System.out.printf("pi = %10.8f\n", Math.PI);
    }
}

Vi skrev även ett program som ger en tabell med olika värden:

class PrintTable {

    public static void main(String[] args) {
        new PrintTable().run();
    }

    void run() {
        for (double x = 0; x <= 2.1; x += 0.125) {
            System.out.printf("%5.1f  %10.5f  %10.5f\n",
                              x, Math.sqrt(x), Math.exp(2*x));
            System.out.println(x);
        }
    }
}

Mer om parametrar ‐ call-by-value

class Inc {

    public static void main(String[] args) {
        new Inc().run();
    }

    void run() {
        int n = 0;
        increase(n);
        System.out.println(n);
        increase(5);
    }

    void increase(int n) {
        n++;
    }
}

Det visar sig att värdet på n i huvudprogrammet inte ändras -- det är bara dess värde som skickas till underprogrammet.

class MovingTurtles {

    public static void main(String[] args) {
        new MovingTurtles().run();
    }

    GraphicsWindow w = new GraphicsWindow(500, 500);   // global

    void run() {
        Turtle t = new Turtle(w, 250, 250);
        move(t);
        w.waitForMouseClick();
        t.left(90);
    }

    void move(Turtle t) {
        t.forward(100);
        t = new Turtle(w, t.getX() + 100, t.getY() + 100);
    }
}

Även här är det bara värdet på parametern t som skickas, men vi kan ändra på det objekt som den referar till.

Att hantera fel

Vi skrev en funktion som skulle räkna ut arean av trianglar, och som ger ett exekveringsfel om någon skickar in värden som inte kan vara sidor i en triangel:

class Triangles {

    public static void main(String[] args) {
        new Triangles().run();
    }

    void run() {
        double a = Keyboard.nextDouble("Ange sida a: ");
        double b = Keyboard.nextDouble("Ange sida b: ");
        double c = Keyboard.nextDouble("Ange sida c: ");
        try {
            System.out.print("Arean är: ");
            System.out.println(area(a, b, c));
        } catch (Exception e) {
            System.out.println("Något gick fel: " + e.toString());
        }
        System.out.println("Jag kom hit!");
    }

    double area(double a, double b, double c) {
        if (a > b + c || b > a + c || c > a + b) {
            throw new RuntimeException("Felaktiga sidor");
        }
        double s = (a + b + c) / 2;
        return Math.sqrt(s * (s - a) * (s - b) * (s - c));
    }
}

Vi såg även hur man kan fånga upp de fel som uppstår när någon matar in en sträng istället för ett heltal:

class InputExample {

    public static void main(String[] args) {
        new InputExample().run();
    }

    void run() {
        int choice = menu();
        System.out.printf("Du valde %d\n", choice);
        switch (choice) {
        case 1:
            System.out.println("Skall chiffrera");
            break;
        case 2:
            System.out.println("Skall dechiffrera");
            break;
        default:
            System.out.println("Felaktigt kommando");
            break;
        }
    }

    int menu() {
        System.out.println("1. Chiffrera");
        System.out.println("2. Dechiffrera");
        try {
            int choice = Keyboard.nextInt("Ange alternativ: ");
            return choice;
        } catch (Exception e) {
            System.out.println("Inte ett tal");
            Keyboard.nextLine();
            return menu();
        }
    }
}

Ett problem med globala variabler

Avslutningsvis såg vi att vi måste vara försiktiga när vi använder globala variabler -- det är helt OK att använda dem för att flera underprogram skall kunna använda värden som de alla är intresserade av, men gör det inte för tat slippa deklarera variabler i underprogrammen!

class Globals {

    public static void main(String[] args) {
        new Globals().run();
    }

    int k;     // usch och fy!

    void run() {
        GraphicsWindow w = new GraphicsWindow(500, 500);
        Turtle t = new Turtle(w, 300, 300);
        t.setSpeed(10);
        t.penDown();
        for (k = 1; k <= 3; k++) {
            drawSquare(t, 100);
            t.jumpTo(t.getX() + 37, t.getY() + 23);
        }
    }

    void drawSquare(Turtle t, int side) {
        for (k = 1; k <= 4; k++) {
            t.forward(side);
            t.left(90);
        }
    }
}

Vi tittade även snabbt på hur vi skulle kunna skriva ett program som spelar Hangman (meningen är att ni själva skall göra det under övningen).

class Hangman {

    public static void main(String[] args) {
        new Hangman().run();
    }

    String hidden;
    StringBuilder pattern;
    int nbrOfGuesses;

    void run() {
        enterHiddenSentence();
        while (!finished()) {
            enterGuess();
        }
        congratulate();
    }

    void enterHiddenSentence() {
        hidden = Keyboard.nextLine("Ange gömd rad: ");
        // ...
    }
}