Autor Beitrag
→Tobi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 23



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 56

Kubuntu 9.04 Jaunty
Mono 2.4 + MonoDevelop 2.0; Qt Creator
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 23



BeitragVerfasst: Mo 09.02.09 18:51 
Genau so etwas habe ich gesucht! Eben eine Funktion wie 'Char.IsNumber()'.
JüTho
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
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
BeitragVerfasst: Mo 09.02.09 19:09 
user profile icon→Tobi hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mo 09.02.09 19:17 
user profile iconJüTho hat folgendes geschrieben Zum zitierten Posting springen:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
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
BeitragVerfasst: Mo 09.02.09 20:03 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 23



BeitragVerfasst: 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)


ausblenden volle Höhe C#-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:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Parser
{
    class Program
    {
        static void Main(string[] args)
        {
            // Version 0.01 - Eingabe verarbeiten

            int i = 0;
            String Term = "";
            List<String> Teile = new List<string>();
            bool IstZahl = false;

            Term = Console.ReadLine();

            // Eingabe in ein dynamisches Array schreiben
            for (i = 0; i < Term.Length; i++)
            {
                Teile.Add(Term.Substring(i, 1));
            }

            // Array durchlaufen und Zahlen verknüpfen
            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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
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
BeitragVerfasst: 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:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
// Eingabe in ein dynamisches Array schreiben
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:
ausblenden C#-Quelltext
1:
2:
3:
4:
// Array durchlaufen und Zahlen verknüpfen
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4798
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Di 10.02.09 18:08 
user profile iconTh69 hat folgendes geschrieben Zum zitierten Posting springen:
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).
Ja, sowas habe ich im Studium gelernt. Das war eine der (fand ich) schwereren LV. :mrgreen:

user profile iconTh69 hat folgendes geschrieben Zum zitierten Posting springen:
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.
Ja, mit dem Expression Tree werkele ich gerade ein wenig herum. Sowas hatte ich letztlich vor. Wenn man das richtig macht, dauert das aber ne Weile, vor allem, wenn man C# noch nicht so gut kennt. ;-)

Aber ich arbeite mich gerade in C# und parallel PHP besser ein, da ist das ne ganz gute Übung, weil es auch interessant ist.
&#8594;Tobi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 23



BeitragVerfasst: 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 ^^.
ausblenden volle Höhe C#-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:
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)
        {
            // Version 0.02 - Strichrechnung

            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();

            // Eingabe in ein dynamisches Array schreiben
            for (i = 0; i < Term.Length; i++)
            {
                Teile.Add(Term.Substring(i, 1));
            }

            // Array durchlaufen und Zahlen verknüpfen
            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;
                }

            }

            // Strichrechnung
            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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4798
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: 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...