--------------------------[ das package Wider ]----------------------- -------[ i] inhalt 0. [ einleitung ] 1. [ Main ] 2. [ ReNe ] 2.1 < syntaxCheck() > 2.2 < solve() > 2.3 < find() > 2.4 < before() > 2.5 < after() > 3. [ ReNeX ] appendix a: beispiel zum verstaendnis appendix b: zusammenfassung der spezifikation -------[ 0.] einleitung ich werde mich in der dokumentation darauf beschraenken, nur das konzept hinter dem sourcecode zu erklaeren. eigene methoden werden natuerlich erklaert, sollten unklarheiten bei anderen methoden (z.b.: String.substring(), ...) auftreten bitte ich in der java2api dokumentation nachzuschlagen (z.b. auf www.inflab.tuwien.ac.at/eprog/). da rekursive algorithmen manchmal schwer nachzuvolziehen sind habe ich in appendix a ein beispiel angefuehrt. sollten sich weitere fragen auftun, bin ich unter patrick.k@rocketmail.com oder im icq netzwerk unter der uin 55690660 erreichbar. -------[ 1.] Main in der for-schleife am anfang wird ueberprueft, ob einer der parameter "--no-eprog" war. wenn ja gibt das programm ausfuehrlichere fehlermeldungen als "FALSCHE EINGABE". die methode syntaxCheck() testet den eingabestring auf fehler. die methode solve() liefert den gesamtwiederstand als double-wert zurueck. Math.round() rundet das ergebnis, dieses wird in einen int gecastet und von EprogIO ausgegeben. tritt eine REsistorNEtworkeXception auf (von syntaxCheck(), oder solve()) auf, wird die fehlermeldung ausgegeben. -------[ 2.] ReNe REsistorNEtwork die klasse ReNe stellt die methoden syntaxCheck() und solve() zur verfuegung. die methode solve() ist zwar das herzstueck des package, aber sie wird hier am ende beschrieben, weil sie auf den anderen drei methoden aufbaut. ---< 2.1> syntaxCheck() jedesmal wenn eine klammer geoeffnet wird, wird die variable brackets um eins erhoet, wir eine klammer geschlossen wird brackets um eins verringert. sollte zu irgendeinem zeitpunkt brackets negativ sein, wurde eine klammer geschlossen, die garnicht geoeffnet wurde. ist am ende des strings, brackets ungleich null, wurde eine klammer geoeffnet, aber nicht mehr geschlossen. jedesmal wenn ein operator ('+', '/') gefunden wird, wird lastWasOperator auf true gesetzt. wird ein operator gefunden waerend diese variable true ist, stehen zwei operatoren hintereinander. wird eine klammer zugemacht und die variable ist true, steht direkt vorher ein operator. wurde der ganze string durchlaufen und die variabel ist true, steht ganz am ende des strings ein operator. und diese beiden faelle sind natuerlich nicht zulaessig. weisters wird bei jedem auftreten eines operators ein zaehler um eins erhoeht. wenn eprog- einschraenkungen gewuenscht sind, wird abgebrochen sobald 15 operatoren gefunden wurden. fuer die eingabe sind nur die zeichen "0123456789+/()" erlaubt. wird ein anderes zeichen gefunden, loest das switch-statement eine exception aus. ---< 2.2> find() diese methode durchsucht einen String nach einem zeichen. sie ignortiert allerdings alle zeichen in klammernausdruecken. wird eine oeffnende klammer gefunden wird ein zaehler um eins erhoeht, bei einer schlieszenden klammer um eins gesenkt (puh, deja-vu). nur wenn der zaehler auf null ist, wird das zeichen ueberhaupt gesucht. zurueckgegeben wird die position, an der das zeichen gefunden wurde oder 0 wenn nichts gefunden wurde. ---< 2.3> before() liefert einen substring des uebergebenen strings zurueck, der nur vom anfang des eingabestrings bis zu einem gewissen zeichen (exklusive) reicht. ---< 2.4> after() liefert einen substring des uebergebenen strings zurueck, der nur von einem gewissen zeichen des eingabestrings (exklusive) bis zum ende reicht. ---< 2.5> solve() wenn ein '+' gefunden wird (das nicht in einem klammerausdruck steht), wird zunaechstuberprueft, ob auch ein '/' vorhanden ist (was ja nicht sein darf, weil die verschiedenen ebenen des netzwerkes durch klammern gruppiert werden muessen). wenn nicht wird mittels before() alles was vor dem '+' steht ermittelt und wiederum an solve() uebergeben. gelichfalls wird das ergebniss von allem was nach dem '+' steht mit solve(after()) ermittelt. die return-werte dieser aufrufe werden addiert und das ergebeniss zurueckgegeben. wird ein '/' gefunden, wird wie schon bei '+' alles vor und nach dem '/' ge-solve()-ed. allerdings muss man bei der berechnung von zwei paralell geschalteten widerstaenden die kehrwerte addiesren und davon wieder den kehrwert bilden. also werden die ergebnisse erst einmal zwischen gespeichert, kehrwert gebildet, addiert, wieder kehrwert und dann endlich zurueckgegeben. wird kein operator gefunden, kann es sein das der ganze ausdruck von klammern umgeben ist. also ruft man solve() auf mit einem substring bei dem das erste und das letzte zeichen (die klammern) abgeschnitten wurden. der so erhaltene wert wird selbst wieder zurueckgegeben. wurde kein operator gefunden aber der ausdruck steht auch nicht ganz in klammern kann (duerfte) es sich nur noch um eine zahl handeln. sollte dem nicht so sein wirft Integer.parseInt() eine NumberFormatException. diese fange ich aber gleich hier ab, damit im hauptprogramm nur eine REsistorNEtworkeXception gefangen werden muss. auszerdem wird ueberprueft, ob der wert auch positiv ist (negative oder widerstaende gleich 0 bearbeitet das programm nicht). wenn alles gut geht wird der int wert von Integer.parseInt() zurueckgegeben. -------[ 3.] ReNeX REsistorNEtworkeXception zuerst werden die konstanten fuer die fehlertypen definiert. werden dem constructor ein typ und eine position uebergeben, erstellt er im switch-statement die jeweilige fehlermeldung. die for-schleife am ende sollte den zeiger in die naehe des fehlers bringen. eine ReNeX die einen String uebergeben bekommt, wird nur von ReNe.solve() geworfen, wenn Integer.parseInt() irgendeinen fehler verursacht hat. da ich aus Integer.parseInt() nicht auch noch rauskitzeln will _was_ fuer einen fehler es gefunden hat, gibt das einfach einen "unkown error" und den eingabeabschnitt in dem das passiert ist. printMessage kann von einem programm aufgerufen werden um die fehlermeldungen auszugeben. wobei der kleine zeiger (ein '^') nur ausgegeben wird wenn es fuer den jeweiligen fehler sinn macht. appendix a: beispiel zum verstaendnis als eingabe nehme ich den ausdruck "(1/2)+3". 1. solve("(1/2)+3"): das erste solve das aufgerufen wird findet ein '+' das nicht in klammern steht. ein '/' ist nicht in der gleichen ebene also wird der ausdruck aufgeteilt in (1/2) und 3. auf beide haelften wird wiederum solve() ausgefuehrt. --2. solve("(1/2)"): im ersten term findet solve keine operatoren. kann aber feststellen, dass der ganze ausdruck in klammern steht. es ruft also solve() mit dem substring auf der die klammern nicht enthaelt. ----3. solve("1/2"): mit find() wird ein '/' gefunden. der ausdruck wird geteilt und beide haelften werden an ein neues solve() gegeben. ------4. solve("1"): operatoren gibt es keine und der ausdruck steht auchnicht in klammern also versucht solve die eingabe mit Integer.parseInt() int eine zahl umzuwandeln (was auch geht) und liefert diesen wert zurueck. ----3. solve("1/2") (bekam gerade 1 vom 4. solve()): der solve aufruf fuer alles was vor dem '/' steht lieferte eine zwei zurueck. da wir eine paralellschaltung haben wird der kehrwert davon ersteinmal gespeichert. ein neues solve fuer alles hinter dem '/' wird gestartet. ------5. solve("2"): wieder kann direkt eine zahl zurueckgegeben werden. ----3. solve("1/2") (bekam gerade 1 vom 5. solve()): auch alles was hinter dem '/' stand wurde geloest. vom ergebnis wird wieder der kehrwert gebildet. jetzt werden die beiden werte addiert, davon wieder der kehrwert gebildet und das ergebenis (zwei drittel) dann an das 2. solve() zurueckgegeben. --2. solve("(1/2)") (bekam gerade 2/3 vom 3. solve()): der wert vom dritten solve() wird direkt an das erste solve() weitergegeben. 1. solve("(1/2)+3") (bekam gerade 2/3 vom 2. solve()): alles vor dem '+' wurde geloest. jetzt kommt das solve fuer alles dahinter. --6. solve("3"): es wird direkt der wert 3 zurueckgegeben. 1. solve("(1/2)+3") (bekam gerade 3 vom 6. solve()): jetzt habe wir alle werte und sie werden nur noch zusammengezaehlt und zurueckgeben (3 + 2/3). im hauptprogramm wird das dann auf 4 gerundet. ich hoffe das beispiel hilft beim verstaendniss. appendix b: zusammenfassung der spezifikation hier nun wirklich _ganz_ kurz die zusammenfassung der spezifikation. eingelesen werden soll ein String der ein widerstandsnetwerk beschreibt. erlaubt sind nur die zeichen "0123456789+/()". eine serielle schaltung zweier widerstaende wird durch ein '+', eine paralelle schaltung durch ein '/' dargestellt. verschiedene ebenen des netzwerkes werden durch klammern dargestellt. die widerstaende muessen alle positiv und im bereich der int-zahlen liegen. bei korrekter eingabe soll der gesamtwiderstand ausgegeben werden, ansonsten das altbekannte "FALSCHE EINGABE". ach, da stand auch noch was drin von wegen, das problem muss rekursiv und als package geloest werden. so jetzt mag ich aber wirklich nicht mehr. ich wuensche noch viel erfolg! -->patrick -- klaffenboeck patrick /"\ patrick.k@rocketmail.com \ / ASCII Ribbon Campaign ICQ# 55690660 X against HTML in email & vCards / \