Entwickler-Ecke
Sonstiges (Delphi) - Sortieren eines Arrays auf Basis eines anderen Arrays
Xardas008 - Do 29.03.07 12:04
Titel: Sortieren eines Arrays auf Basis eines anderen Arrays
Hi ihr,
das Problem klingt komplizierter als es ist. Ich bin gerade einen Taschenrechner am programmieren, der auch Punkt vor Strichrechnung beherrscht.
Funktioniert soweit auch schon ganz gut.
Nur an einer Stelle hapert es, der Array, wo ich die eingegebenen Zahlen aus dem Editfeld drin speichere, müssen umsortiert werden, da ich intern Klammern in das Operatorenarray einfüge, wenn der Operator ein * oder ein / ist, damit der dies zuerst rechnet.
Das Problem durch die Klammern ist dann, dass die Reihenfolge der Zahlen nicht mehr stimmt, sie müssen neu sortiert werden.
Für die Rechnung 1 + 2x3 - 1/2 +6 muss der Taschenrechner intern folgendes machen, er rechnet erst 2x3, dazu addiert er die 1. Um jetzt 1/2 rechnen zu können, müssen beide Elemente im Array um 1 nach hinten geschoben werden (alle dahinter natürlich auch), um dann die +6 zu rechnen, muss die 6 ein weiteres mal nach hinten geschoben werden, usw.
Irgendwie bekomme ich die Prozedur dafür nicht so recht hin, wollte das ganze Rekursiv lösen, wobei beide Arrays dieser Prozedur übergeben werden müssen.
Hoffe dass ich mit Eurer Hilfe das hinbekomme, dann kann ich auch noch nachträglich Klammernsetzung einfügen (weil die sind nach mathematischen Gesetzen ja noch vor dem Punkt (* oder /) zu lösen.
Mit freundlichen Grüßen
Xardas008
Edit: Liefere euch hier mal eben die prozeduren GetNumber und SetOperator, wo die beiden Arrays gefüllt werden.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62:
| function TFrm_Taschenrechner.GetNumbers(vNumber:STRING):Number; var i, k:INTEGER; dummy:REAL; dummy3 :ARRAY[1..40] of REAL; dummy2 :StringArray; dummy4 :char; begin j := 0; for i := 1 to Length(vNumber) do begin
if not(vNumber[i] = '|') then begin
if vNumber[i] = '|' then begin inc(j); end else begin
inc(j); Number2[j] := StrToFloat(vNumber[i]); end; end; end; result := Number2; end;
function TFrm_Taschenrechner.SetOperator(Operator :STRING):StringArray; var i:INTEGER; begin k:= 0; for i := 1 to Length(Operator) do begin if not(Operator[i] = '|') then begin
if Operator[i] = '|' then begin inc(k); end else begin inc(k); if (Operator[i]= '*') or (Operator[i] = '/') then begin vFeld[k] := '('; inc(k); vFeld[k] := Operator[i]; inc(k); vFeld[k] := ')'; end else begin vFeld[k] := Operator[i]; end; end; end; end; result := vFeld; end; |
Xardas008 - Do 29.03.07 14:50
Habe folgende Schleife gebastelt, funktioniert fast, wenige Stellen erhalten einen falschen Wert. Hier die Schleife:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37:
| for i:= 1 to Length(Operator) do begin if (Operator[i] = '(') then begin for k := 1 to Length(Operator) do begin dummy3[k] := 0; end; for k:=i to Length(Operator) do begin dummy3[k] := vNumber[k+2]; end; for k:=i to Length(Operator) do begin vNumber[k+3] := dummy3[k]; end;
end else begin if (Operator[i] = ')') then begin for k:= 1 to Length(Operator) do begin dummy3[k] := 0; end; for k:= i to Length(Operator) do begin dummy3[k] := vNumber[k]; end; for k:=i to Length(Operator) do begin vNumber[k+1] := dummy3[k]; end;
end; end; |
Bei der Beispielrechnung 1+ (2x3) - (1/2) + 6 muss die zweite 1 an Position 5 (von Pos. 4) und die 6 auf Pos. 9 von Pos. 6, an Pos. 5 landet die 1 auch, Pos. 9 erhält auch die 6, nur Position 6 erhält auch die 1, obwohl hier die 2 hingehört und pos. 7 hat dann die 2, die aber beim Rechnen nicht beachtet wird, da an der Stelle ein Operator steht der nicht abgefragt wird da es ne Klammer ist.
Am besten baue ich euch mal die Arrays hier auf.
Operator{'+','(','*',')','-','(','/',')','+',' ',...}
vNumber{1,2,3,4,5,6,0...}
Ist ziemlich kompliziert, gebe ich zu.
Wenn ihr noch Infos braucht, einfach sagen, ich bemüh mich dann diese zu liefern.
jaenicke - Do 29.03.07 16:00
Also ich werd mir das mal ansehen, aber was ich mich frage ist: Warum so kompliziert?
IMHO ist es deutlich einfacher eine Baumstruktur zu verwenden. So habe ich das auch gemacht, als ich symbolische Berechnungen durchführen wollte. Ganz nebenbei ist es so relativ einfach auch Ableiten und Integrieren einzubauen (naja Integrieren ist noch nicht fertig...).
Aber das wollte ich nur mal anmerken, deine Lösung werde ich mir mal ansehen, der Fehler muss ja zu finden sein.
Xardas008 - Do 29.03.07 17:15
Von Baumstruktur habe ich bisher noch nichts gehört, ka wie die gehen soll. Ich weiß ich programmiere irgendwie immer etwas zu kompliziert, sodass ich meistens später nicht mehr weiß was ich grade überhaupt gemacht habe lol^^
Xardas008 - Fr 30.03.07 08:48
Wo kann ich etwas über diese Baumstruktur nachlesen, vielleicht bekomme ich das Problem damit eher gelöst.
Narses - Fr 30.03.07 10:46
Moin!
Eine weitere, weit verbreitete Methode, die Operatorenrangfolge abzubilden, ist ein (Calculator-)Stack, also ein Kellerspeicher. Schau mal, ob du damit und geeigneten eigenen Klassen für Operatoren, die du dann mit den Argumenten in den Stack packst, weiter kommst. ;) Zumindest der Stack (= TStack) ist schon bei Delphi dabei. :idea:
cu
Narses
Xardas008 - Fr 30.03.07 15:07
So hab die letzten 15 Min nochmal rumexperimentiert, bis zu einer bestimmten Anzahl von Operatoren geht es gut, also oben genanntes Rechenbeispiel löst er nun richtig, aber kommt ein *2 am Ende dazu, gehts schief, dann haben wir eine Abweichung von 2, weil er statt der 6 an Pos. 10 eine 2 stehen hat.
Wie würde oben genanntes Beispiel als Baumstruktur gelöst? Oder wie kann man das sonst lösen dass der Array richtig zugeordnet wird?
Xardas008 - Mo 02.04.07 06:51
Das Problem ist immer noch nicht gelöst.
Xardas008 - Di 03.04.07 06:30
So, hab das Problem mal auf eine andere Weise gelöst, nur an einer Stelle hapert es irgendwie, wodurch eine Endlosschleife endsteht.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| while s > 0 do begin term_str := copy(Input, s+1,pos(copy(Input, s+1, length(Input)), ')')-1); erg := GetResult(term_str); Input := copy(Input, 0, s-1)+ erg + copy(Input,s+1, pos(copy(Input, s+1, length(Input)), ')')+1); s := Get_Pos_In_Str(Input, s, Ebene); end; |
term_str soll bei folgendem Beispiel: 1+(2*3-(1+2))die innerste Klammer nehmen, und den Teilstring 1+2 in den term_str kopieren, nur irgendwie kopiert er dort nur einen Leeren String rein, obwohl er bei Get_Pos_In_Str die richtige Position bekommt. Warum????
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!