Donnerstag, 31. März 2011
Quadcopter spielen Tennis
Mittwoch, 23. März 2011
Literaturverwaltung - RandomAccessFile (POS1: 2A, 2C)
Jemand will Zeitschriftenartikel, Bücher und Internet-Links für seine Recherchen verwalten. Schreiben Sie dazu eine Java-Klasse (plus eventuelle Hilfsklassen), welche es ermöglicht diese Daten in einer RandomAccess-Datei zu speichern. Folgende Daten sollen in der Klasse
Eintrag
erfasst werden:- autor -
String(100)
- titel -
String(100)
- erscheinungsjahr -
int
- verlag -
String(30)
- zeitschrift -
String(30)
- seiten -
String(10)
- link -
String(60)
String(100)
bedeutet, dass dafür maximal 100 (genau 100) Zeichen gespeichert werden soll. Sie können das so implementieren, dass kürzere Strings hinten mit Leerzeichen gefüllt werden. Längere Strings müssen abgeschnitten werden. Für eine eventuelle Anzeige/Ausgabe müssen aber die Füllzeichen entfernt werden. Die Klasse Eintrag
ist mit entsprechenden Getter- und Setter-Methoden auszustatten (die bei den Strings das Abschneiden und Auffüllen bewerkstelligen).Die Klasse
Literatur
für die Verwaltung der Datensätze soll folgende Methoden bereitstellen:public void neuerEintrag(Eintrag eintrag)
- fügt einen neuen Eintrag in die Datei ein.public Eintrag lese(int nummer)
- liefert den Eintrag an der Stellenummer
odernull
, falls dieser Eintrag nicht existiert.public void loescheEintrag(int nummer)
- löscht den Eintrag an der Stellenummer
(tut nichts, wenn es den Eintrag nicht gibt).
Der Konstruktor der Klasse Literatur soll eine geöffnete RandomAccess-Datei als Parameter haben:
public Literatur(RandomAccessFile file)
Implementieren Sie das Löschen so, dass der jeweilige Eintrag als gelöscht markiert wird (zusätzliches Feld) und diese Änderung in der Datei gespeichert wird. Der Datensatz ist also physisch noch in der Datei. Bei der Methode
lese()
muss also im Falle eines gelöschten Eintrags null
geliefert werden.Umgekehrt muss bei
neuerEintrag()
zunächst ein gelöschter Eintrag gesucht werden. Wird ein solcher gefunden, so wird er durch den neuen ersetzt (Lösch-Markierung muss wieder zurückgesetzt werden). Wird kein gelöschter Datensatz gefunden, so ist der neue an die Datei anzuhängen.Schreiben Sie ein kleines Testprogramm zum Testen Ihrer Klassen.
Anmerkung: Die Daten sind für eine echte Anwendung nicht ausreichend und müssten unterteilt werden, da es z.B. mehrere Autoren für einen Artikel gibt.
Hinweis: hier finden Sie eine Testklasse zum Testen der Klasse
Literatur
. Die Klasse Literatur
muss wie diese Testklasse im Package literatur
sein. Weiters muss die Library für JUnit 3 angegeben werden. Diese Testklasse trifft gewissen Annahmen zur Implementierung von Literatur
und Eintrag
. Bitte passen Sie entweder die Testklasse an Ihre Implementierung an oder Sie ändern Ihre Literatur
bzw. Eintrag
-Klassen entsprechend (z.B. nimmt der Test an, dass es eine read()
und eine write()
-Methode gibt, die einen Datensatz ("in sich hinein") liest bzw. einen Datensatz ("sich selbst") schreibt (jeweils an die Position, die in Literatur
bestimmt wurde).Ihre Klasse Eintrag könnte etwa so beginnen:
public class Eintrag { // Feldlängen private final static int autorLen = 100; private final static int titelLen = 100; private final static int verlagLen = 30; private final static int zeitschriftLen = 30; private final static int seitenLen = 10; private final static int linkLen = 60; // Felder private String autor; private String titel; private int erscheinungsjahr; private String verlag; private String zeitschrift; private String seiten; private String link; // gelöscht? private boolean istGeloescht = false;Da eine fixe Datensatzlänge gefordert ist, müssen Sie die Länge ermitteln, indem Sie die Längen der einzelnen Felder zusammenzählen. Wir schätzen für
Boolean
die Länge von int
(bestimmt mit Hilfe der Wrapperklasse Integer
und der Konstante SIZE
, welche die Länge in Bits angibt).public static int eintragLen() { int len = Integer.SIZE / 8 + (autorLen + titelLen + verlagLen + zeitschriftLen + seitenLen + linkLen) * 3 + 6 * Long.SIZE / 8 + Integer.SIZE / 8; return len; }Der Faktor 3 entsteht durch die Verwendung der UTF-8-Kodierung. UTF-8 ist eine Kodierung des Unicodes und speichert alle Zeichen des ASCII-Codes auch in der selben Kodierung wie ASCII, daher werden dann für andere Zeichen 2, 3 bzw. 4 Bytes verwendet (Unicode verwendete in den ersteren Versionen 16 Bit, in Java werden daher Zeichen mit 16 Bit kodiert). Um ganz sicher zu sein, müsste man den Faktor 4 verwenden.
Long.SIZE / 8
ist die Längeninformation, die in jedem String-Objekt gespeichert ist.Strings werden mit
file.writeUTF(string);
geschrieben bzw. mit string = file.readUTF();
gelesen.public void write(RandomAccessFile out) throws IOException { out.writeBoolean(istGeloescht); out.writeUTF(autor); out.writeUTF(link); out.writeUTF(seiten); out.writeUTF(titel); out.writeUTF(verlag); out.writeUTF(zeitschrift); out.writeInt(erscheinungsjahr); } public void read(RandomAccessFile in) throws IOException, EOFException { istGeloescht = in.readBoolean(); autor = in.readUTF(); link = in.readUTF(); seiten = in.readUTF(); titel = in.readUTF(); verlag = in.readUTF(); zeitschrift = in.readUTF(); erscheinungsjahr = in.readInt(); }
Die String-Felder müssen natürlich auf eine fixe Länge gebracht werden, d.h. zu lange Strings müssen abgeschnitten, zu kurze evtl. verlängert werden. Dies erledigt man am Besten in den Setter- bzw. Getter-Methoden.
Das Lesen eines Datensatzes in der Klasse
Das Lesen eines Datensatzes in der Klasse
Literatur
könnte etwa so funktionieren:public Eintrag lese(int nummer) throws IOException { long pos = nummer * Eintrag.eintragLen(); if (pos < file.length()) { file.seek(pos); Eintrag eintrag = new Eintrag(); eintrag.read(file); if (!eintrag.istGeloescht()) { return eintrag; } else { return null; // gelöschter Eintrag gilt als nicht vorhanden } } else { return null; // über die Dateilänge hinaus } }Vervollständigen Sie mit diesen Informationen Ihre Klassen.
Nennen Sie das Projekt
klasse-name-literatur
(klasse
... 2a, 2b, 2c, name
... Ihr Familienname), z.B. 2a-haberstroh-literatur
.Freitag, 18. März 2011
Experimente mit Queues (POS1-2: 2A, 2C, PR: 5A, 5B)
Implementieren Sie im Package
Als Testklasse verwenden Sie bitte die folgende Klasse
Experimentieren Sie mit unterschiedlichen Wartezeiten, sodass die Queue (Ringpuffer) voll bzw. leer werden kann. Was passiert?
Wenn die Queue nicht synchronisiert wird, was kann passieren? Können Sie das Verhalten in Experimenten nachweisen?
Bauen Sie entsprechendes
Source Code
ringbuffer
eine Klasse Queue
für Integer-Werte. Implementieren Sie die Queue
in Form eines Ringpuffers. Es soll die Exception QueueFullException
geworfen werden, wenn der Ringpuffer voll ist und die Exception QueueEmptyException
, wenn der Ringpuffer leer ist.Als Testklasse verwenden Sie bitte die folgende Klasse
QueueTest
, welche zwei Threads erzeugt. Einen Sender, der zufällige "Nachrichten" (Integerwerte) in die Warteschlange steckt und einen Empfänger, der Werte aus der Warteschlange entnimmt. Beide geben jeweils die gesendete bzw. gelesene Nachricht aus. Beide Threads haben unterschiedliche zufällige Wartezeiten.Experimentieren Sie mit unterschiedlichen Wartezeiten, sodass die Queue (Ringpuffer) voll bzw. leer werden kann. Was passiert?
Wenn die Queue nicht synchronisiert wird, was kann passieren? Können Sie das Verhalten in Experimenten nachweisen?
Bauen Sie entsprechendes
synchronized
in Ihre Queue ein (5. Klasse). Was muss synchronisiert werden?Source Code
/** * java-queue: ringbuffer.QueueTest.java * * 17.03.2011, Harald R. Haberstroh */ package ringbuffer; import java.util.Random; /** * Testen der Queue mit 2 Threads. * * @author Harald R. Haberstroh (hp) * */ public class QueueTest extends Thread { private final static int MAXRUNS = 20; private Queue messages; private Random rnd = new Random(); public QueueTest(String name, Queue messages) { super(name); this.messages = messages; } public void run() { if (getName().equalsIgnoreCase("Sender")) { for (int i = 0; i < MAXRUNS; i++) { int msg = rnd.nextInt(100); long sleepTime = (long) rnd.nextInt(500) + 500; // 500-1000ms try { System.out.println(getName() + " sending " + msg); messages.put(msg); } catch (QueueFullException e) { System.err.println(getName() + ":Oops - Queue full"); } try { sleep(sleepTime); } catch (InterruptedException e) { System.err.println(getName() + ":Oops - interrupted"); } } } else { // Receiver setName(" " + getName()); // Einrückung for (int i = 0; i < MAXRUNS || !messages.isEmpty(); i++) { long sleepTime = (long) rnd.nextInt(900) + 600; // 900-1500ms try { if (!messages.isEmpty()) { System.out.println(getName() + " read " + messages.get()); } } catch (QueueEmptyException e) { System.err.println(getName() + ": Oops - Queue empty"); } try { sleep(sleepTime); } catch (InterruptedException e) { System.err.println(getName() + ":Oops - interrupted"); } } } System.out.println(getName() + " finished"); } public String toString() { return getName(); } /** * @param args */ public static void main(String[] args) { Queue messages = new Queue(); QueueTest sender = new QueueTest("Sender", messages); QueueTest receiver = new QueueTest("Receiver", messages); sender.start(); receiver.start(); try { sender.join(); receiver.join(); } catch (InterruptedException e) { System.err.println(e.getLocalizedMessage()); } System.out.println(".... all finished ...."); } }Beispielausgabe bei Standardeinstellung
Sender sending 73 Sender sending 46 Receiver read 73 Sender sending 63 Receiver read 46 Sender sending 11 Receiver read 63 Sender sending 89 Sender sending 21 Receiver read 11 Sender sending 99 Receiver read 89 Sender sending 79 Sender sending 41 Receiver read 21 Sender sending 17 Receiver read 99 Sender sending 92 Receiver read 79 Sender sending 89 Receiver read 41 Sender sending 52 Receiver read 17 Sender sending 60 Receiver read 92 Sender sending 25 Receiver read 89 Sender sending 82 Sender sending 60 Receiver read 52 Sender sending 13 Sender sending 34 Receiver read 60 Sender sending 10 Receiver read 25 Sender finished Receiver read 82 Receiver read 60 Receiver read 13 Receiver read 34 Receiver read 10 Receiver finished .... all finished ....
Labels: Aufgabe, Java, POS1-2, PR5
Mittwoch, 16. März 2011
RMI-Client/Server mit Java (PR: 5A, 5B)
Schreiben Sie eine Klasse
Die zu öffnende Datei soll als Parameter der Kommandozeile angegeben werden. Aufruf:
Also z.B.:
Schreiben Sie weiters eine Klasse
Also z.B.:
oder
In weiterer Folge soll der Client eine Minute lang zufällige Datensätze auswählen und ausgeben (falls diese existieren). Zwischen zwei Zugriffen soll eine zufällige Zeit zwischen 1 und 5 Sekunden liegen (d.h. es werden mindestens 12 und höchstens 60 weitere Zeilen ausgegeben).
Server
, welche über RMI folgende Objekte bereitstellt: rmi://localhost/Data
(implementiert InterfaceDB
)rmi://localhost/Header
(implementiert InterfaceHeader
)
localhost
kann natürlich (theoretisch) jede beliebige IP-Adresse bzw. jeder beliebige Hostname sein, wenn unter dieser Adresse ein RMI-Server erreichbar ist.Die zu öffnende Datei soll als Parameter der Kommandozeile angegeben werden. Aufruf:
java Server dateiname
Also z.B.:
java Server machines.db
Schreiben Sie weiters eine Klasse
Client
, welche über RMI die vom Server
bereitgestellten Objekte verwendet, um einfache "Datenbank"-Zugriffe zu machen. Beim Aufruf soll über einen optionalen Kommandozeilenparameter die Adresse des Servers angegeben werden. Wird kein Parameter angegeben, so ist localhost
zu verwenden. Aufruf: java Client [hostaddress]
Also z.B.:
java Client
oder
java Client 127.0.0.1
Client
soll einfach den Inhalt der Datenbank ausgeben (nur nicht gelöschte Datensätze). Die Spaltenüberschriften sind entsprechend der Informationen aus der Datei (über Header
) ausgeben. Zeilen müssen gemäß der Feldlängen formatiert sein.In weiterer Folge soll der Client eine Minute lang zufällige Datensätze auswählen und ausgeben (falls diese existieren). Zwischen zwei Zugriffen soll eine zufällige Zeit zwischen 1 und 5 Sekunden liegen (d.h. es werden mindestens 12 und höchstens 60 weitere Zeilen ausgegeben).
Binärdateien bearbeiten mit Java - Zusatz für Client (PR: 5A, 5B)
Wie unter "Binärdateien bearbeiten mit Java (PR: 5A, 5B)" beschrieben, ist in der Binärdatei auch die Feldbeschreibung enthalten. An Server bzw. in der Klasse
Data
wird aber nur die Typ bzw. Längeninformation benötigt. Implementieren Sie das Interface Header
(entweder eigene Klasse oder Klasse Data
), um die nötigen Informationen für den Client, der ja die Daten darstellen soll, bereitzustellen.package data; /** * RuD-Übung 2011 * * data.Header.java * @author (c) 2011, Harald R. Haberstroh * 16.3.2011 */ import java.rmi.Remote; import java.rmi.RemoteException; /** * @author Harald R. Haberstroh (hh) * */ public interface Header extends Remote { /** * Liefert die Anzahl der Felder. * * @return Anzahl der Felder * @throws RemoteException */ public int getNumFields() throws RemoteException; /** * Liefert den Feldnamen zur gegebenen Feldnummer * * @param fieldNo * Nummer Feldes. * @return Feldname * @throws RemoteException */ public String getFieldName(int fieldNo) throws RemoteException; /** * Liefert die Beschreibung des Feldes zur gegebenen Feldnummer * * @param fieldNo * Nummer Feldes. * @return Feldbeschreibung * @throws RemoteException */ public String getFieldDesc(int fieldNo) throws RemoteException; /** * Liefert den Typ des Feldes zur gegebenen Feldnummer. * 'F'...fix, 'V'...Variabel, 'C'...Zeichen * * @param fieldNo * Nummer Feldes. * @return Typ des Feldes ('F', 'V' oder 'C') * @throws RemoteException */ public char getFieldType(int fieldNo) throws RemoteException; /** * Liefert die (maximale) Länge des Feldes zur gegebenen Feldnummer. * * @param fieldNo * Nummer Feldes. * @return (maximale) Feldlänge * @throws RemoteException */ public int getFieldLen(int fieldNo) throws RemoteException; }
Donnerstag, 10. März 2011
Lösungen zu "Übungsbeispiele zu Sequenzen, Schleifen und Funktionen in Python" (POS1: 1B)
Hier mögliche Lösungen zu der Aufgabe "Übungsbeispiele zu Sequenzen, Schleifen und Funktionen in Python (POS1: 1B)". Einige der Aufgaben enthalten Suchaufgaben. Die Funktionen dazu sind teilweise nicht "strukturiert" programmiert, das heißt, dass sie in diesen Fällen nicht nur ein
Bei obigem Beispiel müsste man
Die Tests verwenden
Die Funktionen
return
sondern mehrere Ausgänge haben. Um das zu verdeutlichen, beachten Sie folgendes Beispiel:def isint(string): """prüft, ob der String eine ganze Zahl ist (Vorzeichen optional, nur Ziffern). Prüfe nur Ziffernbereich.""" if len(string) > 0: if string[0] == '+' or string[0] == '-': for c in string[1:]: if c < '0' or c > '9': return False else: for c in string: if c < '0' or c > '9': return False else: return False return TrueHier erfolgt ein
return False
aus den Schleifen über den String string
, sobald ein Fehler gefunden wurde. Das vereinfacht den Algorithmus, widerspricht aber der strukturierten Programmierung, die bei Funkionen nur einen Ausgang erlaubt (bei Schleifen gilt das auch, die Schleife verlässt man nur durch die Schleifenbedingung, nicht durch break
oder eben return
). Beim Debuggen größerer Systeme ist es von Vorteil, wenn man sich darauf verlassen kann, dass jede Funktion nur einen Ausgang hat, denn man braucht dann nur diesen einen beobachten und nicht mehrere.Bei obigem Beispiel müsste man
while
-Schleifen verwenden:def isint(string): """prüft, ob der String eine ganze Zahl ist (Vorzeichen optional, nur Ziffern). Prüfe nur Ziffernbereich.""" ok = True if len(string) > 0: if string[0] == '+' or string[0] == '-': i = 1 while ok and i < len(string): if string[i] < '0' or string[i] > '9': ok = False i += 1 else: i = 0 while ok and i < len(string): if string[i] < '0' or string[i] > '9': ok = False i += 1 else: ok = False return okDiese Variante könne man noch "vereinfachen", weil sich die beiden Zweige mit oder ohne Vorzeichen nur im Startwert der Laufvariable
i
unterscheiden:def isint(string): """prüft, ob der String eine ganze Zahl ist (Vorzeichen optional, nur Ziffern). Prüfe nur Ziffernbereich.""" ok = True if len(string) > 0: if string[0] == '+' or string[0] == '-': i = 1 else: i = 0 while ok and i < len(string): if string[i] < '0' or string[i] > '9': ok = False i += 1 else: ok = False return okDie "nicht strukturierte" Variante ist aber bei weitem schneller entwickelt und durch die automatischen Tests ist auch sichergestellt, dass sie funktioniert.
Die Tests verwenden
assert()
, um die Ergebnisse mit den erwarteten Ergebnissen zu vergleichen. assert()
bricht das Programm auf der Stelle ab, wenn die Bedingung nicht erfüllt ist. Dadurch hat man die Möglichkeit, den Fehler einzugrenzen. Passt die Bedingung, so läuft das Programm einfach weiter.""" author: Haberstroh, Harald matnr: d09666 file: sequenzenbeispiele.py desc: Beispiele einfacher Funktionen mit Sequenzen (vgl. Programmierblog) Einige Funktionen bauen auf den anderen auf. Zu jeder Funktion (ausgenommen Hilfsfunktion) gibt es eine Testfunktion die die jeweilige Funktion mit Testwerten prüft. Die Funktion assert() prüft den Wahrheitswert des Parameters. Ist dieser True, so läuft das Programm einfach weiter. Ist er jedoch False, wird das Programm mit einer Fehlermeldung und Zeilennummer abgebrochen. Man kann dadurch feststellen, welcher Test nicht funktioniert hat. date: 7.3.2011 class: Lehrer catnr: 33 """ #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def isint(string): """prüft, ob der String eine ganze Zahl ist (Vorzeichen optional, nur Ziffern). Prüfe nur Ziffernbereich.""" if len(string) > 0: if string[0] == '+' or string[0] == '-': for c in string[1:]: if c < '0' or c > '9': return False else: for c in string: if c < '0' or c > '9': return False else: return False return True def test_isint(): assert(isint("") == False) assert(isint("a") == False) assert(isint("1a") == False) assert(isint("a1") == False) assert(isint("1+1") == False) assert(isint("1+") == False) assert(isint("1") == True) assert(isint("+1") == True) assert(isint("-1") == True) assert(isint("11212") == True) assert(isint("-11212") == True) assert(isint("+11212") == True) print("test_isint() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def isintb(string, basis): """prüft, ob der String eine ganze Zahl zur Basis basis ist (Vorzeichen optional, nur Ziffern). Baue String mit gültigen Zeichen zusammen und prüfe dann, ob jedes Zeichen in diesem String vorkommt.""" if basis > 1: gueltig = "" # "Liste" der gültigen Zeichen für geg. Basis if basis > 10: # Ziffern und Buchstaben (immer groß und klein) for z in range(10): gueltig += chr(z + ord('0')) for z in range(basis - 10): gueltig += chr(z + ord('a')) # Kleinbuchstabe gueltig += chr(z + ord('A')) # Großbuchstabe else: # nur Ziffern for z in range(basis): gueltig += chr(z + ord('0')) if len(string) > 0: if string[0] == '+' or string[0] == '-': # Vorzeichen for c in string[1:]: if c not in gueltig: return False else: for c in string: if c not in gueltig: return False else: return False else: return False return True # alles OK def test_isintb(): assert(isintb("", 2) == False) assert(isintb("a", 2) == False) assert(isintb("1a", 2) == False) assert(isintb("a1", 2) == False) assert(isintb("1+1", 2) == False) assert(isintb("1+", 2) == False) assert(isintb("1", 2) == True) assert(isintb("+1", 2) == True) assert(isintb("-1", 2) == True) assert(isintb("11212", 2) == False) assert(isintb("-11212", 2) == False) assert(isintb("+11212", 2) == False) assert(isintb("11212", 3) == True) assert(isintb("-11212", 3) == True) assert(isintb("+11212", 3) == True) assert(isintb("aBCdeF", 16) == True) assert(isintb("-aBCdeF", 16) == True) assert(isintb("+aBCdeF", 16) == True) print("test_isintb() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def sumdigits(zahl): """Berechnet die Ziffernsumme aus der gegebenen Zahl (int)""" sum = 0 while zahl != 0: sum += zahl % 10 # Rest ist immer Einerstelle zahl = zahl // 10 return sum def test_sumdigits(): assert(sumdigits(0) == 0) assert(sumdigits(1) == 1) assert(sumdigits(7) == 7) assert(sumdigits(10) == 1) assert(sumdigits(11) == 2) assert(sumdigits(123) == 6) assert(sumdigits(1010) == 2) print("test_sumdigits() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def wert_der_ziffer(ziffer): """liefert den Wert der Ziffer ziffer (0..9, bzw. A, B, C, ...)""" if ord(ziffer) <= ord("9"): wert = ord(ziffer) - ord("0") else: wert = ord(ziffer) - ord("A") + 10 return wert def horner(zahl, basis): """berechnet Dezimalzahl aus zahl (String) zur Basis basis. liefert Zahl. Hornerschema!""" dez = 0 for ziffer in zahl: dez *= basis dez += wert_der_ziffer(ziffer) return dez def test_horner(): assert(horner("", 10) == 0) assert(horner("1", 10) == 1) assert(horner("12", 10) == 12) assert(horner("123", 10) == 123) assert(horner("1", 2) == 1) assert(horner("10", 2) == 2) assert(horner("11", 2) == 3) assert(horner("4", 16) == 4) assert(horner("A", 16) == 10) assert(horner("10", 16) == 16) print("test_horner() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def isipv4(string): """Prüft, ob der gegebene String eine IPv4-Adresse enthält. IPv4-Adressen sind 4 Zahlen zwischen 0 und 255, die durch einen Punkt getrennt sind. Beispiele: 127.0.0.1, 193.170.149.129, 81.200.64.185 Ungültige: 81.2010.64.185, 123.23.12, 127,0,0,1""" zahl = "" anzpunkte = 0 anzziffer = 0 for z in string: if '0' <= z <= '9': zahl += z anzziffer += 1 elif z == '.' and anzziffer > 0: # mindestens 1 Ziffer vor Zahl if not (0 <= horner(zahl, 10) <= 255): return False zahl = "" # neu beginnen anzziffer = 0 anzpunkte += 1 else: return False if anzpunkte == 3 and anzziffer > 0: # nach 3. Punkt eine Zahl! if not (0 <= horner(zahl, 10) <= 255): return False return True else: return False def test_isipv4(): assert(isipv4("127.0.0.1")) assert(isipv4("193.170.149.129")) assert(isipv4("81.200.64.185")) assert(not isipv4("")) assert(not isipv4("81.2010.64.185")) assert(not isipv4("123.23.12")) assert(not isipv4("123.23.12.")) assert(not isipv4("123.23.12.3.3")) assert(not isipv4("123.23.12.3.")) assert(not isipv4("127,0,0,1")) print("test_isipv4() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def anz_zahlen(string): """ermittelt die Anzahl der ganzen Zahlen im String""" anzahl = 0 in_zahl = False for zeichen in string: if zeichen in "0123456789": if not in_zahl: anzahl += 1 in_zahl = True else: in_zahl = False return anzahl def test_anz_zahlen(): string = "das ist eine Zahl 123 und noch eine 1 und noch eine 3213x23123" assert(4 == anz_zahlen(string)) assert(0 == anz_zahlen("keine")) assert(1 == anz_zahlen("eine Zahl 123")) assert(2 == anz_zahlen("zwei 23 und 324")) assert(3 == anz_zahlen("drei 23 34 22")) assert(4 == anz_zahlen("vier 234 234 234 45")) assert(5 == anz_zahlen("5 234 234 234 45")) print("test_anz_zahlen() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def sum_zahlen(string): """ermittelt die Summe der ganzen Zahlen im String. Eine Zahl ist eine ununterbrochene Folge von Ziffern. Beispiel: sum_zahlen("x 34 3 12k33 44 hallo 23") liefert 149""" summe = 0 zahl = "" for zeichen in string: if zeichen in "0123456789": zahl += zeichen else: summe += horner(zahl, 10) # umrechnen und dazuzählen zahl = "" # neu beginnen if len(zahl) > 0: # zuletzt war Zahl, daher dazurechnen summe += horner(zahl, 10) return summe def test_sum_zahlen(): string = "das ist eine Zahl 123 und noch eine 1 und noch eine 3213x23123" assert(26460 == sum_zahlen(string)) assert(0 == sum_zahlen("keine")) assert(123 == sum_zahlen("eine Zahl 123")) assert(347 == sum_zahlen("zwei 23 und 324")) assert(79 == sum_zahlen("drei 23 34 22")) assert(747 == sum_zahlen("vier 234 234 234 45")) assert(752 == sum_zahlen("5 234 234 234 45")) print("test_sum_zahlen() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def iskonto(string): """Prüft, ob der String eine gültige Kontonummer enthält. Dabei gelten folgende Regeln: 1. genau 9 Ziffern (es dürfen Leerzeichen dazwischen sein 2. die letzte Ziffer ist eine Prüfziffer und es gilt Die Kontonummer ist genau 9 Stellen lang und ist dann richtig, wenn die folgendermaßen gebildete Summe auf Null endet: Ziffern mit ungeradem Index werden addiert(=Teilsumme1); Ziffern mit geradem Index werden verdoppelt und das jeweilige Produkt addiert, wenn es einstellig ist, andernfalls wird die Quersumme des Produkts addiert(=Teilsumme2); Summe= teilsumme1 + Teilsumme2 Beispiel: 123456782 1+ 3+ 5+ 7+ 2 = 18 Teilsumme1 2*2+ 4*2+ (1+2)+ (1+6) = 22 Teilsumme2 6*2=12 8*2=16 ------ 40 Summe mod 10= Null Beispiele für Kontonummern: 697199107 richtige Kontonummer 723016689 richtige Kontonummer 723016699 falsche Kontonummer """ # entferne alle Leerzeichen (sind ja erlaubt) kontonummer = "" for c in string: if '0' <= c <= '9': kontonummer += c elif c != ' ': return False # nur Ziffern und Leerzeichen erlaubt! if len(kontonummer) != 9: return False summe = 0 # alles in einer Summe, aufteilen ist nicht nötig for i in range(len(kontonummer)): ziffer = ord(kontonummer[i]) - ord('0') if (1 + i) % 2 == 1: # ungerade summe += ziffer else: # gerade doppelt = ziffer * 2 if doppelt >= 10: # Zwei Ziffern summe += doppelt % 10 # Einer summe += doppelt // 10 # Zehner else: # immer noch eine Ziffer summe += doppelt return summe % 10 == 0 # Summe muss durch 10 teilbar sein def test_iskonto(): assert(not iskonto("")) assert(not iskonto("a")) assert(not iskonto("69719a9107")) assert(not iskonto("69719917")) assert(not iskonto("723016699")) assert(iskonto("723016689")) assert(iskonto("697199107")) assert(iskonto("123456782")) assert(iskonto("12 345 6782")) print("test_iskonto() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def reverse_s(string): """liefert String in umgekehrter Reihenfolge zurück""" s = "" for c in string: s = c + s return s def test_reverse_s(): assert("" == reverse_s("")) assert("a" == reverse_s("a")) assert("ba" == reverse_s("ab")) assert("abc" == reverse_s("cba")) print("test_reverse() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def toupper(string): """liefert String in Großbuchstaben zurück""" s = "" for c in string: if 'a' <= c <= 'z': s += chr(ord(c) - ord('a') + ord('A')) elif c == 'ä': s += 'Ä' elif c == 'ö': s += 'Ö' elif c == 'ü': s += 'Ü' else: s += c return s def test_toupper(): assert("" == toupper("")) assert("A" == toupper("a")) assert("AB" == toupper("ab")) assert("ÄBC" == toupper("äbc")) assert("A" == toupper("a")) assert("AB" == toupper("Ab")) assert("ÄBC" == toupper("äBc")) print("test_toupper() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def tolower(string): """liefert String in Kleinbuchstaben zurück""" pass s = "" for c in string: if 'A' <= c <= 'Z': s += chr(ord(c) - ord('A') + ord('a')) elif c == 'Ä': s += 'ä' elif c == 'Ö': s += 'ö' elif c == 'Ü': s += 'ü' else: s += c return s def test_tolower(): assert("" == tolower("")) assert("a" == tolower("A")) assert("ab" == tolower("AB")) assert("äbc" == tolower("ÄBC")) assert("a" == tolower("A")) assert("ab" == tolower("Ab")) assert("äbc" == tolower("äBc")) print("test_tolower() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def isupper(string): """prüft, ob String nur Großbuchstaben enthält""" for c in string: if 'a' <= c <= 'z' or c in "äöü": # ein Kleinbuchstabe return False return True def test_isupper(): assert(isupper("")) assert(isupper("A")) assert(isupper("AEÄÖ")) assert(not isupper("a")) assert(not isupper("abcö")) assert(not isupper("AbC")) print("test_isupper() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def islower(string): """prüft, ob String nur Kleinbuchstaben enthält""" for c in string: if 'A' <= c <= 'Z' or c in "ÄÖÜ": # ein Großbuchstab return False return True def test_islower(): assert(islower("")) assert(islower("a")) assert(islower("aeöä")) assert(not islower("A")) assert(not islower("ABCÖ")) assert(not islower("AbC")) print("test_islower() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def ispalindrom(string): """Prüft, ob der String ein Palindrom ist (von vorne und hinten gelesen gleich).""" for i in range(len(string)): if string[i] != string[-1 - i]: return False return True def test_ispalindrom(): assert(ispalindrom("")) assert(ispalindrom("a")) assert(ispalindrom("aa")) assert(ispalindrom("aba")) assert(ispalindrom("abba")) assert(not ispalindrom("ab")) assert(not ispalindrom("abb")) assert(not ispalindrom("abab")) print("test_ispalindrom() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def ispalindrom_l(liste): """Prüft, ob die Liste von vorne und hinten gelesen gleich ist.""" return ispalindrom(liste) # sollte äquivalent sein! def test_ispalindrom_l(): assert(ispalindrom_l([])) assert(ispalindrom_l([1])) assert(ispalindrom_l([1, 1])) assert(ispalindrom_l([1, 2, 1])) assert(ispalindrom_l([1, 2, 2, 1])) assert(not ispalindrom_l([1, 2])) assert(not ispalindrom_l([1, 2, 2])) assert(not ispalindrom_l([1, 2, 1, 2])) print("test_ispalindrom_l() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def reverse_l(liste): """liefert die Liste in umgekehrter Reihenfolge zurück""" l = [] for e in liste: l = [e] + l return l def test_reverse_l(): assert([] == reverse_l([])) assert([1] == reverse_l([1])) assert([1, 2] == reverse_l([2, 1])) assert([1, 2, 3] == reverse_l([3, 2, 1])) print("test_reverse_l() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def sum(liste): """liefert die Summe aller Zahlen in der Liste""" summe = 0 for e in liste: summe += e return summe def test_sum(): assert(0 == sum([])) assert(12 == sum([12])) assert(12 == sum([4, 8])) assert(12 == sum([4, 4, 4])) print("test_sum() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def mittelwert(liste): """liefert den Mittelwert (Durchschnitt) aller Zahlen in der Liste""" if len(liste) > 0: return sum(liste) / len(liste) else: return 0 def test_mittelwert(): assert(0 == mittelwert([])) assert(1 == mittelwert([1])) assert(1.5 == mittelwert([1, 2])) assert(2 == mittelwert([2, 2, 2])) assert(2 == mittelwert([1, 2, 3])) print("test_mittelwert() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def rmdups(liste): """(ReMove DUPlicates) liefert Liste, aus der alle Vielfachen entfernt (hintereinander). Beispiele: [1, 2, 2, 2, 5, 2, 3, 2, 2, 23] -> [1, 2, 5, 2, 3, 2, 23] [99, 99, 23, 99, 99, 12, 2] -> [99, 23, 99, 12, 2] [] -> [] [1, 2, 4, 10] -> [1, 2, 4, 10]""" if len(liste) > 0: ret = [liste[0]] for e in liste: if ret[-1] != e: # letztes Element ungleich? ret.append(e) return ret else: return liste def test_rmdups(): assert([1, 2, 5, 2, 3, 2, 23] == rmdups([1, 2, 2, 2, 5, 2, 3, 2, 2, 23])) assert([99, 23, 99, 12, 2] == rmdups([99, 99, 23, 99, 99, 12, 2])) assert([] == rmdups([])) assert([1, 2, 4, 10] == rmdups([1, 2, 4, 10])) print("test_rmdups() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def isin(item, liste): """ist item in liste enthalten?""" for e in liste: if item == e: return True return False def rmalldups(liste): """(ReMove ALL DUPlicates) liefert Liste, aus der alle Vielfachen entfernt (müssen nicht hintereinander stehen). Beispiele: [1, 2, 2, 2, 5, 2, 3, 2, 2, 23] -> [1, 2, 5, 3, 23] [99, 99, 23, 99, 99, 12, 2] -> [99, 23, 12, 2] [] -> [] [1, 2, 4, 10] -> [1, 2, 4, 10]""" if len(liste) > 0: ret = [liste[0]] for e in liste: # if e not in ret: # schon vorhanden? if not isin(e, ret): ret.append(e) return ret else: return liste def test_rmalldups(): assert([] == rmalldups([])) assert([1, 2, 5, 3, 23] == rmalldups([1, 2, 2, 2, 5, 2, 3, 2, 2, 23])) assert([99, 23, 12, 2] == rmalldups([99, 99, 23, 99, 99, 12, 2])) assert([1, 2, 4, 10] == rmalldups([1, 2, 4, 10])) print("test_rmalldups() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def binsearch(liste, such): """liefert den Index von such in der sortierten Liste liste oder -1, wenn such in liste nicht vorkommt. Es ist die binäre Suche anzuwenden! """ first = 0 last = len(liste) - 1 mid = (last - first) // 2 + first #print(first, mid, last) while len(liste) > 0 and first <= last: if such < liste[mid]: last = mid - 1 elif such > liste[mid]: first = mid + 1 else: return mid #index found mid = (last - first) // 2 + first #print(first, mid, last) return -1 # not found def test_binsearch(): """static tests""" assert(binsearch([], 1) == -1) assert(binsearch([1], 2) == -1) assert(binsearch([1], 0) == -1) assert(binsearch([1], 1) == 0) assert(binsearch([1,3], 0) == -1) assert(binsearch([1,3], 2) == -1) assert(binsearch([1,3], 1) == 0) assert(binsearch([1,3], 3) == 1) assert(binsearch([1,3], 4) == -1) assert(binsearch([1,3,5], 2) == -1) assert(binsearch([1,3,5], 4) == -1) assert(binsearch([1,3,5], 1) == 0) assert(binsearch([1,3,5], 3) == 1) assert(binsearch([1,3,5], 5) == 2) assert(binsearch([1,3,5], 6) == -1) assert(binsearch([1,3,5,7], 0) == -1) assert(binsearch([1,3,5,7], 1) == 0) assert(binsearch([1,3,5,7], 3) == 1) assert(binsearch([1,3,5,7], 5) == 2) assert(binsearch([1,3,5,7], 7) == 3) assert(binsearch([1,3,5,7], 9) == -1) assert(binsearch([1,3,5,7], 2) == -1) assert(binsearch([1,3,5,7], 4) == -1) assert(binsearch([1,3,5,7], 6) == -1) import random for i in range(25): liste = [random.randint(0, 100) for i in range(100)] liste.sort() num = random.randint(0, 100) if num in liste: if binsearch(liste, num) < 0: print(liste) print("%d should be found in list" % num) assert(binsearch(liste, num) >= 0) else: if binsearch(liste, num) >= 0: print(liste) print("%d should not be found in list" % num) assert(binsearch(liste, num) < 0) print("test_binsearch() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def sumteilbar(liste, teiler): """Berechnet die Summe aller durch teiler teilbaren Zahlen der Liste""" summe = 0 for e in liste: if e % teiler == 0: summe += e return summe def test_sumteilbar(): assert(0 == sumteilbar([], 2)) assert(0 == sumteilbar([1], 2)) assert(0 == sumteilbar([1, 3], 2)) assert(0 == sumteilbar([1, 3, 23], 2)) assert(2 == sumteilbar([2], 2)) assert(2 == sumteilbar([1, 2], 2)) assert(2 == sumteilbar([1, 2, 23], 2)) assert(32 == sumteilbar([1, 8, 24], 2)) assert(27 == sumteilbar([3, 8, 24], 3)) print("test_sumteilbar() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def issorted(liste): """Prüft, ob die Liste sortiert ist, d.h. ob e1 <= e2 <= e3 <= ... <= en e1, e2, ... en sind die n Elemente der Liste mit Länge n""" for i in range(len(liste) - 1): if liste[i] > liste[i + 1]: return False return True def test_issorted(): assert(issorted([])) assert(issorted([1])) assert(issorted([1, 1])) assert(issorted([1, 3, 3, 4])) assert(not issorted([1, 0])) assert(not issorted([1, 2, 1])) print("test_issorted() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def printlxl(liste1, liste2): """gibt eine Multiplikationstabelle der beiden Listen aus. Zum Beispiel: a = [1, 2, 4, 5] b = [3, 2, 2] printlxl(a, b) gibt dann folgendes aus: 3 2 2 6 4 4 12 8 8 15 10 10 Die erste Liste bestimmt die Anzahl der Zeilen, die zweite die Anzahl der Spalten. Es wird immer ein Element der ersten Liste mit einem der zweiten Liste multipliziert. """ erg = lxl(liste1, liste2) for zeile in erg: for spalte in zeile: print("%4d" % spalte, end = "") print() def test_printlxl(): a = [1, 2, 4, 5] b = [3, 2, 2] printlxl(a, b) print("test_printlxl() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def lxl(liste1, liste2): """liefert eine Multiplikationstabelle der beiden Listen (Liste von Listen). Zum Beispiel: a = [1, 2, 4, 5] b = [3, 2, 2] lxl(a, b) liefert folgende Liste zurück: [[3, 2, 2], [6, 4, 4], [12, 8, 8], [15, 10, 10]] übersichtlich formatiert: [[3, 2, 2], [6, 4, 4], [12, 8, 8], [15, 10, 10]] Die erste Liste bestimmt die Anzahl der "Zeilen", die zweite die Anzahl der "Spalten". Es wird immer ein Element der ersten Liste mit einem der zweiten Liste multipliziert. """ erg = [] if len(liste2) > 0: for a in liste1: zeile = [] for b in liste2: zeile.append(a * b) erg.append(zeile) return erg def test_1x1(): a = [1, 2, 4, 5] b = [3, 2, 2] assert([[3, 2, 2], [6, 4, 4], [12, 8, 8], [15, 10, 10]] == lxl(a, b)) assert([] == lxl([], [])) assert([] == lxl([], [1, 2])) assert([] == lxl([1, 2], [])) print("test_1x1() ok") #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- # Testaufrufe: test_isint() test_isintb() test_sumdigits() test_horner() test_isipv4() test_anz_zahlen() test_sum_zahlen() test_iskonto() test_reverse_s() test_toupper() test_tolower() test_isupper() test_islower() test_ispalindrom() test_ispalindrom_l() test_reverse_l() test_sum() test_mittelwert() test_rmdups() test_rmalldups() test_binsearch() test_sumteilbar() test_issorted() test_printlxl() test_1x1()
Die Funktionen
isupper()
und islower()
sind eigentlich nicht korrekt, denn liefert z.B. isupper("A4C")
True
. Man müsste also eher schreiben:def isupper(string): """prüft, ob String nur Großbuchstaben enthält""" for c in string: if not ('A' <= c <= 'Z' or c in "ÄÖÜ"): return False return True
Labels: Lösung, POS1-1, Python
Sonntag, 6. März 2011
Übungsbeispiele zu Sequenzen, Schleifen und Funktionen in Python (POS1: 1B)
Hier finden Sie eine Reihe von Aufgabenstellungen als Übung zur nächsten praktischen Arbeit.
Gegeben sind minimale Funktionsrümpfe mit der Aufgabenstellung als DocString.
Die Funktionen sind ohne Standardmethoden bzw. Funktionen zu implementieren (ausgenommen die Funktion
Schreiben Sie zu den Funktionen jeweils passende Testprogramme.
Gegeben sind minimale Funktionsrümpfe mit der Aufgabenstellung als DocString.
Die Funktionen sind ohne Standardmethoden bzw. Funktionen zu implementieren (ausgenommen die Funktion
len()
). Sollte es eine Standardfunktion zur Lösung der Aufgabe geben, verwenden Sie diese, um das Ergebnis zu prüfen. Bereiche ([von:bis]
) dürfen verwendet werden, sofern sie benötigt werden.def isint(string) """prüft, ob der String eine ganze Zahl ist (Vorzeichen optional, nur Ziffern)""" pass
def isintb(string, basis) """prüft, ob der String eine ganze Zahl zur Basis basis ist (Vorzeichen optional, nur Ziffern)""" pass
def isnum(string) """prüft, ob der String eine Zahl ist (Vorzeichen optional, Ziffern und Komma)""" pass
def horner(zahl, basis): """berechnet Dezimalzahl aus zahl (String) zur Basis basis. liefert Zahl.""" pass
def sumdigits(zahl): """Berechnet die Ziffernsumme aus der gegebenen Zahl (int)""" pass
def sumdigits_s(string): """Berechnet die Ziffernsumme aus der gegebenen Zahl (str), wenn es überhaupt eine Zahl ist. Liefert -1, wenn keine gültige Zahl""" pass
def isipv4(string): """Prüft, ob der gegebene String eine IPv4-Adresse enthält. IPv4-Adressen sind 4 Zahlen zwischen 0 und 255, die durch einen Punkt getrennt sind. Beispiele: 127.0.0.1, 193.170.149.129, 81.200.64.185 Ungültige: 81.2010.64.185, 123.23.12, 127,0,0,1""" pass
def anz_vokale(string): """Zähle die Selbstlaute im String und liefere Anzahl zurück""" pass
def anz_zahlen(string): """ermittelt die Anzahl der ganzen Zahlen im String. Eine Zahl ist eine ununterbrochene Folge von Ziffern. Beispiel: anz_zahlen("x 34 3 12k33 44 hallo 23") liefert 6""" pass
def sum_zahlen(string): """ermittelt die Summe der ganzen Zahlen im String. Eine Zahl ist eine ununterbrochene Folge von Ziffern. Beispiel: anz_zahlen("x 34 3 12k33 44 hallo 23") liefert 149""" pass
def iskonto(string): """Prüft, ob der String eine gültige Kontonummer enthält. Dabei gelten folgende Regeln: 1. genau 9 Ziffern (es dürfen Leerzeichen dazwischen sein 2. die letzte Ziffer ist eine Prüfziffer und es gilt Die Kontonummer ist genau 9 Stellen lang und ist dann richtig, wenn die folgendermaßen gebildete Summe auf Null endet: Ziffern mit ungeradem Index werden addiert(=Teilsumme1); Ziffern mit geradem Index werden verdoppelt und das jeweilige Produkt addiert, wenn es einstellig ist, andernfalls wird die Quersumme des Produkts addiert(=Teilsumme2); Summe= teilsumme1 + Teilsumme2 Beispiel: 123456782 1+ 3+ 5+ 7+ 2 = 18 Teilsumme1 2*2+ 4*2+ (1+2)+ (1+6) = 22 Teilsumme2 6*2=12 8*2=16 ------ 40 Summe mod 10= Null Beispiele für Kontonummern: 697199107 richtige Kontonummer 723016699 falsche Kontonummer """ pass
def reverse_s(string): """liefert String in umgekehrter Reihenfolge zurück""" pass
def toupper(string): """liefert String in Großbuchstaben zurück""" pass
def tolower(string): """liefert String in Kleinbuchstaben zurück""" pass
def isupper(string): """prüft, ob String nur Großbuchstaben enthält""" pass
def islower(string): """prüft, ob String nur Kleinbuchstaben enthält""" pass
def ispalindrom(string): """Prüft, ob der String ein Palindrom ist (von vorne und hinten gelesen gleich).""" pass
def ispalindrom_l(liste): """Prüft, ob die Liste von vorne und hinten gelesen gleich ist.""" pass
def reverse_l(liste): """liefert die Liste in umgekehrter Reihenfolge zurück""" pass
def sum(liste): """liefert die Summe aller Zahlen in der Liste""" pass
def mittelwert(liste): """liefert den Mittelwert (Durchschnitt) aller Zahlen in der Liste""" pass
def rmdups(liste): """(ReMove DUPlicates) liefert Liste, aus der alle Vielfachen entfernt (hintereinander). Beispiele: [1, 2, 2, 2, 5, 2, 3, 2, 2, 23] -> [1, 2, 5, 2, 3, 2, 23] [99, 99, 23, 99, 99, 12, 2] -> [99, 23, 99, 12, 2] [] -> [] [1, 2, 4, 10] -> [1, 2, 4, 10]""" pass
def rmalldups(liste): """(ReMove ALL DUPlicates) liefert Liste, aus der alle Vielfachen entfernt (müssen nicht hintereinander stehen). Beispiele: [1, 2, 2, 2, 5, 2, 3, 2, 2, 23] -> [1, 2, 5, 3, 23] [99, 99, 23, 99, 99, 12, 2] -> [99, 23, 12, 2] [] -> [] [1, 2, 4, 10] -> [1, 2, 4, 10]""" pass
def binsearch(liste, such): """liefert den Index von such in der sortierten Liste liste oder -1, wenn such in liste nicht vorkommt. Es ist die binäre Suche anzuwenden! """ pass
def sumdigits(zahl): """Berechnet die Ziffernsumme aus der gegebenen Zahl (int)""" pass
def sumteilbar(liste, teiler): """Berechnet die Summe aller durch teiler teilbaren Zahlen der Liste""" pass
def issorted(liste): """Prüft, ob die Liste sortiert ist, d.h. ob e1 <= e2 <= e3 <= ... <= en e1, e2, ... en sind die n Elemente der Liste mit Länge n""" pass
def printlxl(liste1, liste2): """gibt eine Multiplikationstabelle der beiden Listen aus. Zum Beispiel: a = [1, 2, 4, 5] b = [3, 2, 2] printlxl(a, b) gibt dann folgendes aus: 3 2 2 6 4 4 12 8 8 15 10 10 Die erste Liste bestimmt die Anzahl der Zeilen, die zweite die Anzahl der Spalten. Es wird immer ein Element der ersten Liste mit einem der zweiten Liste multipliziert. """ pass
def lxl(liste1, liste2): """liefert eine Multiplikationstabelle der beiden Listen (Liste von Listen). Zum Beispiel: a = [1, 2, 4, 5] b = [3, 2, 2] lxl(a, b) liefert folgende Liste zurück: [[3, 2, 2], [6, 4, 4], [12, 8, 8], [15, 10, 10]] übersichtlich formatiert: [[3, 2, 2], [6, 4, 4], [12, 8, 8], [15, 10, 10]] Die erste Liste bestimmt die Anzahl der "Zeilen", die zweite die Anzahl der "Spalten". Es wird immer ein Element der ersten Liste mit einem der zweiten Liste multipliziert. """ pass
Schreiben Sie zu den Funktionen jeweils passende Testprogramme.
Labels: Aufgabe, POS1-1, Python
Freitag, 4. März 2011
SAR (ROB: 2C)
SAR steht normalerweise für "Search and Rescue" - hier soll es "Search and Remove" heißen.
Ein Roboter soll in einem hellen rechteckigen Feld, das mit einer schwarzen Linie umgeben ist, einen Klotz finden und auf einer dunklen (schwarzen) Fläche in einem der Ecken abstellen. Das Feld sieht etwa so aus:
Finden Sie eine geeignete Strategie, den Klotz aufzuspüren.
Wie kann der Klotz transportiert werden?
Wie findet man die markierte Ecke (Fläche) zum Ablegen?
Ein Roboter soll in einem hellen rechteckigen Feld, das mit einer schwarzen Linie umgeben ist, einen Klotz finden und auf einer dunklen (schwarzen) Fläche in einem der Ecken abstellen. Das Feld sieht etwa so aus:
Finden Sie eine geeignete Strategie, den Klotz aufzuspüren.
Wie kann der Klotz transportiert werden?
Wie findet man die markierte Ecke (Fläche) zum Ablegen?
Java Übungen und Aufgabe (POS1: 2A, 2C)
Klassen, Objekte
Erzeugen Sie eine KlasseSomeMaths
, welche eine statische Konstante PI
enthält sowie eine statische Methode double getSquare(double x)
, welche das Quadrat von x
liefert.Erstellen Sie weiters eine Klasse
Circle
, welche eine Kreis simuliert. Circle
hat ein Attribut radius
sowie die Methoden getCircumference()
, welche den Umfang liefert, und getArea()
, welche die Fläche berechnet. Die Methoden sollen sich der Konstante PI
und der Methode getSquare()
von SomeMaths
bedienen.Eine dritte Klasse
CircleExercise
soll im main()
drei Kreise vom Typ Circle
erzeugen und jeweils den Radius, den Umfang und die Fläche ausgeben.Das UML-Diagramm sieht etwa so aus:
Arrays
Erzeugen Sie eine KlasseDreieckArray
, welche ein privates zweidimensionales Array feld
für Integers enthält. Dieses Feld soll "dreieckig" sein und mit folgenden Werten initialisiert werden:1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1
Die Methoden sind public und sollen folgendes tun:
void create(int zeilen, int spalten)
soll ein neues Feld mit den gegebenen Zeilen und Spalten erzeugen (rechteckig).int[][] getArray()
soll das Feld zurückliefern.int[] summen()
soll ein eindimensionales Feld mit den Zeilensummen liefern.boolean set(int zeile, int spalte, int wert)
soll den Wert an der gegebenen Stelle im Feld feld setzen und bei erfolg true zurückliefern. Bei ungültigen Indizes soll false zurückgeliefert werden.Schreiben Sie eine Klasse
TestDreieckArray
, in der zwei Objekte von DreieckArray in der Methode main()
angelegt werden. Machen Sie zum Testen passende Aufrufe der Methoden (z.B. gültige und ungültige set()
usw.).Streams, Strings
Schreiben Sie eine KlasseReadFile
, welche eine eine auf der Kommandozeile angegebene Datei öffnet und in einen String einliest. Verwenden Sie dazu drei Methoden String liesString(InputStream fileInputStream)
, String liesStringBuffer(InputStream fileInputStream)
und String liesStringBuilder(InputStream fileInputStream)
und messen Sie die Zeiten, die mit den einzelnen Methoden benötigt werden um die Datei zu lesen.Von der Datei soll jeweils mit
read()
ein Zeichen gelesen werden. Die Methode liesString()
hängt das gelesene Zeichen jeweils an einen String an, die Methode liesStringBuffer()
verwendet einen StringBuffer
und liesStringBuilder()
verwendet einen StringBuilder
. Das gelesene Zeichen wird dann immer mit append()
an den StringBuffer
bzw. StringBuilder
angehängt.Testen Sie mit unterschiedlich großen Dateien (kleine, mittlere, große, ganz große). Sie werden unterschiedliche Zeiten messen bei den verschiedenen Methoden. Erklären Sie die Unterschiede!
Verwenden Sie
System.currentTimeMillis()
(liefert long
), um die aktuelle Zeit in ms zu erhalten.Random, Calendar, Kommandozeile, Streams
Es sollen Testdaten der FormDatum Von-Zeit Bis-Zeit Datum Von-Zeit Bis-Zeit ...erzeugt werden. Wobei ein Datum die Form
JJJJ-MM-TT
und Von-Zeit und Bis-Zeit die Form HH:MM
haben soll. Weiters sollen folgende Bedingungen erfüllt sein:- Verwenden Sie
java.util.Random
um die Testdaten zu bekommen. - Bis-Zeit soll immer nach Von-Zeit kommen (also später)
- Eine Zeile mit Datum, Von-Zeit und Bis-Zeit soll immer nach jenem Zeitbereich der vorhergehenden Zeile kommen (die Zeiten sind also sortiert).
- Zwischen zwei Zeilen sollen nicht mehr als 36 Stunden liegen (Bis-Zeit bis Von-Zeit)
2011-03-04 10:24 10:45 2011-03-04 11:33 12:56 2011-03-05 12:33 17:23
Das Programm soll folgendermaßen aufgerufen werden:
java CalenderTest [-h] [startdatum] [startzeit] [datei] anzahl -h ... Ausgabe dieser Hilfe und Ende startdatum ... JJJJ-MM-TT (optional) startzeit ... HH:MM (optional) datei ... Name der Ausgabedatei (optional) anzahl ... Anzahl der zu erzeugenden ZeilenWird kein
startdatum
angegeben, so ist der heutige Tag als Startwert zu verwenden.Wird kein
startzeit
angegeben, so ist die aktuelle Uhrzeit als Startwert zu verwenden. Diese Startwerte sind in der ersten Ausgabezeile zu sehen.Wenn kein Dateiname
datei
angegeben, so ist die Standardausgabe zu verwenden.Die Anzahl der zu erzeugenden Zeilen muss mindestens 1 sein!
Fehlermeldungen sind auf
System.err
auszugeben.Nennen Sie das Projekt
calendertest
(klasse-name-calendertest
).Mittwoch, 2. März 2011
Prüfen Sie Ihr Wissen (POS1: 2A, 2C)
Sie finden an dieser Stelle eine Reihe von Fragen und Aufgaben, die Sie etwa Mitte des zweiten Jahrgangs Informatik beantworten bzw. lösen können sollten.
Theorie
In diesem Blog und auch im alten Blog gibt es bereits eine Reihe von Aufgaben. Vergleichen Sie Ihre Lösungen mit jenen Ihrer MitschülerInnen.
Hier noch ein paar "Grundübungen":
Theorie
- Was ist ein Dictionary in Python?
- Was bedeutet der Begriff "Sequenz" in Python? Geben Sie einige Beispiele.
- Wie wird eine Funktion in Python definiert?
- Welche Arten der Parameterübergabe gibt es in Python?
- Wie kann eine Python-Funktion mehr als einen Wert (Parameter) ändern bzw. zurückliefern?
- Geben Sie ein Beispiel für eine kürzest mögliche Funktion in Python an!
- Was ist eine Variable?
- Was versteht man unter "Duck Typing"?
- Wie werden in Python for-Schleifen gebildet?
- Was ist ein Python-Modul? Wofür werden Module verwendet?
- Wie kann eine (Text-)Datei gelesen werden?
- Wie kann man in Python Kommandozeilenparameter auswerten?
- Welche Grunddatentypen kennen Sie? Geben Sie auch den Speicherbedarf und den Wertebereich an.
- Was versteht man unter den Eigenschaften eines Objekts? Wie spiegelt sich das in einer Klasse wieder?
- Welche Kontrollstrukturen kennen Sie?
- Was ist ein Array?
- Geben Sie ein Beispiel eines eindimensionalen Arrays in Java an.
- Wie kann man ein eindimensionales Array in Java initialisieren?
- Geben Sie ein Beispiel eines zweidimensionalen Arrays in Java an.
- Wie kann man ein zweidimensionales Array in Java initialisieren?
- Kann man in Java ein zweidimensionales Array definieren, welches "nicht rechteckig" (rechteckig bedeutet hier: alle Zeilen gleich lang) ist?
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um alle Elemente eines eindimensionalen Arrays zu ermitteln, die ein bestimmtes Kriterium (z.B. ist größer als ein bestimmter Wert) erfüllen.
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um alle Elemente eines zweidimensionalen Arrays zu ermitteln, die ein bestimmtes Kriterium erfüllen.
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Maximum aller Werte eines eindimensionalen Arrays zu ermitteln.
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Minimum aller Werte eines eindimensionalen Arrays zu ermitteln.
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Maximum aller Werte eines zweidimensionalen Arrays zu ermitteln.
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um das Minimum aller Werte eines zweidimensionalen Arrays zu ermitteln.
- Was ist eine Funktion? Geben Sie ein Beispiel in Java inklusive der Verwendung der Funktion.
- Was ist eine Methode? Geben Sie ein Beispiel in Java inklusive der Verwendung der Funktion.
- Was ist der Unterschied zwischen einer Variable eines Grunddatentyps und einer Variable vom Typ einer Klasse?
- Was ist eine Klasse?
- Was ist ein Objekt? Erklären Sie den Zusammenhang zwischen Objekt und Klasse.
- Was sind Strings?
- Wie kann man Strings vergleichen?
- Wozu benötigt man Kommentare?
- Wozu benötigt man Programmierrichtlinien?
- Vergleichen Sie Java mit Python.
- Woran soll Sie die Geschichte "Shlemiel the Painter" erinnern?
- Was muss grundsätzlich (ohne Programmdetails) gemacht werden, um von einer Datei zu lesen?
- Was muss grundsätzlich (ohne Programmdetails) gemacht werden, um in eine Datei zu schreiben?
- Geben Sie einen Algorithmus (ohne Programmdetails) an, um alle Zeilen einer Textdatei zu ermitteln, die ein bestimmtes Kriterium (z.B. enthält einen bestimmten String) erfüllen.
- Welche Arten von Programm(ier)fehlern kennen Sie? Wie findet man diese Fehler?
- Wieviele
main()
-Methoden muss eine Java-Klasse besitzen? - Wieviele
main()
-Methoden kann eine Java-Klasse maximal haben? - Wieviele Klassen können in einer einzelnen Java-Datei implementiert werden?
- Welchen Wert hat die Variable
einInteger
? Begründen Sie Ihre Antwort!int einInteger = Integer.MAX_VALUE + 1;
- Was versteht man unter impliziter bzw. expliziter Typumwandlung? Nennen Sie jeweils mindestens ein Beispiel.
In diesem Blog und auch im alten Blog gibt es bereits eine Reihe von Aufgaben. Vergleichen Sie Ihre Lösungen mit jenen Ihrer MitschülerInnen.
Hier noch ein paar "Grundübungen":
- Erstellen Sie ein Pythonprogramm, welches das Maximum einer Sequenz ermittelt. Definieren Sie dazu eine fixe Testsequenz mit folgenden Werten
[-1, -23, -2, -32,-89, -100, -1, -99]
. Finden Sie weitere Beispieltestdaten. - Erstellen Sie ein Pythonprogramm, welches das Minimum einer Sequenz ermittelt. Definieren Sie dazu eine fixe Testsequenz mit folgenden Werten
[1, 23, 2, 32, 89,100, 1, 99]
. Finden Sie weitere Beispieltestdaten. - Erstellen Sie ein Javaprogramm, welches das Maximum einer Sequenz ermittelt. Definieren Sie dazu eine fixe Testsequenz mit folgenden Werten
[-1, -23, -2, -32,-89, -100, -1, -99]
. Finden Sie weitere Beispieltestdaten. - Erstellen Sie ein Javaprogramm, welches das Minimum einer Sequenz ermittelt. Definieren Sie dazu eine fixe Testsequenz mit folgenden Werten
[1, 23, 2, 32, 89,100, 1, 99]
. Finden Sie weitere Beispieltestdaten. - Erstellen Sie ein Pythonprogramm, welches die Häufigkeit von Elementen einer Sequenz (Liste) ermittelt. Definieren Sie dazu eine Testsequenz mit folgenden Werten
[1, 2,-3, 4, 2, 1, 10, -3, 4, 2, 2, 10]
bzw.["hallo", "du", "test", "du","Maus", "test", "Test"]
. Das Ergebnis soll eine Liste von unterschiedlichen Werten sein und wie oft sie vorkommen. - Betrachten Sie die Methode
dividiere
im folgenden Programm. lässt sich das Programm übersetzen? Falls nicht, dann korrigieren Sie die Fehler:
public class DivisionApp { public static void main(String[] args) { int ergebnis = dividiere(40, 5); System.out.println("Ergebnis: " + ergebnis); } public static int dividiere(int divident, int divisor) { if (divisor > 0) { return divident / divisor; } } }
- Folgende Ausgabe soll erzeugt werden:
1 3 5 7 9
. Lösen Sie die Aufgabe- mithilfe einer
while
-Schleife - mithilfe einer
do-while
-Schleife - mithilfe einer
for
-Schleife und des Modulo-Operators - mithilfe einer
for
-Schleife ohne den Modulo-Operator
- mithilfe einer
- Folgende Ausgabe soll erzeugt werden:
1 2 4 7 11 16 22 29 37
. Lösen Sie die Aufgabe- mithilfe einer
do-while
-Schleife - mithilfe einer
for
-Schleife
- mithilfe einer
- Schreiben Sie ein Java-Programm, welches mithilfe eines Stacks folgende Werte in umgekehrter Reihenfolge ausgibt:
23 21 20 18 17 13 11 5 3
- Schreiben Sie ein Java-Programm, welches mithilfe einer Queue folgende Werte in derselben Reihenfolge ausgibt:
23 21 20 18 17 13 11 5 3
- Schreiben Sie auf Basis der letzten beiden Beispiele Programme, die Strings statt der Integer-Werte verwenden können.
Labels: allgemeines, Aufgabe, Java, POS1-2, Python
Klammerprüfung mittels Stack (POS1: 2A, 2C)
Schreiben Sie ein Java-Programm, welches zeichenweise von der Standardeingabe liest und prüft, ob die eingegebenen Klammern eine gültige Klammerung mit
Beispiele für korrekte Klammerung:
Beispiele für falsche Klammerung:
Das Programm soll nur ausgeben, ob die Klammerung korrekt ist. Das Programm soll alle Klammern bis
Verwenden Sie für die Implementierung einen (selbstprogrammierten) Stack (eigene Klasse):
Erweitern Sie das Programm so, dass eine Hilfe ausgegeben werden kann, mehrere Eingabedateien und optional eine Ausgabedatei angegeben werden kann. Eine Eingabedatei entspricht einem Klammerausdruck (der natürlich aus mehreren Zeilen bestehen kann). Wird keine Eingabedatei angegeben, so ist von
Aufruf:
Erweitern Sie das Programm um die Ausgabe einer detaillierten Fehlermeldung. Welcher Fehler wurde gefunden? Wo wurde der Fehler gefunden (Zeile/Spalte)?
mögliche Fehler
([{}])
ergeben.Beispiele für korrekte Klammerung:
()([])[[([])]]{} x{abc(sdf(c))asd}asx () [] ((())) {{{(())}}}
Beispiele für falsche Klammerung:
(() []) (([)])
Das Programm soll nur ausgeben, ob die Klammerung korrekt ist. Das Programm soll alle Klammern bis
EOF
prüfen (bei den Beispielen oben ist jeweils eine Zeile eine Eingabe!).Verwenden Sie für die Implementierung einen (selbstprogrammierten) Stack (eigene Klasse):
void push(char elem); // Element oben auf Stack char pop(); // oberstes Element boolean isEmpty(); // false wenn nicht leer
Erweiterung um Programmargumente und Dateien
Erweitern Sie das Programm so, dass eine Hilfe ausgegeben werden kann, mehrere Eingabedateien und optional eine Ausgabedatei angegeben werden kann. Eine Eingabedatei entspricht einem Klammerausdruck (der natürlich aus mehreren Zeilen bestehen kann). Wird keine Eingabedatei angegeben, so ist von
stdin
zu lesen.Aufruf:
java Klammer [-h|-o out] [eingabedateien...] -h ... Hilfe -o out ... Ausgabe in die Datei out eingabedateien ... optional mehrere Eingabedateien
Detaillierte Fehlermeldungen
Erweitern Sie das Programm um die Ausgabe einer detaillierten Fehlermeldung. Welcher Fehler wurde gefunden? Wo wurde der Fehler gefunden (Zeile/Spalte)?
mögliche Fehler
falsche Klammer-Zuzu viele Klammern-Zuzu wenig Klammern-Zu
Dienstag, 1. März 2011
Binärdateien bearbeiten mit Java (PR: 5A, 5B)
Entwickeln Sie sie eine Klasse
Der Parameter
Die Datensatznummer
Gelöschte Datensätze werden einfach als gelöscht markiert (s.u.) und müssen beim Anlegen neuer Datensätze zuerst verwendet werden (erst wenn kein gelöschter Datensatz existiert, wird die Datei vergrößert).
Datensätze sollen gesperrt werden können (die Klasse
Die Strings sind kodiert mit dem Encoding ISO-8859-1, d.h. jedes Zeichen ist einem Byte kodiert und es sind nur ASCII-Zeichen sowie die westeuropäischen Erweiterungen erlaubt. Es gibt Strings fixer Länge (werden mit Leerzeichen aufgefüllt) und Strings variabler Länge (werden wie C-Strings mit
Die Datei mit den (Test-)Daten hat folgendes Format:
Die Datei beginnt mit einem Header:
Diese Datei enthält nur die Geräte (und deren grafische Koordinaten):
Schreiben Sie passende Tests um die Klasse
Die weiteren Tests sollen natürlich die gesamte Funktionalität und das Locking testen.
Nennen Sie das Projekt
Die Datenklasse soll dann später in einem Client-/Server-System zum Einsatz kommen, wo mehrere grafische Clients eine Binärdatei bearbeiten sollen. Die Angabe dazu folgt...
Data
, die das Interface DB
implementiert. Die Klasse Data
soll die Methoden zum Bearbeiten (Lesen, Schreiben) binärer Dateien nach dem unten beschriebenen Datenformat bereitstellen.package data; /** * RuD-Übung 2011 * * data.DB.java * @author (c) 2011, Harald R. Haberstroh * 1.3.2011 */ import java.rmi.Remote; import java.rmi.RemoteException; /** * @author Harald R. Haberstroh (hh) * */ public interface DB extends Remote { /** * Sperre den gegebenen Datensatz. Ist der Datensatz bereits gesperrt, dann * wait(). * * @param recNo * Nummer des zu sperrenden Datensatzes. * @return Sperr-Identifikation. * @throws RemoteException * @throws RecordNotFoundException * ungültige Datensatznummer */ public long lock(int recNo) throws RemoteException, RecordNotFoundException; /** * Hebe Sperre wieder auf. notify(). * * @param recNo * Nummer des gesperrten Datensatzes * @param lockCookie * Sperr-Identfikation. * @throws RemoteException * @throws RecordNotFoundException * ungültige Datensatznummer * @throws SecurityException * ungültiges lockCookie oder nicht gelockt */ public void unlock(int recNo, long lockCookie) throws RemoteException, RecordNotFoundException, SecurityException; /** * lege neuen Datensatz an. * * @param record * Neuer Datensatz * @return Nummer des neuen Datensatzes * @throws RemoteException */ public int create(Record record) throws RemoteException; /** * lösche Datensatz. Sperre wird aufgehoben, notify(); * * @param recNo * Nummer des Datensatzes. * @param lockCookie * Sperr-Identfikation. * @throws RemoteException * @throws RecordNotFoundException * ungültige Datensatznummer * @throws SecurityException * ungültiges lockCookie oder nicht gelockt */ public void delete(int recNo, long lockCookie) throws RemoteException, RecordNotFoundException, SecurityException; /** * ändere Datensatz (überschreibe mit dem gegebenen Datensatz). * * @param record * neuer Datensatz * @param recNo * Nummer des gesperrten Datensatzes * @param lockCookie * Sperr-Identfikation. * @throws RemoteException * @throws RecordNotFoundException * ungültige Datensatznummer * @throws SecurityException * ungültiges lockCookie oder nicht gelockt */ public void update(Record record, int recNo, long lockCookie) throws RemoteException, RecordNotFoundException, SecurityException; /** * suche Datensätze. * * @param criteria * String-Array mit Kriterien, null matcht alles, sonst * Stringrepräsentation des Suchkriteriums (entspricht den Daten in * Record). * @return Array von Recordnummern * @throws RemoteException */ public int[] find(String[] criteria) throws RemoteException; /** * lese Datensatz. * * @param recNo * Nummer des zu lesenden Datensatzes. * @return Record * @throws RemoteException * @throws RecordNotFoundException * Datensatz existiert nicht. */ public Record read(int recNo) throws RemoteException, RecordNotFoundException; }Die Klasse Data muss zusätzlich einen Konstruktor
Data(String dateiname)
bereitstellen, der die Datei dateiname (z.B. "machines.db"
) öffnet und zur Bearbeitung mit den im Interface DB
definierten Methoden bereitstellt. Der Konstruktor muss die nötigen Exceptions werfen, wenn die Datei nicht geöffnet werden kann.Der Parameter
String[] criteria
der Methode find()
enthält das Suchkriterium, wobei jedem Feld ein String zugeordnet ist. Soll also nur nach einem Namen (siehe unten) gesucht werden, so muss criteria[1]
den gesuchten Namen (bzw. einen Teil davon) enthalten. Alle anderen Elemente des Arrays müssen dann null
sein. Soll nach mehreren Kriterien selektiert werden, so sind die entsprechenden Felder mit Werten zu belegen.find()
liefert dann ein Array mit den Indizes der passenden Datensätze.Die Datensatznummer
recNo
ist immer der Index innerhalb der Datei!Gelöschte Datensätze werden einfach als gelöscht markiert (s.u.) und müssen beim Anlegen neuer Datensätze zuerst verwendet werden (erst wenn kein gelöschter Datensatz existiert, wird die Datei vergrößert).
RecordNotFoundException
wird immer dann geworfen, wenn recNo
auf einen gelöschten Datensatz weist oder, wenn der Datensatz gar nicht existiert. Lösen Sie das Problem, dass nur mit der einfachen RecordNotFoundException
das Dateiende nicht ermittelt werden kann, in geeigneter Weise.Record
muss in geeigneter Weise implementiert werden.Datensätze sollen gesperrt werden können (die Klasse
Data
kann von mehreren parallelen Threads verwendet werden). Dazu soll die Methode lock()
eine (beliebige) dem Datensatz zuordenbare Zahl (Lockcookie bzw. Sperr-Identifikation) liefern und den Satz sperren. Die Methoden, die eine Sperre benötigen müssen dann anhand dieses Lockcookies überprüfen, ob der Datensatz gesperrt ist und die entsprechende Operation ausführen. Ist der Datensatz nicht gesperrt oder das Lockcookie ungültig, so ist eine SecurityException
zu werfen. Die Methode unlock()
hebt die Sperre wieder auf. Nach einem delete()
braucht man (kann man) kein unlock()
machen.Datenformat
Die Strings sind kodiert mit dem Encoding ISO-8859-1, d.h. jedes Zeichen ist einem Byte kodiert und es sind nur ASCII-Zeichen sowie die westeuropäischen Erweiterungen erlaubt. Es gibt Strings fixer Länge (werden mit Leerzeichen aufgefüllt) und Strings variabler Länge (werden wie C-Strings mit
'\0'
abgeschlossen) mit einer Obergrenze.Die Datei mit den (Test-)Daten hat folgendes Format:
Die Datei beginnt mit einem Header:
4 Bytes Magic Cookie, Wert 4242 4 Offset in Bytes zu den eigentlichen Daten 2 Bytes Anzahl Felder pro Datensatz Pro Feld gibt es folgenden Eintrag: 2 Bytes Länge Feldname n Bytes Feldname 2 Bytes Länge Feldbeschreibung n Bytes Feldbeschreibung für die Tabellenansicht 1 Byte Datentyp: 'F' ... fix, 'V' ... variabel, 'C' ... ein Zeichen 2 Bytes Feldlänge Nach den Feldbeschreibungen, d.h. ab dem Offset, finden sich die eigentlichen Datensätze gemäß der Beschreibungen im Header: 2 Bytes Flag Gelöscht (== 0 ... gelöscht, != 0 ... aktiv) n Bytes Daten gemäß der Datensatzbeschreibung
Testdatei machines.db
Diese Datei enthält nur die Geräte (und deren grafische Koordinaten):
Feldname | Feldbeschreibung | (maximale) Länge | Typ | Bemerkung |
id | Geräte-Id | 10 | String '\0' terminiert | z.B. "z23" |
name | Gerätename | 100 | String '\0' terminiert | Gerätebeschreibung, z.B. "Laderoboter Halle B" |
x | x | 5 | String fixe Länge | z.B. " 50" (vorne mit Leerzeichen aufgefüllt) |
y | y | 5 | String fixe Länge | z.B. " 200" |
Testen der Klasse Data
Schreiben Sie passende Tests um die Klasse
Data
zu testen. Der erste Test soll einfach die Datei machines.db
in lesbarer Form auf der Konsole ausgeben.Die weiteren Tests sollen natürlich die gesamte Funktionalität und das Locking testen.
Downloads
- Interface DB.java
- Testdatei machines.db
Abgabe
Nennen Sie das Projekt
klasse-name-data
also z.B. 5ad-meier-data
und checken Sie es am CVS ein. Termin wird noch bekanntgegeben.Wie geht's weiter
Die Datenklasse soll dann später in einem Client-/Server-System zum Einsatz kommen, wo mehrere grafische Clients eine Binärdatei bearbeiten sollen. Die Angabe dazu folgt...
Abonnieren Posts [Atom]