Mein Formelparser aus BPS #20
Übersicht
BlitzMax, BlitzMax NG
Codearchiv & Module
|
Betreff: Mein Formelparser aus BPS #20
|
Do, Mai 31, 2012 22:41
Antworten mit Zitat
|
Ich habe den Formelparser aus meinem Beitrag zu BPS #20 (Kopfrechnen-Spiel)
https://www.blitzforum.de/forum...hp?t=38666
weiterentwickelt:
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN]
SuperStrict
Type TOperator Field operator:String Field pri:Int EndType
Global TermListe:TList = New TList
Function Rechnen:String(Ausdruck:String) Local term:String , pri:Int = 0 Termliste.clear() Ausdruck = Ausdruck.Replace("," , ".") Ausdruck = Ausdruck.Replace(" " , "") Ausdruck = Ausdruck.tolower() For Local position:Int = 0 Until Ausdruck.length Local zeichen:Byte = Ausdruck[position] If zeichen = Asc("(") pri:+ 100 ; Continue If zeichen = Asc(")") pri:- 100 ; Continue If zeichen = Asc("-") And term = "" term = "-" ; Continue If zeichen >= Asc("0") And zeichen <= Asc("9") Or zeichen=Asc(".") term:+ Chr(zeichen) Else TermListe.addlast(term) term = "" Local t:TOperator = New TOperator t.operator = Chr(zeichen) t.pri = 0 Select Chr(zeichen) Case "+" , "-" t.pri = 10 + pri Case "*" , "/" t.pri = 11 + pri Case "^" t.pri = 12 + pri EndSelect If t.pri > 0 TermListe.addlast(t) Else Notify("Unbekannter Operator ~q" + t.operator + "~q") ; End EndIf EndIf Next TermListe.addlast(term) Prioritaet() Return String(Termliste.first()) EndFunction
Function Prioritaet() Repeat Local pri:Int = 0 Local ausdruck:TOperator For Local c:TOperator = EachIn TermListe If c.pri > pri pri = c.pri ausdruck = c EndIf Next BerechneAusdruck(ausdruck) Until TermListe.count() = 1 EndFunction
Function BerechneAusdruck(ausdruck:Toperator) Local operator:TLink = TermListe.findlink(ausdruck) Local LinkerOperand:TLink = operator.PrevLink() Local RechterOperand:TLink = operator.NextLink() Local links:String = String(LinkerOperand.Value() ) Local rechts:String = String(RechterOperand.Value() ) Local op:TOperator = TOperator(operator.Value() ) Local ergebnis:String Select op.operator Case "^" ergebnis = Double(links) ^ Double(rechts) Case "*" ergebnis = Double(links) * Double(rechts) Case "/" If Double(rechts) = 0 Notify("Division durch Null!") ; End ergebnis = Double(links) / Double(rechts) Case "+" ergebnis = Double(links) + Double(rechts) Case "-" ergebnis = Double(links) - Double(rechts) EndSelect operator.remove() LinkerOperand.remove() TermListe.InsertAfterLink(ergebnis , RechterOperand) RechterOperand.remove() EndFunction
Print Rechnen("((12 5-50) *4)^2")
Ich weiss, meine gross- Kleinschreibung...
|
|
|
|
Fr, Jun 01, 2012 0:39
Antworten mit Zitat
|
Sehr schön gelöst das Problem
Obwohl ich glaube das eine Rekursive Lösung von Vorteil wäre (von der Klammer her). Ich wollte auch mal son Ding schreiben, war aber irgendwie immer zu Faul es dann auch wirklich zu tun aber hast echt gute arbeit gemacht !
Lg
|
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!
|
|
|
Fr, Jun 01, 2012 7:23
Antworten mit Zitat
|
Danke,ToeB!
Ich habe vor einer kleinen Ewigkeit so ein Programm in C++ auf dem Amiga geschrieben, rekursiv und mit
überladenen Operatoren.
Die Aufgabe in BPS #20 war ein willkommener Anlass, nochmal einen Formelparser zu schreiben.
Rekursion wäre tatsächlich eine Option gewesen, aber das war mir dann doch (im Moment) zu viel Aufwand.
|
|
|
Moderator
|
Fr, Jun 01, 2012 8:23
Antworten mit Zitat
|
Schöner Code. Habe mir erlaubt dass Ganze in einen Type auszulagern und im Falle reiner Integer die Ausgabe auf Long umzustellen.
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN]
SuperStrict
Type TOperator Field operator:String Field pri:Int EndType Type TMathParser Global TermListe:TList = New TList Method Rechnen:String(Ausdruck:String) Local term:String , pri:Int = 0 Termliste.clear() Ausdruck = Ausdruck.Replace("," , ".") Ausdruck = Ausdruck.Replace(" " , "") Ausdruck = Ausdruck.tolower() For Local position:Int = 0 Until Ausdruck.length Local zeichen:Byte = Ausdruck[position] If zeichen = Asc("(") pri:+ 100 ; Continue If zeichen = Asc(")") pri:- 100 ; Continue If zeichen = Asc("-") And term = "" term = "-" ; Continue If zeichen >= Asc("0") And zeichen <= Asc("9") Or zeichen=Asc(".") term:+ Chr(zeichen) Else TermListe.addlast(term) term = "" Local t:TOperator = New TOperator t.operator = Chr(zeichen) t.pri = 0 Select Chr(zeichen) Case "+" , "-" t.pri = 10 + pri Case "*" , "/" t.pri = 11 + pri Case "^" t.pri = 12 + pri EndSelect If t.pri > 0 TermListe.addlast(t) Else Notify("Unbekannter Operator ~q" + t.operator + "~q") ; End EndIf EndIf Next TermListe.addlast(term) Prioritaet() Return String(Termliste.first()) EndMethod Method Prioritaet() Repeat Local pri:Int = 0 Local ausdruck:TOperator For Local c:TOperator = EachIn TermListe If c.pri > pri pri = c.pri ausdruck = c EndIf Next BerechneAusdruck(ausdruck) Until TermListe.count() = 1 EndMethod Method BerechneAusdruck(ausdruck:Toperator) Local operator:TLink = TermListe.findlink(ausdruck) Local LinkerOperand:TLink = operator.PrevLink() Local RechterOperand:TLink = operator.NextLink() Local links:String = String(LinkerOperand.Value() ) Local rechts:String = String(RechterOperand.Value() ) Local op:TOperator = TOperator(operator.Value() ) Local ergebnis:String If (links.contains(".") = 0) And (rechts.contains(".") = 0) Then Select op.operator Case "^" ergebnis = Long(Long(links) ^ Long(rechts)) Case "*" ergebnis = Long(Long(links) * Long(rechts)) Case "/" If Long(rechts) = 0 Notify("Division durch Null!") ; End ergebnis = Long(Long(links) / Long(rechts)) Case "+" ergebnis = Long(Long(links) + Long(rechts)) Case "-" ergebnis = Long(Long(links) - Long(rechts)) EndSelect Else Select op.operator Case "^" ergebnis = Double(links) ^ Double(rechts) Case "*" ergebnis = Double(links) * Double(rechts) Case "/" If Double(rechts) = 0 Notify("Division durch Null!") ; End ergebnis = Double(links) / Double(rechts) Case "+" ergebnis = Double(links) + Double(rechts) Case "-" ergebnis = Double(links) - Double(rechts) EndSelect EndIf operator.remove() LinkerOperand.remove() TermListe.InsertAfterLink(ergebnis , RechterOperand) RechterOperand.remove() EndMethod EndType
Print New TMathParser.Rechnen("((12 5-50) *4)^2")
|
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI
Stolzer Gewinner des BAC#48, #52 & #92
|
Übersicht
BlitzMax, BlitzMax NG
Codearchiv & Module
Powered by phpBB © 2001 - 2006, phpBB Group