/**Markus Raab. * * Dieses Programm berechnet einen eingegebenen * String.*/ ************************************ ***E I N S C H R Ä N K U N G E N *** ************************************ Im Vorhinein gleich einmal: Ich habe den besten Parser geschrieben, den ich in meinen Leben implementieren werde :-) Und wegen Eprog konnte ich ihn total verstümmeln *GRRR* Folgendes kann mein Parser, Eprog sagt aber anderes: nur eine Klammerebene erlaubt (klammer von Skalar zählen nicht) nur 4 Operatoren erlaubt Skalar muß in Klammer stehen Wenn Rechenoperation nicht definiert, dann undefiniert (Skalar + Skalar, Vektor + Skalar...) hier ein paar Details: .) Es können natürlich beliebig viele Operatoren vorkommen, darum musste ich eine Route (in main()) schreiben, welche schaut ob über 4 Operatoren vorkommen und dann mit Fehlermeldung beendet! .) Mein Parser hat ein rekursiven Klammerparser, die Klammern können komplett beliebig verschachtelt werden. z.b. (((..)*(..))*(..)) Das ganze in beliebiger Tiefe. Eprog verlangt, dass nur eine Ebene erlaubt ist->Fehlermeldung wenn in Tiefe über 1 gegangen wird. .) Skalare und Vektoren werden in jeder Situation erkannt und richtig berechnet. Bsp:-4--2*[2,3,2]*3 ist natürlich möglich und wird richtig berechnet. Eprog will aber dass alle Skalare in Klammern stehen (-> nicht geklammerte Skalare Exception) und berechnungen die nicht in der Angabe standen sollen auch nicht berechnet werden (-> Exception wenn z.b. Skalar+Skalar). Diese ganzen (in meinem Fall) komplett hirnrissigen und sinnlosen Einschränkungen können natürlich leicht wieder entfernt werden. Einfach nach EPROG suchen, und diese Exception samt Bedingung auskommentieren. Sie haben garantiert keinen anderen Sinn, als der Spezifikation gerecht zu werden. ************************************ *** E R K L Ä R U N G *** ************************************ main() Im Hauptprogramm (ganz unten) wird nur die Funktion klammern aufgerufen. Bei jeder Exception wird (dummerweise!) nur FALSCHE EINGABE ausgegeben, wenn du printStackTrace auskommentierst, bekommst du genaue Informationen darüber was passiert ist. (Klammer falsch gesetzt,...) klammern() Klammern löst rekursiv den String in Teilstrings auf. z.b: (12+3)*2 Hier wird zuerst 12+3 berechnen übergeben. berechne() Berechne ist der Hauptteil des Programmes. Hier wird ein String nach allen Operationen durchgescannt. Dabei wird natürlich zuerst, dass mit dem größten Vorrang verwendet, in dem Beispiel '*'. Erst nachdem alle * berechnet wurden, geht es zu + usw. Die bereits berechneten Teile werden durch einen Token ersetzt. Token Ein Token ist ein String #Nummer (z.b. #1). In dem Vektor ist für diese Nummer ein Vektor abgespeichert. Wenn der Vektor diesen String versucht zu parsen, erkennt er, dass es sich um einen Token handelt und kann die gespeicherten Werte auslesen. ersetze() Für die Ersetzung von einen String zu den String, der den Token repräsentiert ist ersetze zuständig. Durch angaben der Grenzen und der Tokennummer kann in einem String schon ersetzt werden. z.b. (2+5)*3 in #0 wird 7 gespeichert ersetze (0,4,0); // von 0 bis 3 ersetze durch Token 0 wird dann zu #0*3 findop() Schaut sehr kompliziert aus, ist es aber überhaupt nicht. Es ist nur so lang geworden, weil 4 mal geguckt werden muss ob es ein Operator ist. Jedesmal kommen aber andere Operatoren in Betracht, darum konnte es leider nicht schöner geschrieben werden (zumindest nicht ohne Flexibilität einzubüßen). Es wird einfach ein bestimmter oder beliebiger Operator gesucht und die Position zurückgeliefert. Bei dem Operator - könnte es sich auch um ein Vorzeichen handelt, dass muss auch überprüft werden. parse() Findet elegant die Zahl aus dem String heraus. Dabei werden Vektoren, Skalare und Token unterschieden. calc() Ist ein Multiplexer für die anderen Berechnungsmethoden. Dadurch (und durch andere Vorkehrungen) kann man relativ einfach eine neue Operation einfügen. ************************************ *** T E S T E N *** ************************************ Diese Berechnungen werden wegen verstümmelungen nicht mehr berechnet (siehe Punkt 1 ->Einschränkungen). Weiter unten sind die Strings die auch mit Einschränkung funktionieren. Zum Testen sind zwei Kommentare zu entfernen, um zu erkennen wie die subsitution funktioniert und um eine genau Fehlerausgabe zu erhalten! *** Standard: 12+32+483+32+49+12+3 623 480-12-36-25-87-20-02 298 20+25+3-5+12-63+32-89+2 -63 40+23-56*68+2-5*9+3-5+6-9 -3793 12+6*3*2*6*(4-3+2*2)*2-4 2168 (12+3)*(2+3)*(6-2)-(2+2) 296 (12+3*(2+1)*3-(2-1))*2 76 *** Vorzeichen: -12*3+2--4*(-2+-9)*-1 10 -5--3--2+-3*-2*2 12 -1--1--2--3*-2+3-(2+3)--2 -4 -(2*3) -6 -(-2*-(3+-1)*-3+5)*-2+5 -9 (2+2)*-(2+2) -8 Ab hier wird alles auch mit Einschränkung richtig berechnet. Skalarprodukt mit Maple überprüft. *** Vektoren: [-2,1,3]+[3,3,2]-(3)*[3,2,4] [ -8.000 , -2.000 , -7.000 ] (2.3)*[3.2,-12,5]+[0.64,7.6,-1.5] [ 8.000 , -20.000 , 10.000 ] [2,3,4]*[4,5,6] [ -2.000 , 4.000 , -2.000 ] [-4.2,3.4,34]*[2.3,-4,2.1] [ 143.140 , 87.020 , 8.980 ] [1.2,52.3,14.4]*[50.5,10.6,5.7] [ 145.470 , 720.360 , -2628.430 ] [4,2,7]*[3,2,4]+(23)*[3,4,2]-[3,2,3] [ 60.000 , 95.000 , 45.000 ] ((3)*[2,3,4])*((2)*[4,2,3]) [ 6.000 , 60.000 , -48.000 ] [-4.2,3.4,34]*[2.3,-4,2.1] [ 143.140 , 87.020 , 8.980 ] (2.3)*[3.2,-12,5]+[0.64,7.6,-1.5] [ 8.000 , -20.000 , 10.000 ] ((3)*[2,3.3,2])*((2)*[4,3.2,8])+[-100,40,40] [ 20.000 , -8.000 , -0.800 ] -[2,3,-2]+[2,3,-2] [ 0.000 , 0.000 , 0.000 ] Known Bugs keiner :-) wurde mit allen den obigen Eingabestrings getestet.