Pedro Geschrieben 25. Februar 2009 Geschrieben 25. Februar 2009 Hallo liebe C# Programmierer, Ich hoffe das meine Frage hier richtig ist, wenn nicht entschuldigt das bitte. Zu meiner Frage: Ich soll für eine firma wo ich mich beworben hab nen Taschenrechner in C# programmieren. Dazu nutze ich Microsoft Visual C# express. Mein Problem dabei ist nun das der Rechner die Regeln Punktrechnung geht vor Strichrechnung und Quadrieren geht über alles beinhalten soll. Wie kann ich das realisieren? Bitte um schnelle Hilfe!:hells: Zitieren
flashpixx Geschrieben 25. Februar 2009 Geschrieben 25. Februar 2009 Schau Dir dazu einmal die "polnische Notation" und Ableitungsbäume bzw Syntaxbaum an. Polnische Notation ? Wikipedia Syntaxbaum ? Wikipedia Phil Zitieren
Shogoki Geschrieben 25. Februar 2009 Geschrieben 25. Februar 2009 Hast du denn schon mal nen kleinen Ansatz? Wenn ja wäre mal ein bischen Code ganz interesant. Ich hab mal nen Taschenrechner in VB.NET geschrieben. Der funtionierte aber praktich nur wie ein normaler Handtaschenrechner. Also man hat die zahl eingegeben aufs Rechenzeichen geklickt und dann hat der das erst gerechnet und so weiter (Also er konnte die "KlaPoPuST" -Regel wie unser Mathe Lehrer er sie genannt hat xD (Klammer vor Potenz vor Punkt vor Strich) nicht) Daher wärs mal interesant wie du die Sache überhaupt angehst. Gibt ja mehrere möglichkeiten. Zitieren
kross Geschrieben 26. Februar 2009 Geschrieben 26. Februar 2009 so sollte es relativ einfach gehen -eingabe (werte und operanten merken) -anschließend aus dieser liste die operationen von der höchsten zur kleinsten priorität abarbeiten -bleibt nurnoch ein wert und keine operation mehr hat man das ergebnis zu tun erstmal ein neues leeres form erstellen und 6 buttons adden und code einfügen das beispielprojekt hat nur addition, multiplikation und potenzieren und als wert nur die zahl 3 -erweitern um ziffern {0..9}/3 -ziffern untereinander zu zahlen zusammenfassen (sind 2 werte an stelle i in der liste ohne rechenoperation benachbart wert=wert*10+wert[i+1], lösche wert[i+1]) -erweitern um subtraktion/division -fehlerbehandlung (doppelte rechenoptoren abfangen etc) using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace WindowsApplication5 { public partial class Form1 : Form { private List<Teil> m_teile; public enum operation { plus, minus, mal, durch, hoch, } public Form1() { InitializeComponent(); button1.Text = "3"; button2.Text = "+"; button3.Text = "*"; button4.Text = "^"; button5.Text = "Neu"; button6.Text = "="; m_teile = new List<Teil>(); } private void button1_Click(object sender, EventArgs e) { m_teile.Add(new Teil(3)); } private void button2_Click(object sender, EventArgs e) { m_teile.Add(new Teil(Operation.plus)); } private void button3_Click(object sender, EventArgs e) { m_teile.Add(new Teil(Operation.mal)); } private void button4_Click(object sender, EventArgs e) { m_teile.Add(new Teil(Operation.hoch)); } private void button5_Click(object sender, EventArgs e) { m_teile = new List<Teil>(); } private void button6_Click(object sender, EventArgs e) { //schrittweise aufloesen //erster schritt die ziffern zu zahlen zusammenfassen //!!!!todo im beispiel nur mit einstelligen ziffern gearbeitet //zweiter schritt potenzen ausrechnen //rechten und linken operand + rechenzeichen aus der liste löschen //ergebnis an deren stelle einfügen for (int i = 0; i < m_teile.Count; i++) { if (m_teile[i].Art == Teil.ArtEnum.RechenOperation && m_teile[i].Operation == Operation.hoch) { int erg = (int)Math.Pow(m_teile[i - 1].Wert, m_teile[i + 1].Wert); m_teile[i - 1].Wert = erg; //wert vor dem operand wird überschrieben spart herrauslöschen und anschließendes neu einfügen m_teile.RemoveRange(i, 2); i--;//i um eins verringern da durch das löschen der aktuellen position dort nun ein noch nicht verarbeiteter wert steht } } //dritter schritt multiplizieren (todo dividieren) for (int i = 0; i < m_teile.Count; i++) { if (m_teile[i].Art == Teil.ArtEnum.RechenOperation && m_teile[i].Operation == Operation.mal) { int erg = m_teile[i - 1].Wert * m_teile[i + 1].Wert; m_teile[i - 1].Wert = erg; //wert vor dem operand wird überschrieben spart herrauslöschen und anschließendes neu einfügen m_teile.RemoveRange(i, 2); i--;//i um eins verringern da durch das löschen der aktuellen position dort nun ein noch nicht verarbeiteter wert steht } } //letzter schritt addieren (todo subtrahieren) for (int i = 0; i < m_teile.Count; i++) { if (m_teile[i].Art == Teil.ArtEnum.RechenOperation && m_teile[i].Operation == Operation.plus) { int erg = m_teile[i - 1].Wert + m_teile[i + 1].Wert; m_teile[i - 1].Wert = erg; //wert vor dem operand wird überschrieben spart herrauslöschen und anschließendes neu einfügen m_teile.RemoveRange(i, 2); i--;//i um eins verringern da durch das löschen der aktuellen position dort nun ein noch nicht verarbeiteter wert steht } } //m_teile sollte nurnoch 1 eintrag haben dieser ist das ergebnis MessageBox.Show(m_teile[0].Wert.ToString()); } } public enum Operation { plus, minus, mal, durch, hoch, } public class Teil { private ArtEnum m_art; public ArtEnum Art { get { return m_art; } } private Operation m_operation; public Operation Operation { get { return m_operation; } } private int m_wert; public int Wert { get { return m_wert; } set { m_wert = value; } } public Teil(Operation _op) { m_art = ArtEnum.RechenOperation; m_operation = _op; } public Teil(int _wert) { m_wert = _wert; m_art = ArtEnum.Wert; } public enum ArtEnum { RechenOperation, Wert } } } Max01 reagierte darauf 1 Zitieren
flashpixx Geschrieben 26. Februar 2009 Geschrieben 26. Februar 2009 Warum schreibst Du nicht zuerst einmal Deine komplette Berechnung in einen Syntaxbaum und traversierst diesen dann entsprechend. In den Blättern stehen die Zahlen, in den Knoten die Operatoren. Damit hast direkt Punkt vor Strichrechnung usw, sowie korrekte Klammerverarbeitung? Phil Max01 reagierte darauf 1 Zitieren
Pedro Geschrieben 26. Februar 2009 Autor Geschrieben 26. Februar 2009 Danke euch schonmal für die antworten auch wenn ich nicht seeehr schlau draus werde da ich noch so gut wie keine erfahrung mit C# hab^^ ich hab gerade gesehen das in meiner aufgabe steht:" Er muss keine grafische Oberfläch haben" heißt das jetz das ich das als Konsolen Applikation schreiben kann? Zitieren
flashpixx Geschrieben 26. Februar 2009 Geschrieben 26. Februar 2009 Danke euch schonmal für die antworten auch wenn ich nicht seeehr schlau draus werde da ich noch so gut wie keine erfahrung mit C# hab^^ Meine Postings beziehen sich nicht auf eine Umsetzung in C# sondern um die theoretischen Grundlagen für die Problemlösung heißt das jetz das ich das als Konsolen Applikation schreiben kann? Sicher. Ich verstehe es so, dass eine Konsolenanwendung ausreichend ist, obwohl man ja auch ein Form machen kann, in dem man die zu berechnende Funktion auch als String in ein Textfeld eingeben kann. Die Progammlogik bleibt gleich Phil Max01 reagierte darauf 1 Zitieren
Pedro Geschrieben 28. Februar 2009 Autor Geschrieben 28. Februar 2009 So ich hab mal nen lösungsansatz, ich lasse jetz die Zahlen und Rechenzeichen in Arrays einlesen: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Taschenrechner_Obeta { class Program { static void Main(string[] args) { int[] Zahlen = new int[1000]; string[] zeichen = new string[500]; int i, k; //Zählvariable i wird auf 0 gesetzt i = 0; //Zählvariable k wird auf 0 gesetzt k = 0; //Begin der Programmierung //try = versuchen dies zu machen,bei einem fehler kommt "catch" ausgabe try { while (zeichen[k] != "=") { Console.WriteLine("Bitte geben Sie eine Zahl ein!"); Zahlen[i] = Convert.ToInt32(Console.ReadLine()); i = i + 1; Console.WriteLine("Nun das Rechenzeichen!"); zeichen[k] = Convert.ToString(Console.ReadLine()); k = k + 1; } } catch { Console.WriteLine("Bitte achten sie auf ihre eingabe! Starten sie das Programm neu!"); } } } } Nun nur mein Problem, wie kann ich die Zeichen überprüfen lassen obs ne Punkt oder Strichrechnung ist? Zitieren
flashpixx Geschrieben 28. Februar 2009 Geschrieben 28. Februar 2009 Nun nur mein Problem, wie kann ich die Zeichen überprüfen lassen obs ne Punkt oder Strichrechnung ist? So wie Du es programmierst gar nicht, denn deine Operatoren haben alle die gleiche Priorität. Der Ausdruck 3+4*2 wird von links sequentiell verarbeitet, d.h. 3+4 = 7 * 2 = 14, mathematisch korrekt: 3+(4*2) = 3+8 = 11. Grundsätzlich würde ich dir die Präfixnotation +3*4 2 empfehlen, so dass die Operatoren zuerst stehen, damit sind die Operatoren entsprechend priorisiert, das ganze empfiehlt sich dann in einen Baum zu speichern, denn du für die Berechnung nur einmal traversieren musst. Phil Zitieren
Pedro Geschrieben 28. Februar 2009 Autor Geschrieben 28. Februar 2009 Grundsätzlich würde ich dir die Präfixnotation +3*4 2 empfehlen Das wurde mir auch schon oft gesagt, frage ist nur wie ich das in C# umsetze, hab dazu nix im Web gefunden... das ganze empfiehlt sich dann in einen Baum zu speichern, denn du für die Berechnung nur einmal traversieren musst. Auch dazu hab ich leider nichts gefunden... kannst du mir als anfänger da n bissl behilflich sein? Zitieren
flashpixx Geschrieben 28. Februar 2009 Geschrieben 28. Februar 2009 kannst du mir als anfänger da n bissl behilflich sein? Es wird dafür keine fertige Lösung in der Form, wie Du sie brauchst, existieren. Du musst die Eingabe einmal komplett als String lesen und dann auftrennen und in eine Baumstruktur einfüllen. Du musst in C# eben eine für Dich passende Struktur selbst erstellen (Baum (Graphentheorie) ? Wikipedia). Noch als Hinweis: Wenn Dir schon mehrfach Ratschläge gegeben wurde, dann musst Du Dich eben hinsetzen und eine Lösung selbstständig entwickeln. Die Präfixnotation ergibt sich automatisch aus der Baumstruktur, wenn Du in die Knoten die Operatoren und in die Blätter die Werte füllst. Traversierst (preoder) Du den Baum und gibst ihn als String aus, erhälst Du die Präfixnotation, die Du direkt arithmetisch verarbeiten kannst. Phil Zitieren
AndiE Geschrieben 28. Februar 2009 Geschrieben 28. Februar 2009 Hallo Pedro, so ganz kann ich dir nicht abnehmen, dass du Anfänger bist. Nach dem ersten Post hast du die Aufgabe bekommen, weil du dich in der Firma beworben hast. Also erwartet man da was von dir. LG André Zitieren
Pedro Geschrieben 2. März 2009 Autor Geschrieben 2. März 2009 Naja also richtig Anfänger bin ich nicht aber die Sprache C# benutze ich zum ersten mal. Weiterhi habe ich eigentlich nur Ausrechende Kenntnisse in Delphi Zitieren
flashpixx Geschrieben 3. März 2009 Geschrieben 3. März 2009 Weiterhi habe ich eigentlich nur Ausrechende Kenntnisse in Delphi Dann entwirf Deinen Code zuerst mal in Delphi und übersetze ihn. Phil Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.