Autor |
Beitrag |
→Tobi 
      
Beiträge: 23
|
Verfasst: Mo 09.02.09 18:35
Ok. Also wenn ich nun anfange die Elemente der Liste mit den ganzen Zeichen zusammenzufassen - also "2", "6", "+", "7" wird zu "26", "+", "7" - wie mach ich das am besten? Eine Möglichkeit wäre ja ein Zahlenarray festzulegen, zu prüfen ob das Zeichen in diesem enthalten ist - also eine Zahl ist. Wenn das bei aufeinanderfolgenden Zeichen zutrifft, werden sie zusammengefügt. Meine Frage: Gibt es einen schnelleren Weg?
|
|
AdrianK
      
Beiträge: 56
Kubuntu 9.04 Jaunty
Mono 2.4 + MonoDevelop 2.0; Qt Creator
|
Verfasst: Mo 09.02.09 18:41
Dazu hab ich mir eine kleine Funktion CheckNumber geschrieben (Char.IsNumber)
Das ersetzen machst du einfach mit List.Repleace
Zuletzt bearbeitet von AdrianK am Mo 09.02.09 18:54, insgesamt 1-mal bearbeitet
|
|
→Tobi 
      
Beiträge: 23
|
Verfasst: Mo 09.02.09 18:51
Genau so etwas habe ich gesucht! Eben eine Funktion wie 'Char.IsNumber()'.
|
|
JüTho
      
Beiträge: 2021
Erhaltene Danke: 6
Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
|
Verfasst: Mo 09.02.09 19:09
→Tobi hat folgendes geschrieben : | Genau so etwas habe ich gesucht! Eben eine Funktion wie 'Char.IsNumber()'. |
Na sowas, wieso hast Du das nicht selbst schnell gefunden? Ein Blick in die SDK-Doku/MSDN unter "Char-Struktur / Alle Member" liefert u.a. IsNumber und IsDigit. Jürgen
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mo 09.02.09 19:17
JüTho hat folgendes geschrieben : | Na sowas, wieso hast Du das nicht selbst schnell gefunden? |
Na, zur Verteidigung: Nenne mir einen Grund, warum diese komische Methode statisch ist  . Aber Google sollte natürlich ebenso schnell zur gleichen Methode führen.
_________________ >λ=
|
|
JüTho
      
Beiträge: 2021
Erhaltene Danke: 6
Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
|
Verfasst: Mo 09.02.09 20:03
Kha hat folgendes geschrieben : | Nenne mir einen Grund, warum diese komische Methode statisch ist |
Weil MS bei manchen Sachen gewürfelt hat, wie es zu realisieren ist? Jürgen
|
|
→Tobi 
      
Beiträge: 23
|
Verfasst: Mo 09.02.09 21:42
Also für alle die auf der Suche nach der Lösung für einen Parser sind (so wie ich). Hier kommt Teil 1: Das Spalten der Eingabe in Zahlen und Rechenzeichen: (für die Konsole)
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:
| using System; using System.Collections.Generic; using System.Linq; using System.Text;
namespace Parser { class Program { static void Main(string[] args) { int i = 0; String Term = ""; List<String> Teile = new List<string>(); bool IstZahl = false;
Term = Console.ReadLine();
for (i = 0; i < Term.Length; i++) { Teile.Add(Term.Substring(i, 1)); }
for (i = 0; i < Teile.Count; i++) { if (Char.IsNumber(Teile[i], 0)) { if (IstZahl) { Teile[i] = Teile[i - 1] + Teile[i]; Teile.RemoveAt(i - 1); i--; } IstZahl = true; } else { IstZahl = false; }
}
Console.ReadLine(); } } } |
Ich hoffe es macht niemandem etwas aus, dass ich hier eine Art schrittweise Anleitung schreibe. Ich meine es wäre wohl nicht sinnvoll wenn ich direkt ein ganzes HowTo schreibe. Aus dem einfachen Grund, dass ich es selbst noch nicht kann^^. Also ergänze ich einfach immer den vorherigen Code mit meinem neuen Wissen - gewonnen aus den Kommentaren.
Man bin ich ein toller Autor! ^^
|
|
JüTho
      
Beiträge: 2021
Erhaltene Danke: 6
Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
|
Verfasst: Di 10.02.09 11:36
Hallo,
für alle, die hier Kommentare schreiben wollen: Ich wollte eigentlich wie folgt eine Änderung vorschlagen.
*******************************************************************
die erste for-Schleife und die List<string> kannst Du Dir schenken:
C#-Quelltext 1: 2: 3: 4: 5:
| for (i = 0; i < Term.Length; i++) { Teile.Add(Term.Substring(i, 1)); } |
Ein String kann auch wie ein char-Array behandelt werden. Du kannst also an allen folgenden Stellen (wie im folgenden Ausschnitt) Teile bzw. Teile[i] durch Term bzw. Term[i] ersetzen:
C#-Quelltext 1: 2: 3: 4:
| for (i = 0; i < Term.Length; i++) { if (Char.IsNumber(Term[i])) |
*******************************************************************
Aber diese Änderung bringt nichts. Tobi möchte die Zahlen in der List<string> zusammensetzen und zwischenspeichern. Für dieses Verfahren braucht er natürlich Strings und kann nicht (wie mein Ansatz) mit Chars auskommen.
Ich würde es nicht so machen, sondern so schnell wie möglich die Substrings in "echte" Zahlen konvertieren. Aber es ist ein möglicher Weg; dann bringt die "Verkürzung" über Term[i], d.h. den String als char-Array zu behandeln, nichts.
Jürgen
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Di 10.02.09 16:26
Sorry, aber ich kriege immer die Krise, wenn irgendwelche Halbprofis versuchen, selber einen Parser zu entwickeln.
Zuersteinmal sollte man sich mit dem Begriffen "EBNF (Enhanced Backus Naur Form)" und "Grammatik" auseinandersetzen und daraus dann einen möglichst einfachen Parser entwickeln (z.B. Top-Down 1 Step-Ahead). Unter C++ würde ich dafür jetzt 'boost.spirit' empfehlen, aber leider gibt es so etwas noch nicht für C#.
Das ganze Rumfrickeln mit Strings und Klammerung etc. führt meistens immer in eine Sackgasse, da die Operator-Prioritäten ja auch noch bedacht werden müssen...
PS: Einen Beispielparser (in C++ mit dem BCB entwickelt) könnt ihr euch mal unter www.bitel.net/dghm11...ctParser-Sources.zip ansehen.
Noch ein PS:
Zitat: |
Das ist zwar noch sehr, sehr hochgegriffen - aber wäre es möglich ein Programm zu schreiben, dass eine Formel vereinfacht? Zum Beispiel "225x - 175x + (-45x)".
|
Hierfür reicht ein Parser nicht aus, sondern dann benötigt man den schon erwähnten Expression Tree. Und anhand von Rechenregeln werden dann Baum-Umformungen durchgeführt und zum Schluß erst wieder in einen Text zurücktransformiert. So ein Programm habe ich damals als Studi (noch in C) geschrieben, jedoch den Source irgendwo zuhause auf einem Rechner (bei Interesse könnt ich ihn ja mal rauskramen...)
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 10.02.09 18:08
|
|
→Tobi 
      
Beiträge: 23
|
Verfasst: Mo 16.02.09 22:32
Nun gut. Hier kommt endlich der zweite Teil: Strichrechnung mit Klammern. Ich weiß - es gibt bestimmt ein Dutzend Möglichkeiten es besser zu machen. Und über Verbesserungsvorschläge bin ich auch dankbar. Sie sollten bloß in den Grenzen des Machbaren für einen Schüler liegen ^^.
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: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83:
| using System; using System.Collections.Generic; using System.Linq; using System.Text;
namespace Parser { class Program { static void Main(string[] args) { int i = 0, Anfang = 0; String Term = ""; List<String> Teile = new List<string>(); bool IstZahl = false; double Zahl1 = 0, Zahl2 = 0, Ergebnis = 0;
Term = Console.ReadLine();
for (i = 0; i < Term.Length; i++) { Teile.Add(Term.Substring(i, 1)); }
for (i = 0; i < Teile.Count; i++) { if (Char.IsNumber(Teile[i], 0)) { if (IstZahl) { Teile[i] = Teile[i - 1] + Teile[i]; Teile.RemoveAt(i - 1); i--; } IstZahl = true; } else { IstZahl = false; }
}
while (Teile.Count > 1) { try { if (Teile[Anfang + 2] == "(") { Anfang += 3; continue; } } catch { }
if (Teile[Anfang + 1] == ")") { Teile.RemoveAt(Anfang - 1); Teile.RemoveAt(Anfang); Anfang = 0; continue; } Zahl1 = Convert.ToDouble(Teile[Anfang]); Zahl2 = Convert.ToDouble(Teile[Anfang + 2]); if (Teile[Anfang + 1] == "+") Ergebnis = Zahl1 + Zahl2; if (Teile[Anfang + 1] == "-") Ergebnis = Zahl1 - Zahl2; Teile[Anfang + 2] = Convert.ToString(Ergebnis); Teile.RemoveAt(Anfang); Teile.RemoveAt(Anfang); }
Console.WriteLine(Teile[0]); Console.ReadLine(); } } } |
Es gibt nur ein paar kleine Hacken:
- Man darf die gesamte Rechnung nicht in Klammern schreiben.
Bsp: (12+(12-35+(35+4))). Richtig wäre: 12+(12-35+(35+4))
- Klammern müssen richtig gesetzt werden. Man darf auch keine weglassen
Klar. Das sind Kleinigkeiten, die man leicht beheben kann. Sie machen den Code bloß unnötig unübersichtlich. Darum habe ich sie weggelassen. Über einen Try-Block um die Schleife wäre allerdings noch mal nachzudenken damit das Programm bei falscher Eingabe nicht einfach den Geist aufgibt. 
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mo 01.06.09 12:44
Ich habe nun auch meinen Formel-Parser nach C# übersetzt:
www.mycsharp.de/wbb2...=3545284#post3545284
(gesamte Projekt als Dateianhang im Hauptbeitrag)
Dieser darf dann gerne als Referenzprojekt angesehen werden...
|
|