Kommentare hinzugefügt. Nun wird nur eine Ebene für diesen
Der Code funktioniert perfekt. Es passieren keine Fehler mehr,
wenn zu viele Operatoren vorkommen.
Code: Alles auswählen
;/-----------------------------------------------------------------\
;|  *** Calculate string - template ***                            |
;|    Created by Josef Sniatecki 2008.                             |
;\-----------------------------------------------------------------/
;  Durch "CalculateString" kann man einfache Stringterme
;  berechnen lassen. Die Werte werden in Doubles berechnet.
;  Dies erlaubt das Ausrechnen von komplexen Eingaben
;  wärend dem Programmablauf.
;  
;  FEATURES:
;    > Die Priorität kann durch Klammern erhöht werden.
;    > Die Priorität der Operatoren wird beachtet. (Punkt vor Strich usw.)
;    > Funktionen und Konstanten werden unterstützt. Sie können
;      auch selbst welche hinzufügen.
;    > Zahlen können auch im Binär- und Hexadezimalformat geschrieben werden.
;    > Logische Operatoren (wie &,|,! usw.) können genutzt werden.
;    > Variable Werte können leicht inerhalb eines Terms genutzt werden.
;      Mehr dazu unter "SYNTAX".
;    > Der Potenz-Operator ("^") kann genutzt werden.
;  
;  SYNTAX:
;    KOMMA:
;      Das Komma für Dezimalzahlen wird immer mit
;      einem "." gekennzeichnet.
;    FUNKTIONEN:
;      Funktionen können klein oder groß geschrieben werden.
;      Parameter werden in einer nachfolgenden Klammer gesetzt
;      und durch ein "," voneinander getrennt. Die Klammern
;      müssen auch bei keinen Parametern vorkommen.
;    KONSTANTEN:
;      Konstanten werden wie in PureBasic mit einem "#"
;      angefangen und können klein oder groß geschrieben werden.
;    VARIABLEN:
;      Variablen müssen immer ein einzelner Buchstabe sein.
;      Dieser kann klein oder groß sein; jedoch macht
;      die größe keinen Unterschied. Um einer Variable
;      einen Wert zu setzen, kann man folgende Wege nutzen:
;      > CalcStr_Var('GROßBUCHSTABE'-65)=WERT
;      > CalcStr_Var('KLEINBUCHSTABE'-97)=WERT
;    BINÄR:
;      Binärzahlen werden mit einem "%" gestartet. Dabei können
;      die nachfolgenden Binärzeichen folgende sein:
;      > 1 = 1,i,I
;      > 0 = 0,o,O
;    HEXADEZIMAL:
;      Hexadezimalzahlen werden mit einem "$" gestartet.
;      Die nachfolgenden Buchstaben können klein oder groß
;      geschrieben werden.
;    BOGENMAß:
;      Winkel können durch ein folgendes "°" in Bogenmaß
;      umgewandelt werden. Manche Funktionen nutzen
;      Parameter im Bogenmaß (zB. Sin,Cos,...).
;    POTENZEN:
;      Die Zeichen "²" und "³" können als Potenzen genutzt werden.
;      Auch bei Consolen-Anwendungen (Ascii-Codes variiren).
;    DURCHSCHNITT:
;      Der Durchschnitt aus einer beliebigen Menge von Zahlen
;      wird berechnet, indem man die Zahlen in einer
;      geschweiften Klammer angibt und mit Kommas voneinander
;      trennt.
;      Beispiel: "{10,20,30}" = 20
;    FREIHEIT:
;      Leerzeichen können ruhig zur eigenen Übersichtlichkeit des
;      Terms genutzt werden.
CompilerIf Defined(Templates_Math_CalculateString_PBI,#PB_Constant)=#False
#Templates_Math_CalculateString_PBI=#True
;/------------------------------------------\
;| Intergrations                            |
;\------------------------------------------/
Procedure.l DBin(Bin.s)
  ;DecimalBinary(Binary)
  
  Protected *Char.Character ;Character
  Protected I.l             ;Index
  Protected Dec.l           ;Decimal
  
  *Char=@Bin
  While *Char\C<>0
    Dec<<1
    If *Char\C='1' : Dec+1 : EndIf
    *Char+1
  Wend
  ProcedureReturn Dec
EndProcedure
Procedure.l DHex(Hex.s)
  ;DecimalHexadecimal(Hex)
  
  Protected *Char.Character ;Character
  Protected I.l             ;Index
  Protected Dec.l           ;Decimal
  
  *Char=@Hex
  While *Char\C<>0
    Dec<<4
    If *Char\C<='9' : Dec+*Char\C-'0' : Else : Dec+*Char\C-'A'+10 : EndIf
    *Char+1
  Wend
  ProcedureReturn Dec
EndProcedure
;/------------------------------------------\
;| Constants                                |
;\------------------------------------------/
Enumeration 1  ;CalculateString_Priorities
  #CalcStr_AddASubPrio ;AddAndSubtract~
  #CalcStr_MulADivPrio ;MultiplicateAndDivide~
  #CalcStr_LogicalPrio
  #CalcStr_PowPrio     ;Power~
  #CalcStr_NotPrio
EndEnumeration
;/------------------------------------------\
;| Variables                                |
;\------------------------------------------/
Global *CalcStr_CChar.Character=0 ;{ CalculateString_CurrentCharacter
;  Dies ist der Lesezeiger des zu berechnenden
;  Terms.
;}
Global CalcStr_Prio.b             ;~Priority
Global Dim CalcStr_Var.d(25)      ;~Variable
Global *CalcStr_FuncA             ;~FunctionArray
Global *CalcStr_FuncA_End.l       ;~FunctionArray_End
Global *CalcStr_ConstA            ;~ConstantArray
Global *CalcStr_ConstA_End.l      ;~ConstantArray_End
;/------------------------------------------\
;| Declarings                               |
;\------------------------------------------/
Declare.d CalcStr(Term.s="",Prio.b=0)
Declare.d CalcStr_Num()
Declare.d CalcStr_Bin()
Declare.d CalcStr_Hex()
Declare.d CalcStr_Func()
Declare.l CalcStr_Args(ArgAm.l)
Declare.d CalcStr_Const()
;/------------------------------------------\
;| Functions                                |
;\------------------------------------------/
Procedure.d CalcStr(Term.s="",Prio.b=0)
  ;CalculateString(Term="",Priority=0)
  ;{
  ;  Diese Funktion liest ein Term, Zeichen
  ;  für Zeichen und berechnet diesen.
  ;  Falls kein Term angegeben wird, wird
  ;  der Lesezeiger nicht erneut an den
  ;  Anfang des Terms gesetzt.
  ;  
  ;  Der Lesezeiger ("*CalcStr_CChar") ist
  ;  global und wird in jeder Ebene benutzt.
  ;
  ;  WARNUNG:
  ;    Bitte diese Prozedur nicht mehrmals
  ;    gleichzeitig nutzen (In Threads usw.),
  ;    Da diese Funktion und viele andere
  ;    dazugehörigen Funktionen, globale
  ;    Variablen nutzen und modifizieren.
  ;}
  
  #CalcStr_InvChar=0 ;~InvaildCharacter
  
  Protected Num.d ;Number
  Protected L1.l  ;Long1
  Protected L2.l  ;Long2
  
  If Term ;Neuer Term.
    *CalcStr_CChar=@Term ;Lesezeiger auf den Anfang des Terms setzen.
  EndIf
  
  While *CalcStr_CChar\C<>0
    Select *CalcStr_CChar\C
      
      ;[ Werte auslesen ]
      Case '0' To '9'
        Num=CalcStr_Num()
      Case '%' ;Binär
        *CalcStr_CChar+1
        Num=CalcStr_Bin()
      Case '$' ;Hexadezimal
        *CalcStr_CChar+1
        Num=CalcStr_Hex()
      Case 'A' To 'Z','a' To 'z'
        Select PeekC(*CalcStr_CChar+1) ;Nächstes Zeichen.
          Case 'A' To 'Z','a' To 'z' ;Funktion.
            Num=CalcStr_Func()
            *CalcStr_CChar+1
            Continue
          Default ;Variable (Nur ein Zeichen).
            If *CalcStr_CChar<=90
              Num=CalcStr_Var(*CalcStr_CChar\C-65) ;Großbuchstabe.
            Else
              Num=CalcStr_Var(*CalcStr_CChar\C-97) ;Kleinbuchstabe.
            EndIf
        EndSelect
      Case '#' ;Konstante auslesen.
        *CalcStr_CChar+1
        Num=CalcStr_Const()
      
      ;[ Operatoren ]
      ;{ Schema:
      ;    Case 'ZEICHEN FÜR OPERATOR'
      ;      If Prio<#KONSTANTE_FÜR_PRIORITÄT_DES_OPERATORS
      ;        *CalcStr_CChar+1 ;Über das Zeichen springen.
      ;        BERECHNUNG.
      ;        ;Bei der Berechnung muss eine neue Ebene
      ;        ;zum zurückgeben eines zweiten Faktors
      ;        ;aufgerufen werden. Dabei muss der erste Parameter
      ;        ;ein "" sein und der zweite die Konstante
      ;        ;mit der Priorität des Operators.
      ;      Else
      ;        ProcedureReturn Num
      ;      EndIf
      ;}
      Case '+'
        If Prio<#CalcStr_AddASubPrio
          *CalcStr_CChar+1
          Num+CalcStr("",#CalcStr_AddASubPrio)
          Continue
        Else
          ProcedureReturn Num
        EndIf
      Case '-'
        If Prio<#CalcStr_AddASubPrio
          *CalcStr_CChar+1
          Num-CalcStr("",#CalcStr_AddASubPrio)
          Continue
        Else
          ProcedureReturn Num
        EndIf
      Case '*'
        If Prio<#CalcStr_MulADivPrio
          *CalcStr_CChar+1
          Num*CalcStr("",#CalcStr_MulADivPrio)
          Continue
        Else
          ProcedureReturn Num
        EndIf
      Case '/'
        If Prio<#CalcStr_MulADivPrio
          *CalcStr_CChar+1
          Num/CalcStr("",#CalcStr_MulADivPrio)
          Continue
        Else
          ProcedureReturn Num
        EndIf
      Case '&'
        If Prio<#CalcStr_LogicalPrio
          *CalcStr_CChar+1
          L1=Num
          L2=CalcStr("",#CalcStr_LogicalPrio)
          L1&L2
          Num=L1
          Continue
        Else
          ProcedureReturn Num
        EndIf
      Case '|'
        If Prio<#CalcStr_LogicalPrio
          *CalcStr_CChar+1
          L1=Num
          L2=CalcStr("",#CalcStr_LogicalPrio)
          L1|L2
          Num=L1
          Continue
        Else
          ProcedureReturn Num
        EndIf
      Case '!'
        If Prio<#CalcStr_LogicalPrio
          *CalcStr_CChar+1
          L1=Num
          L2=CalcStr("",#CalcStr_LogicalPrio)
          L1!L2
          Num=L1
          Continue
        Else
          ProcedureReturn Num
        EndIf
      Case '^'
        If Prio<#CalcStr_PowPrio
          *CalcStr_CChar+1
          Num=Pow(Num,CalcStr("",#CalcStr_PowPrio))
          Continue
        Else
          ProcedureReturn Num
        EndIf
      Case '~'
        If Prio<#CalcStr_NotPrio
          *CalcStr_CChar+1
          L1=CalcStr("",#CalcStr_NotPrio)
          L1=~L1
          Num=L1
          Continue
        Else
          ProcedureReturn Num
        EndIf
        
      ;[ Umwandlungen ]
      Case '°',248 ;Winkel in Bogenmaß umwandeln.
        Num=Num*2*#PI/360
      Case '²',253 ;²
        Num=Num*Num
      Case '³',252 ;³
        Num=Num*Num*Num
        
      ;[ Extras ]
      Case '{' ;Durchschnitt.
        *CalcStr_CChar+1
        L1=0
        Repeat
          Num+CalcStr()
          L1+1
        Until *CalcStr_CChar\C='}' Or PeekC(*CalcStr_CChar-1)<>','
        Num/L1
      Case '}' ;Ende des Durchschnitts.
        ProcedureReturn Num
        
      ;[ Verwaltung der Ebenen ]
      Case ','           ;Parameter zurückgeben.
        *CalcStr_CChar+1 ;Über das Komma springen.
        ProcedureReturn Num
      Case '('           ;Neue Ebene hinzufügen.
        *CalcStr_CChar+1 ;Über "Klammer auf" springen.
        Num=CalcStr()    ;Nummer aus einer neuen Prozedur auslesen und berechnen.
        *CalcStr_CChar+1 ;Über "Klammer zu" springen.
        Continue
      Case ')'           ;Eine Ebene zurückspringen.
        ProcedureReturn Num
      Case ' '           ;Unnützliches Zeichen.
        *CalcStr_CChar+1 ;Ignorieren.
        Continue
        
      Default
        CompilerIf #PB_Compiler_Debugger
          Debug "CalcStr() error: "+Chr(32)+Chr(*CalcStr_CChar\C)+Chr(32)+" is an invaild character!"
          Beep_(250,250)
          End
        CompilerEndIf
    EndSelect
    *CalcStr_CChar+1
  Wend
  ProcedureReturn Num
EndProcedure
Procedure.d CalcStr_Num()
  ;CalculateString_Number()
  
  Protected NumAStr.s ;NumberAsString
  
  Repeat
    Select *CalcStr_CChar\C
      Case '0' To '9','.'
        NumAStr+Chr(*CalcStr_CChar\C)
      Default                         ;Unbekanntes Zeichen.
        *CalcStr_CChar-1              ;Lesezeicher vor dem unbekannten Zeiger setzen.
        ProcedureReturn ValD(NumAStr) ;Gelesener String als Zahl zurückgeben.
    EndSelect
    *CalcStr_CChar+1
  ForEver
  ProcedureReturn 0
EndProcedure
Procedure.d CalcStr_Bin()
  ;CalculateString_Binary()
  
  Protected NumAStr.s ;NumerAsString
  
  Repeat
    Select *CalcStr_CChar\C
      Case '0','1'
        NumAStr+Chr(*CalcStr_CChar\C)
      Case 'o','O'
        NumAStr+"0"
      Case 'i','I'
        NumAStr+"1"
      Default                         ;Unbekanntes Zeichen.
        *CalcStr_CChar-1              ;Lesezeiger vor dem unbekannten Zeichen setzen.
        ProcedureReturn DBin(NumAStr) ;Gelesener String als Binärzahl zurückgeben.
    EndSelect
    *CalcStr_CChar+1
  ForEver
  ProcedureReturn 0
EndProcedure
Procedure.d CalcStr_Hex()
  ;CalculateString_Hexadecimal()
  
  Protected NumAStr.s ;NumerAsString
  
  Repeat
    Select *CalcStr_CChar\C
      Case '0' To '9','A' To 'F'
        NumAStr+Chr(*CalcStr_CChar\C)
      Case 'a' To 'f'
        NumAStr+UCase(Chr(*CalcStr_CChar\C))
      Default                         ;Unbekanntes Zeichen.
        *CalcStr_CChar-1              ;Lesezeiger vor dem unbekannten Zeichen setzen.
        ProcedureReturn DHex(NumAStr) ;Den gelesenen String als Hexadezimalzahl zurückgeben.
    EndSelect
    *CalcStr_CChar+1
  ForEver
  ProcedureReturn 0
EndProcedure
Procedure.d CalcStr_Func()
  ;CalculateString_Function()
  
  #CalcStr_Func_InvFunc=0 ;~InvaildFunction
  #CalcStr_Func_InvChar=1 ;~InvaildCharacter
  
  Protected Func.s ;Function
  Protected Num.d  ;Number
  Protected *Args  ;Arguments
  Protected *Ptr   ;Pointer
  Protected F.b    ;Found
  
  Repeat
    Select *CalcStr_CChar\C
      Case 'A' To 'Z','a' To 'z'   ;Buchstabe wird in den Name eingelesen.
        Func+Chr(*CalcStr_CChar\C) ;Name der Funktion verlängern.
      Case '('                     ;Klammer wurde nach dem Name gefunden.
        Func=LCase(Func)           ;Name der Funktion in Kleinbuchstaben umwandeln.
        Select Func
          Case "abs"
            *Args=CalcStr_Args(1)
            Num=Abs(PeekD(*Args))
          Case "pow"
            *Args=CalcStr_Args(2)
            Num=Pow(PeekD(*Args),PeekD(*Args+SizeOf(Double)))
          Case "sqr"
            *Args=CalcStr_Args(2)
            Num=Pow(PeekD(*Args),1/PeekD(*Args+SizeOf(Double)))
          Case "arc","a"
            *Args=CalcStr_Args(1)
            Num=PeekD(*Args)*360/(2*#PI)
          Case "rad","r"
            *Args=CalcStr_Args(1)
            Num=PeekD(*Args)*2*#PI/360
          Case "sin"
            *Args=CalcStr_Args(1)
            Num=Sin(PeekD(*Args))
          Case "cos"
            *Args=CalcStr_Args(1)
            Num=Cos(PeekD(*Args))
          Case "tan"
            *Args=CalcStr_Args(1)
            Num=Tan(PeekD(*Args))
          Case "asin"
            *Args=CalcStr_Args(1)
            Num=ASin(PeekD(*Args))
          Case "acos"
            *Args=CalcStr_Args(1)
            Num=ACos(PeekD(*Args))
          Case "atan"
            *Args=CalcStr_Args(1)
            Num=ATan(PeekD(*Args))
            
          Default                                   ;Eigene oder ungültige Funktion.
            If *CalcStr_FuncA                       ;Startzeiger für Funktionen wurde vom Anwender gesetzt...
              *Ptr=*CalcStr_FuncA                   ;Lesezeiger auf den Start setzen.
              While *Ptr<*CalcStr_FuncA_End         ;Solange der Lesezeiger != dem Endzeiger ist...
                If Func=PeekS(*Ptr)                 ;Funktionsnamen auslesen und Checken...
                  *Ptr+Len(PeekS(*Ptr))+1           ;Mit dem Lesezeiger über den Namen springen.
                  If PeekL(*Ptr)                    ;Falls Parameter gebraucht werden... (!=0)
                    *Args=CalcStr_Args(PeekL(*Ptr)) ;Zeiger auf Array der Parameter in "*Args" abspeichern.
                  EndIf
                  *Ptr+SizeOf(Long)                    ;Lesezeiger über die Anzahl der Parameter springen lassen.
                  CallFunctionFast(PeekL(*Ptr),*Args,@Num)     ;Funktion aufrufen lassen.
                  F=#True                           ;Gefunden.
                  Break
                Else
                  *Ptr+Len(PeekS(*Ptr))+1
                  *Ptr+SizeOf(Long)*2
                EndIf
              Wend
            EndIf
            
            If F=#False ;Funktion nicht gefunden.
              CompilerIf #PB_Compiler_Debugger
                Debug "CalcStr_Func() error: "+Func+" is an invaild function!"
                Beep_(250,250)
                End
              CompilerEndIf
            EndIf
        EndSelect
        If *Args : FreeMemory(*Args) : EndIf
        ProcedureReturn Num
      Default
        CompilerIf #PB_Compiler_Debugger
          Debug "CalcStr_Func() error: "+Str(*CalcStr_CChar\C)+" code is an invaild function character."
          Beep_(250,250)
          End
        CompilerEndIf
    EndSelect
    *CalcStr_CChar+1
  ForEver
  ProcedureReturn 0
EndProcedure
Procedure.l CalcStr_Args(ArgAm.l)
  ;CalculateString_Arguments(ArgumentAmount)
  
  Protected *Args ;Arguments
  Protected I.l   ;Index
  
  *Args=AllocateMemory(SizeOf(Double)*ArgAm) ;Array für Argumente erstellen.
  *CalcStr_CChar+1                        ;Mit dem Lesezeiger über "Klammer auf" springen.
  
  For I=1 To ArgAm                           ;Für jedes Argument.
    PokeD(*Args+SizeOf(Double)*(I-1),CalcStr()) ;Wert des Arguments berechnen und in die Array speichern.
  Next
  ProcedureReturn *Args
EndProcedure
Procedure.d CalcStr_Const()
  ;CalculateString_Constant()
  
  #CalcStr_InvConst=0 ;~InvaildConstant
  
  Protected Const.s ;Constant
  Protected Num.d   ;Number
  Protected *Ptr    ;Pointer
  Protected F.b     ;Found
  
  Repeat
    Select *CalcStr_CChar\C
      Case 'A' To 'Z','a' To 'z'    ;Buchstabe wird in den Name eingelesen.
        Const+Chr(*CalcStr_CChar\C) ;Name der Konstante verlängern.
      Default                       ;Ein unbekanntes Zeichen.
        *CalcStr_CChar-1            ;Vor dem Unbekannten Zeichen setzen.
        Const=LCase(Const)          ;Name der Konstante in Kleinbuchstaben umwandeln.
        Select Const
          Case "pi"
            Num=3.1415926535897931 ;Entspricht dem Double-Format.
          Case "eul","e"
            Num=2.7182818284590455 ;Entspricht dem Double-Format.
          Case "ang","a"           ;"Ang" entspricht "Angle"
            Num=57.2957795131
          Case "rad","r"
            Num=0.0174532925
          Default                             ;Eigene oder ungültige Konstante.
            If *CalcStr_ConstA                ;Ist dieser Zeiger vom Anwender gesetzt worden...
              *Ptr=*CalcStr_ConstA            ;Lesezeiger auf den Start aller Konstanten setzen.
              While *Ptr<>*CalcStr_ConstA_End ;Lesezeiger ist != dem Endzeiger.
                If Const=PeekS(*Ptr)          ;Name der Konstante auslesen und Checken...
                  *Ptr+Len(PeekS(*Ptr))+1     ;Lesezeiger über den Namen springen lassen.
                  Num=PeekD(*Ptr)             ;Konstante Nummer auslesen.
                  F=#True                     ;Gefunden.
                  Break                       ;Suchschleife beenden.
                Else
                  *Ptr+Len(PeekS(*Ptr))+1     ;Lesezeiger über den falschen Name springen lassen.
                  *Ptr+SizeOf(Double)            ;Lesezeiger über die unbrauchbare Zahl springen lassen.
                Endif
              Wend
            EndIf
            
            If F=#False ;Nicht gefunden.
              CompilerIf #PB_Compiler_Debugger
                Debug "CalcStr_Const() error: "+Const+" is an invaild constant!"
                Beep_(250,250)
                End
              CompilerEndIf
            EndIf
        EndSelect
        ProcedureReturn Num
    EndSelect
    *CalcStr_CChar+1
  ForEver
  ProcedureReturn 0
EndProcedure
;/------------------------------------------\
;| Examples                                 |
;\------------------------------------------/
;{ View
;   ;Dieses Beispiel zeigt einige möglichen Terme und erlaubt
;   ;selbst welche zu schreiben und ausrechnen zu lassen.
; 
;   OpenConsole()
;   ConsoleTitle("Term calculator")
;   
;   ConsoleColor(15,0) : PrintN("Example terms with their results:") : ConsoleColor(7,0)
;   PrintN("12.5 + 20.5      = "+StrD(CalcStr("12.5+20.5")))           ;Normale Dezimalrechnung.
;   PrintN("60 + 2 * 5       = "+StrD(CalcStr("60+2*5")))              ;Punkt vor Strich wird beachtet.
;   PrintN("sin(45"+Chr(248)+")         = "+StrD(CalcStr("Sin(45°)"))) ;Unterstützung von Funktionen.
;   PrintN("%10 | %01        = "+StrD(CalcStr("%10|%01")))             ;Binäre Berechnung.
;   PrintN("{20,10}          = "+StrD(CalcStr("{20,10}")))             ;Berechnung des Durchschnitts.
;   PrintN("#PI*2            = "+StrD(CalcStr("#PI*2")))               ;Ersetzt Konstanten.
;   
;   PrintN("")
;   ConsoleColor(15,0) : PrintN("You can also use functions:") : ConsoleColor(7,0)
;   PrintN("2 * x + 3 ^ (x / 2) + 5")
;   For X=1 To 5
;     CalcStr_Var('X'-65)=X
;     PrintN("x = "+Str(X)+"     : "+StrD(CalcStr("2*x+3^(x/2)+5")))
;   Next
;   PrintN("the variables can be the letters from a to z.")
;   
;   PrintN("")
;   ConsoleColor(15,0) : PrintN("Your own terms:") : ConsoleColor(7,0)
;   PrintN("1 - default")
;   PrintN("2 - function")
;   PrintN("Enter nothing to return.")
;   PrintN("")
;   
;   Repeat
;     ConsoleColor(12,0) : Print("Mode: ") : ConsoleColor(7,0)
;     Select Input()
;       Case "1"
;         Repeat
;           ConsoleColor(12,0) : Print("Term: ") : ConsoleColor(7,0)
;           Term$=Input()
;           If Term$
;             ConsoleColor(14,0) : Print("Result: ") : ConsoleColor(7,0)
;             PrintN(StrD(CalcStr(Term$)))
;           EndIf
;         Until Term$=""
;       Case "2"
;         ConsoleColor(12,0) : Print("Function: ") : ConsoleColor(7,0)
;         Function$=Input()
;         Repeat
;           ConsoleColor(12,0) : Print("x: ") : ConsoleColor(7,0)
;           X$=Input()
;           If X$
;             CalcStr_Var('X'-65)=CalcStr(X$) ;Setzt die Variable x auf den eingegebenen Wert.
;             ConsoleColor(14,0) : Print("Result: ") : ConsoleColor(7,0)
;             PrintN(StrD(CalcStr(Function$)))
;           EndIf
;         Until X$=""
;       Default
;         Break
;     EndSelect
;   ForEver
;   
;   CloseConsole()
;   End
;}
;{ Extended
;   ;In diesem Beispiel werden eigene Funktionen angewendet.
;   ;Alle Argumente werden in den Zeiger 'Args' abgespeichert.
;   ;Diese können dann mit 'PokeD' ausgelesen werden.
;   
;   Global Mem.d
;   
;   Procedure.l CalcStr_Func_Rand(*Args,*Num)
;     ;CalculateString_Function_Random(Arguments,Number)
;     
;     PokeD(*Num,Random(PeekD(*Args)))
;   EndProcedure
;   Procedure.l CalcStr_Func_Mem(*Args,*Num)
;     ;CalculateString_Function_Memory(Arguments,Number)
;     
;     PokeD(*Num,Mem)
;   EndProcedure
;   
;   DataSection
;     Funcs: ;Functions
;       Data.s "rand"               ;Name einer Funktion. Immer klein schreiben!
;       Data.l 1                    ;Anzahl der Argumente.
;       Data.l @CalcStr_Func_Rand() ;Zeiger auf die wahre Funktion.
;       
;       Data.s "mem"
;       Data.l 0
;       Data.l @CalcStr_Func_Mem()
;     EndFuncs: ;EndOfFunctions
;   EndDataSection
;   
;   *CalcStr_FuncA=?Funcs        ;Setzt den Anfangslabel für die eigenen Funktionen.
;   *CalcStr_FuncA_End=?EndFuncs ;Setzt das Endlabel für die eigenen Funktionen.
;   
;   
;   
;   OpenConsole()
;   ConsoleTitle("Term calculator")
;   
;   PrintN("1 - default")
;   PrintN("2 - function")
;   PrintN("Enter nothing to return.")
;   PrintN("")
;   
;   Repeat
;     ConsoleColor(12,0) : Print("Mode: ") : ConsoleColor(7,0)
;     Select Input()
;       Case "1"
;         Repeat
;           ConsoleColor(12,0) : Print("Term: ") : ConsoleColor(7,0)
;           Term$=Input()
;           If Term$
;             ConsoleColor(14,0) : Print("Result: ") : ConsoleColor(7,0)
;             Mem=CalcStr(Term$) ;Das Ergebnis wird in 'Mem' abgespeichert und kann mit "MEM()" wieder erhalten werden.
;             PrintN(StrD(Mem))
;           EndIf
;         Until Term$=""
;       Case "2"
;         ConsoleColor(12,0) : Print("Function: ") : ConsoleColor(7,0)
;         Function$=Input()
;         Repeat
;           ConsoleColor(12,0) : Print("x: ") : ConsoleColor(7,0)
;           X$=Input()
;           If X$
;             CalcStr_Var('X'-65)=CalcStr(X$) ;Setzt die Variable x auf den eingegebenen Wert.
;             ConsoleColor(14,0) : Print("Result: ") : ConsoleColor(7,0)
;             PrintN(StrD(CalcStr(Function$)))
;           EndIf
;         Until X$=""
;       Default
;         Break
;     EndSelect
;   ForEver
;   
;   CloseConsole()
;   End
;}
CompilerEndIf