Aufgabe 1

Lösungsidee

Es wird eine Klasse Person erstellt, welche Felder (Eigenschaften) für Vorname (forename), Nachname (surname), Alter (age), Mädchenname (maidenName), Geschlecht (male = true/false) sowie den Ehepartner als Objekt-Verweis (Person mate) auf eine andere Person enthält. Ist dieser Verweis = null, ist die Person ledig.
Beim Heiraten (Person.marry(Person brideOrGroom)) müssen die Eigenschaften beider beiteiligter Personen angepasst werden. Bei Scheidung (Person.divorce()) wird der Verweis auf den Ehepartner wieder gelöscht und der Name der Ehepartnerin wieder gleich dem Mädchennamen gesetzt. Die "Heirats-Methode" gibt weiters einen boole'schen Wert zurück, anhand dessen vom Rufer festgestellt werden kann, ob die Heirat zulässig ist. Ist sie es nicht, wird eine Fehlermeldung in einem weiteren Feld (errMsgMarry) der Person, auf der die Methode aufgerufen wurde, gesetzt.

Source

/**
 * 
 * Softwareentwicklung I - Exercise 5/1.
 * Class Person for abstracting marrying and divorcing.
 * In-source comments are followed by the described code.
 * 
 * @author Daniel Brunthaler (0255054)
 * @version 1.0
 * 
 */
public class Person {

    private String surname;
    // maiden name is set, if the person is female and gets married.
    private String maidenName = null;
    private String forename;
    private int age;
    // false, if the person is female.
    private boolean male;
    // null if the person is unmarried.
    private Person mate = null;
    // contains an error message if marrying is not allowed 
    // (means method boolean marry(Person brideOrGroom) returns false).
    public String errMsgMarry = null;
    
    /**
     * Constructor for a person.
     * @param forename of person.
     * @param surname of person.
     * @param male true, if person is male, false if female.
     * @param age of person.
     */
    public Person(String forename, String surname, boolean male, int age) {
        this.forename = forename;
        this.surname = surname;
        this.male = male;
        this.age = age;
    }
    
    /**
     * String representation of this person.
     * @return an adequate String of the personal data of this person.
     * @see java.lang.Object#toString()
     */
    public String toString() {
        String personalInfo;
        if(male()) {
            personalInfo = "Herr ";
        } else {
            personalInfo = "Frau ";
        }
        personalInfo +=  name() + ", Alter " + age();
        if(mate == null) {
            personalInfo += ", ledig";
        } else {
            personalInfo += ", verheiratet mit " + mate.name();
        }
        return personalInfo;
    }
    
    /**
     * Gender of person.
     * @return true if person is male, false if female.
     */
    public boolean male() {
        return male;
    }
    
    /**
     * Name of the person in an adequate String.
     * @return Forename, surname and maiden name when person is female and 
     *          married.
     */
    public String name() {
        String name = forename + " " + surname;
        if (!male() && mate != null) {
            name += " (Maedchenname " + maidenName + ")";
        }
        return name;
    }
    
    /**
     * Marriage status.
     * @return true if person is married.
     */
    public boolean married() {
        if (mate == null) {
            return false;
        } else {
            return true;
        }
    }
    
    /**
     * Age of person.
     * @return age of person.
     */
    public int age() {
        return age;
    }

    /**
     * Marry this person with another person.
     * @param brideOrGroom person which should this person married with.
     * @return true if the marriage is allowed, false if not allowed. In this
     *           case an error message is saved in errMsgMarry.
     */
    public boolean marry(Person brideOrGroom) {
        errMsgMarry = null;
        if (married()) {
            errMsgMarry = name() + " ist schon verheiratet!";
            return false;
        } else if (brideOrGroom.married()) {
            errMsgMarry = brideOrGroom.name() + " ist schon verheiratet!";
            return false;
        } else if (age() < 18) {
            errMsgMarry = name() + " ist zu jung zum Heiraten!";
            return false;
        } else if (brideOrGroom.age() < 18) {
            errMsgMarry = brideOrGroom.name() + " ist zu jung zum Heiraten!";
            return false;
        } else if (!(male() ^ brideOrGroom.male())) {
            errMsgMarry = "Homosexuelle Ehen sind nicht erlaubt!";
            return false;
        } else {
            mate = brideOrGroom;
            brideOrGroom.mate = this;
            if (male()) {
                brideOrGroom.maidenName = brideOrGroom.surname;
                brideOrGroom.surname = surname;
            } else {
                maidenName = surname;
                surname = brideOrGroom.surname;
            }
        }
        return true;
    }
    
    /**
     * Divorce of this person and the married person. The female part gets
     * back her maiden name (into the surname). 
     */
    public void divorce() {
        if (mate == null) {
            return;
        } else {
            if (male()) {
                mate.surname = mate.maidenName;
                mate.maidenName = null;
                mate.mate = null;
                mate = null;
            } else {
                surname = maidenName;
                maidenName = null;
                mate.mate = null;
                mate = null;
            }
        }
    }
    
    /**
     * For testing purpose only. Marrying and divorcing as well as all possible 
     * error cases are tested.
     * @param args no arguments have to be given.
     */
    public static void main(String[] args) {
        boolean marryOk;
        Person donald = new Person("Donald", "Duck", true, 30);
        Person daisy = new Person("Daisy", "Queen", false, 25);
        Person gustav = new Person("Gustav", "Gans", true, 50);
        Person tick = new Person("Tick", "Duck", true, 16);
        IO.writeLn(donald.toString());
        IO.writeLn(daisy.toString());
        IO.writeLn(gustav.toString());
        IO.writeLn(tick.toString());
        IO.writeLn("Donald und Daisy heiraten (endlich) :) ...");
        marryOk = donald.marry(daisy);
        if(!marryOk) {
            IO.writeLn(donald.errMsgMarry);
        }
        IO.writeLn(donald.toString());
        IO.writeLn(daisy.toString());
        IO.writeLn("Gustav will Daisy heiraten ...");
        marryOk = gustav.marry(daisy);
        if(!marryOk) {
            IO.writeLn(gustav.errMsgMarry);
        }
        IO.writeLn(gustav.toString());
        IO.writeLn(daisy.toString());
        IO.writeLn("Donald und Daisy lassen sich wieder scheiden :( ...");
        donald.divorce();
        IO.writeLn(donald.toString());
        IO.writeLn(daisy.toString());
        IO.writeLn("Daisy ist deprimiert und will Tick heiraten ...");
        marryOk = daisy.marry(tick);
        if(!marryOk) {
            IO.writeLn(daisy.errMsgMarry);
        }
        IO.writeLn(daisy.toString());
        IO.writeLn(tick.toString());
        IO.writeLn("Donald wird schwul und will Gustav heiraten ...");
        marryOk = donald.marry(gustav);
        if(!marryOk) {
            IO.writeLn(donald.errMsgMarry);
        }
        IO.writeLn(donald.toString());
        IO.writeLn(gustav.toString());
    }
}

  

Test

Testplan + Hardcopy

Der Test wurde in der main-Methode der Klasse Person implementiert, da der Aufwand der Entwicklung eines Benutzer-Systems den Entwicklungsaufwand für die Klasse Person weit übertreffen würde. Getestet wird der Heirats- und Scheidungsfall sowie alle möglichen Fehlerfälle.

Aufgabe 2

Lösungsidee

Zur Speicherung der Häufigkeiten der Zeichen des Alphabets wird ein int-Array verwendet. Um den Index auf die entspr. Buchstaben abzubilden wird die Methode Character.getNumericValue(char ch) und die Methode Character.forDigit(int digit, Character.MAX_RADIX) verwendet, wobei erstere bei 'a' den Wert 10 ausspuckt und bei zweiteren mit radix = Character.MAX_RADIX dieser Wert wieder in 'a' umgewandelt werden kann. Zur Abbildung des Index muss einfach 10 vom Wert der Methode Character.getNumericValue(char ch) subtrahiert werden und um vom Index des Arrays auf den Buchstaben zu kommen, vor Aufruf der Methode Character.forDigit(int digit, Character.MAX_RADIX) 10 zum entspr. Wert addiert werden.
Die Summe der Buchstaben wird der Einfachheit und der Performance halber in der count-Methode mitgezählt, damit sie dann in der Methode sum() nicht erst berechnet werden muss, was ebenfalls möglich wäre. Die Methode count(String word) ruft zur Kapselung der Funktionen für jeden char des Strings die Methode count(char ch) auf.
Alle Zeichen, welche außerhalbe des Bereiches von 'a' bis 'z' bzw. 'A' bis 'Z' liegen, werden beim Auswerten ignoriert (also auch Leerzeichen).

Source

/**
 * Softwareentwicklung I - Exercise 5/2.
 * Analysing texts in english language.
 * In-source comments are followed by the described code.
 * 
 * @author Daniel Brunthaler (0255054)
 * @version 1.0
 * 
 */
public class CharFreqs {

    private int[] freq = new int[26];
    private int sum = 0;
    
    /**
     * Constructor for a CharFreqs object.
     * The freq array is initialized.
     * @see java.lang.Object#Object()
     */
    public CharFreqs() {
        for (int i=0;i < freq.length;i++) {
            freq[i] = 0;
        }
    }
    
    /**
     * Consider a certain character. All characters different from 'a' until 'z' 
     * and 'A' until 'Z' are ignored. 
     * @param ch character which should be considered.
     */
    public void count(char ch) {
        ch = Character.toLowerCase(ch);
        int idx = Character.getNumericValue(ch) - 10;
        if (idx >= 0 && idx <= 25) {
            sum++;
            freq[idx]++;
        }
    }
    
    /**
     * Consider a certain String.
     * @param word which should be considered. Could be a text with more than one word.
     */
    public void count(String word) {
        char[] chWord = word.toCharArray();
        for (int i = 0;i < chWord.length;i++) {
            count(chWord[i]);
        }
    }
    
    /**
     * Sum of all characters ('a' until 'z' and 'A' until 'Z'), 
     * which occured in the analysed text.
     * @return int
     */
    public int sum() {
        return sum;
    }
    
    /**
     * Average occurence of a certain character.
     * @param ch character (allowed 'a' until 'z' and 'A' until 'Z').
     * @return average occurence of the given character.
     */
    public float mean(char ch) {
        ch = Character.toLowerCase(ch);
        int idx = Character.getNumericValue(ch) - 10;
        if (idx >= 0 && idx <= 25) {
            if (sum == 0) {
                return 0;
            } else {
                return (float) freq[idx] / (float) sum;
            }
        }
        return 0;
    }
    
    /**
     * The character which occured most in the analysed text.
     * @return character which occured most in the analysed text.
     */
    public char max() {
        int max = 0, i_max = 0;
        for (int i = 0;i < freq.length;i++) {
            if (freq[i] > max ) {
                max = freq[i];
                i_max = i;
            }
        }
        return Character.forDigit(i_max + 10,Character.MAX_RADIX);
    }
    
    /**
     * The character which occured least in the analysed text.
     * @return character which occured least in the analysed text.
     */
    public char min() {
        int min = Integer.MAX_VALUE, i_min = 0;
        for (int i = 0;i < freq.length;i++) {
            if (freq[i] != 0 && freq[i] < min ) {
                min = freq[i];
                i_min = i;
            }
        }
        return Character.forDigit(i_min + 10,Character.MAX_RADIX);
    }
    
    /**
     * For testing purpose only.
     * @param args no arguments have to be given.
     */
    public static void main(String[] args) {
        CharFreqs charFreqs = new CharFreqs();
        String text;
        char ch;
        do {
            IO.write("Bitte zu analysierende Buchstaben/Worte eingeben: ");
            text = IO.readLine();
            if (text.length() == 1) {
                charFreqs.count(text.charAt(0));
            } else {
                charFreqs.count(text);
            }
        } while (text.length() > 0);
        IO.write("\nSumme der Buchstaben                  : ");
        IO.writeLn(charFreqs.sum());
        IO.write("Am haeufigsten vorkommender Buchstabe : ");
        IO.writeLn(charFreqs.max());
        IO.write("Am seltensten vorkommender Buchstabe  : ");
        IO.writeLn(charFreqs.min());
        IO.writeLn("\nHaeufigkeit der Buchstaben");
        for(int i = 0, column = 0;i < 26;i++) {
            // Format the output of the frequencies into four columns.
            if (column > 4) {
                IO.write("\n");
                column = 0;
            }
            ch = Character.forDigit(i + 10,Character.MAX_RADIX);
            IO.write(ch + ": " + charFreqs.mean(ch) + " ",15);
            column++;
        }
        System.exit(0);
    }
}

  

Test

Testplan + Hardcopys

Um sowohl die Auswertung von einzelnen Zeichen als auch von ganzen Wörtern zu testen, wird in der main-Methode abhängig von der Anzahl der eingegebenen Zeichen entweder count(char ch) oder count(String word) aufgerufen. Die Eingabe von Zeichen/Wörtern kann durch Eingabe einer leeren Zeichenkette beendet werden.
Der Einfachheit halber wurde in der main-Methode die Ausgabe der Häufigkeiten aller Buchstaben (von a bis z) implementiert.

Eingabe: abcdefghijklmnopqrstuvwxyz
aabb Erwartete Ausgabe: Summe : 30 Häufigster Buchstabe : a (gleich häufig wie b kommt aber vorher) Seltenster Buchstabe : c (gleich selten wie c-z aber erster) Häufigkeit a : 0.1 (3/30) Häufigkeit b : 0.1 (3/30) Häufigkeit c-z : 1/30 Zweck: Test, ob das Prg. grundsätzlich fkt. Hardcopy: Eingabe: Daniel Brunthaler
b b Erwartete Ausgabe: Summe : 18 Häufigster Buchstabe : b Seltenster Buchstabe : d Häufigkeit : ... (manuelle Rechnung nicht mehr sinnvoll) Zweck: Test, ob das Prg. auch Großbuchstaben sowie einzelne Zeichen richtig verarbeitet. Hardcopy: Eingabe: There are worse things in life than death. Have you ever spent an evening with an insurance salesman? Erwartete Ausgabe: ... (manuelle Rechnung nicht mehr sinnvoll) Auf jeden Fall Häufigkeit = 0 bei b, j, k, q, x und z Zweck: Test von umfangreicheren Texten. Hardcopy: