Benötige Hilfe bei Programm in C++
-
suppenkasper61194 schrieb:
Bisher habe ich bis Rechnungen mit 3 Zahlen programmiert. Leider gibt mein Compiler (Dev C++) immer wieder Fehlermeldungen aus
devc++ ist eine IDE und kein Compiler, außerdem ist das Zeug furchtbar veraltet und verbugt. Nimm was anders, Code::Blocks z.B.
Schau dir Flex & Bison. Es gibt davon jeweils eine cygwin Portierung, die kannst du dann verwenden.
-
Dieser Thread wurde von Moderator/in rüdiger aus dem Forum Rund um die Programmierung in das Forum C++ verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Wie angetönt ist das Thema nicht gerade Trivial (im Sinne, dass man das eben mal so machen kann).
Und da du anscheinend Anfänger bist würde ich dir eher dazu raten dich mal ein wenig mehr mit C++ zu beschäftigen. Klassen, Funktionen, Arrays usw. sind Themen, die bei dir bestimmt noch nicht fest sitzen.Ohne (zumindest) diese Grundkenntnisse ist es sehr umständlich etwas grösseres zu machen.
-
Hi,
versuch erst mal entweder den ganzen "Rechenaufgabenstring" insgesamt zu lesen und dann zeichenweise zu verarbeiten oder gleich einzelzeichenweise lesen und verarbeiten.
Du musst erst mal klären, aus was für Einzelelementen Deine Eingabe bestehen darf (Zahlen, Zahlenformate, Operandenzeichen, Klammern, Variablen, Funktionen...). Dann das erste Zeichen einlesen und auf Grund dessen entscheiden, was es für ein Element ist. Danach Zeichen für Zeichen auswerten und jeweils entscheiden ob es noch zum aktuellen Element passt oder ein Zwischenraum ist oder das nächste Element anfängt. Dann im Prinzip zwei Stapel auf denen jeweils Anweisungen und Operanden abgelegt werden. Nach dem fertigen parsen dann berechnen und Ergebnis zurück schreiben. Wenn man die gültigen Rechenregeln (Punkt vor Strich...) beachten will, ist es nicht ganz trivial. Aber da machen ja heute nicht mal mehr einfache Taschenrechner.
Ein anderer Weg wäre die gesamte Formel in Umgekehrt-Polnische-Notation umwandeln und dann mit einem einfachen Stapel abarbeiten. So arbeitet soviel ich weiß auch Excel.Gruß Mümmel
-
Unser guter Stroustrup macht in seinem Buch "Programming" so einen Parser für Arithmetik schon in Kapitel 6, es funktioniert durchaus, auch ohne große C++-Kentnisse. Dabei geht er auch schön auf kontextfreie Grammatiken ein etc. Die Erläuterungen und Übungen sind sehr zu empfehlen!

-
Ad aCTa schrieb:
Unser guter Stroustrup macht in seinem Buch "Programming" so einen Parser für Arithmetik schon in Kapitel 6, es funktioniert durchaus, auch ohne große C++-Kentnisse. Dabei geht er auch schön auf kontextfreie Grammatiken ein etc. Die Erläuterungen und Übungen sind sehr zu empfehlen!

Ist es das hier ?
-
DocShoe schrieb:
Ad aCTa schrieb:
Unser guter Stroustrup macht in seinem Buch "Programming" so einen Parser für Arithmetik schon in Kapitel 6, es funktioniert durchaus, auch ohne große C++-Kentnisse. Dabei geht er auch schön auf kontextfreie Grammatiken ein etc. Die Erläuterungen und Übungen sind sehr zu empfehlen!

Ist es das hier ?
japp, genau
-
Hallo,
Ichn habe mit dem Buch "C++ -die professionelle Referenz" einen Parser programmiert und ihn in eine IF-Verzweigung eingebaut. Der Compiler hat nichts zu merckern, aber totzdem kann ich mit dem Programm nichts rechnen. Was habe ich da falsch gemacht?
Hier der Quelltext:
#include <iostream> #include <stdlib.h> #include <cmath> #include <cstdlib> #include <string> #include <cstdio> #include <fstream> #include <vector> using namespace std; // ANFANG PASER ------------------------------------------------ enum types { DELIMITER = 1, VARIABLE, NUMBER}; class parser { char *exp_ptr; // Zeigt den Ausdruck char token[80]; // speichert aktuelles token char tok_type; // speichert Typ des Token void eval_exp2(double &result); void eval_exp3(double &result); void eval_exp4(double &result); void eval_exp5(double &result); void eval_exp6(double &result); void atom(double &result); void get_token(); void serror(int error); int isdelim(char c); public: parser(); double eval_exp(char *exp); }; //Konstruktor parser::parser() { exp_ptr = NULL; } // Einstiegspunkt des Parsers. double parser::eval_exp(char *exp) { double result; exp_ptr = exp; get_token(); if(!*token) { serror(2); // kein Ausdruck verhanden return 0.0; } eval_exp2(result); if(*token) serror(0); // letztes Token = 0 return result; } // Addiere oder Subtrahiere 2 Terme void parser::eval_exp2(double &result) { register char op; double temp; eval_exp3(result); while((op = *token) == '+' || op == '-') { get_token(); eval_exp3(temp); switch(op) { case '-': result = result - temp; break; case '+': result = result + temp; break; } } } // Multipliziere oder Dividiere 2 Faktoren. void parser::eval_exp3(double &result) { register char op; double temp; eval_exp4(result); while((op = *token) == '*' || op =='/' || op == '%') { get_token(); eval_exp4(temp) ; switch(op) { case '*': result = result * temp; break; case '/': result = result / temp; break; case '%': result = (int) result % (int) temp; break; } } } // Verarbeite Exponenten. void parser::eval_exp4(double &result) { double temp, ex; register int t; eval_exp5(result); if(*token== '^') { get_token(); eval_exp4(temp); ex = result; if(temp == 0.0) { result = 1.0; return; } for(t=(int)temp-1; t > 0; --t) result = result *(double)ex; } } //Werte uniäres + oder - aus. void parser::eval_exp5(double &result) { register char op; op = 0; if((tok_type == DELIMITER) && *token=='+' || *token =='-') { op = *token; get_token(); } eval_exp6(result); if(op=='-') result = -result; } // Verarbeite geklammerte Ausdrücke. void parser::eval_exp6(double &result) { if((*token == '(')) { get_token(); eval_exp2(result); if(*token == ')') serror(1); get_token(); } else atom(result); } // Hole den Wert einer Zahl. void parser::atom(double &result) { switch(tok_type) { case NUMBER: result =atof(token); get_token(); return; default: serror(0); } } //zeige einen Syntaxfehler an. void parser::serror(int error) { static char *e[]= { "Syntaxfehler" "Klammern nicht ausgeglichen" "Kein Ausdruck vorhanden" }; cout << e[error] << endl; } // Hole das nächste Token void parser::get_token() { register char* temp; tok_type = 0; temp = token; *temp = '\0'; if(!*exp_ptr) return; // am Ende des Ausdrucks while(isspace(*exp_ptr)) // Leerraum überspringen ++exp_ptr; if(strchr("+-*/%^=()", *exp_ptr)) { tok_type = DELIMITER; // Zum nächsten Zeichen *temp++ = *exp_ptr++; } else if(isalpha(*exp_ptr)) { while(!isdelim(*exp_ptr)) *temp++ = *exp_ptr++; tok_type = VARIABLE; } else if(isdigit(*exp_ptr)) { while (!isdelim(*exp_ptr)) *temp++ = *exp_ptr++; tok_type = NUMBER; } *temp = '\0'; } // Gib true zurück, wen c ein Trennzeichen ist. int parser::isdelim(char c) { if(strchr(" +-/*%^=()", c) || c == 9 || c=='\r' || c==0) return 1; return 0; } // ENDE PARSER -------------------------------------------------- int main() { //Anfang char Eingabe_Schleife_1; char j; char n; char neustart; do { int Eingabe_Weg; // für die zur Auswahl stehenden Rechenoperationen double Eingabe_3; double Eingabe_10; double Eingabe_11; double Quadrat_1; double Wurzel_1; double Celsius_1; int Primzahl_1; int Eingabe_PR; double Quadrat_2; double Quadratzahl_1; double Quadrateingabe; double zahl1; double zahl2; double zahl3; char operator1; char operator2; double ergebnis; double ergebnis2; bool bool1 = zahl3; bool bool2 =operator2; char EG_LA; cout << "Taschen- und Formelrechner:" << endl << endl; cout << "Hier sehen Sie eine Tabelle mit den ausfuehrbaren Rechenoperationen." << endl; cout << "Waehlen Sie eine Rechenoperation, indem Sie die benoetigte Zahl eingeben und mit ENTER bestaetigen!" << endl << endl; // Allgemeiner Text cout << "Bitte beachten Sie, dass Kommas als Punkte geschrieben werden muessen." << endl << endl; cout << "Taschenrechner (+,-,*,/) (1)" << endl; // Anfang der zur Auswahl stehenden Rechenoperationen... cout << "Quadrierung (2)" << endl; cout << "Wurzelberechnung (3)" << endl; cout << "Fahrenheit in Celsius umrechnen (4)" << endl; cout << "Prmzahlen ausgeben (5)" << endl; cout << "Die ersten 10 Quadratzahlen ausgeben (6)" << endl; cout << "zu Laendern die Hauptstädte ausgeben (7)" << endl; cout << endl; cin >> Eingabe_Weg; cout << endl << endl; // für die Übersichtlichkeit... { if (Eingabe_Weg == 1) { char expstr[80]; cout << "Eingabe von Punkt fuer Stop" << endl << endl; parser ob; cout << "Geben Sie etwas ein! " << endl << endl; cin.getline(expstr, 79); if(*expstr=='.') break; cout << "Das Ergebnis ist: " << ob.eval_exp(expstr) << endl; }; if (Eingabe_Weg == 2) // Quadrierung (2) { cout << "Quadrierung. Geben Sie eine Zahl ein und bestaetigen sie mit ENTER! " << endl << endl; cin >> Eingabe_3; Quadrat_1 = Eingabe_3 * Eingabe_3; cout << "Die Quadratzahl lautet: " << Quadrat_1 << endl; } if (Eingabe_Weg == 3) // Wurzelberechnung { cout << "Wurzelberechnung. Geben Sie eine Zahl ein und bestätigen sie mit ENTER!" << endl << endl; cin >> Eingabe_10; if (Eingabe_10 >= 0) { Wurzel_1 = sqrt(Eingabe_10); cout << "Die Wurzel ist " << Wurzel_1 << endl << endl; } else { cout << endl << "Diese Eingabe ist ungueltig. (Weil z.B. eingegebene Zahl negativ)" << endl; } } if (Eingabe_Weg == 4) // C in F { cout << "Geben Sie die Temperatur in Fahrenheit an und bestaetigen Sie mit ENTER!" << endl << endl; cin >> Eingabe_11; Celsius_1 = (Eingabe_11 - 32) * 5.0 / 9.0; cout << Eingabe_11 << " Grad Fahrenheit sind " << Celsius_1 << " Grad Celsius" << endl << endl; } if (Eingabe_Weg == 5) // Primzahlen ausgeben { cout << "Primzahlen-ausgabe. Diese Funktion gibt die ersten 100 Primzahlen aus. Druecken Sie ENTER!" << endl << endl; cin.get(); cin.get(); const int MaxPrimzahl=100; int Primzahl; int Divisor; bool istEinePrimzahl; cout << "Die Primzahlen von 0 bis 100 lauten: " << endl << endl; cout << "2"; for(Primzahl=3; Primzahl <=MaxPrimzahl; Primzahl++) { istEinePrimzahl=true; for(Divisor=2; istEinePrimzahl && Divisor<Primzahl; Divisor++) { if (0==Primzahl % Divisor) { istEinePrimzahl = false; } } if(istEinePrimzahl) { cout <<", " << Primzahl; } } cout << endl << endl; } if(Eingabe_Weg == 6) { double q; double Quadratzahl_2, Quadratzahl_3, Quadratzahl_4, Quadratzahl_5, Quadratzahl_6, Quadratzahl_7, Quadratzahl_8, Quadratzahl_9; cout << "Quadratzahlenberechnung. Geben Sie eine Zahl ein, von der die ersten 10 Quadzahlen bis berechnet werden sollen!" << endl << endl; cin >> Quadrateingabe; Quadratzahl_1 = Quadrateingabe * Quadrateingabe; Quadratzahl_2 = Quadrateingabe * Quadrateingabe * Quadrateingabe; Quadratzahl_3 = Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe; Quadratzahl_4 = Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe; Quadratzahl_5 = Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe; Quadratzahl_6 = Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe; Quadratzahl_7 = Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe; Quadratzahl_8 = Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe; Quadratzahl_9 = Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe * Quadrateingabe; cout << "Die ersten 10 Quadratzahlen von " << Quadrateingabe << " sind: " << Quadratzahl_1 << ", " << Quadratzahl_2 << ", " << Quadratzahl_3 << ", " << Quadratzahl_4 << ", " << Quadratzahl_5 << ", " << Quadratzahl_6 << ", " << Quadratzahl_7 << ", " << Quadratzahl_8 << ", " << Quadratzahl_9 << endl << endl << endl; } if(Eingabe_Weg == 8) { cout << "test " << endl << endl; } if(Eingabe_Weg == 7) { cout << "Geben sie das Land, von dem Sie die Hauptstadt wissen wollen, in RICHTIGER" << endl << "Rechtschreibung ein (Auch Gross -und Kleinschreibung!)" << endl << endl; cin >> EG_LA; if(EG_LA == 'Deutschland') { cout << "Berlin" << endl; } if(EG_LA == 'Frankreich') { cout << "Paris" << endl; } if(EG_LA == 'Polen') { cout << "Warschau" << endl; } } cout << "Wollen Sie das Programm neu starten? (j/n)" << endl << endl; cin >> neustart; } do { if (neustart!='j' && neustart!='J' && neustart!='n' && neustart!='N') { cout<<"Bei Ihrer Eingabe \"" << neustart << "\" handelt es sich um eine Falscheingabe!"<<endl<<endl; cout <<"Moechten Sie das Programm neustarten?(j/n)"<<endl<<endl; cin>>neustart ; } } while (neustart!='n' && neustart!='N' && neustart!='j' && neustart!='J'); } while (neustart!='n' && neustart!='N'); system ("Pause"); return 0; }Viele Grüße und Danke im voraus,
suppenkasper
-
Mit einem Debugger sollte sich das Problem doch eingrenzen lassen. Weiß nicht ob jmd Motivation hat über 400Zeilen Code zu analysieren.
-
c++hris schrieb:
Weiß nicht ob jmd Motivation hat über 400Zeilen Code zu analysieren.
Noch dazu mies eingerückten Code...
suppenkasper61194 schrieb:
...
Dein Code ist völlig unleserlich, und strotzt nur von Fehlern. Nachfolgend einige Empfehlungen und Fehlerangaben (ich bezweifel gar, das sich der Code ohne Fehler/Warnungen linken lässt):
0. Rücke Sinnvoll ein, du würdest dann auch leichter sehen wenn du öffnende oder schließende Klammern vergessen, oder zuviel gesetzt hast (Wenn ich es richtig sehe hat deine main-Funktion zuviele öffnende Klammern). Verwende dabei eine einheitliche Einrücktiefe (sei es nun per Leerzeilen oder Tabulatoren - aber bleib auch hier einheitlich).
1. Deklariere Variablen möglichst erst, wenn du sie auch benötigst.
2. Versuche Funktionen möglichst klein und überschaubar zu halten, lieber mehrere leicht zu überschauende Funktionen als eine riesige, die keiner sinnvoll überblicken kann.
3. Vermeide tiefe Verschachtelungen (dies kannst du unter anderem durch die Beherzigung von 2. erreichen).
4. Benenne Variablennamen so, das man auch versteht was darunter gemeint ist.
5. Variablen sollten niemals vor der Initialisierung selbiger verwendet werden.
6. Für die Lesbarkeit würde ich mir angewöhnen, niemals mehr als eine Anweisung in eine Zeile zu schreiben (z.B. würde ich "if(*expstr=='.') break;" in 2 Zeilen schreiben).
7. Ebenso würde ich nicht mehrere Variablen in einer Zeile deklarieren... Und statt einer Durchnummerierung empfiehlt sich ein Array (z.B. im Fall von double Quadratzahl_2...).
8. Mal lässt du (zu)viele Leerzeilen stehen, an anderer Stelle quetscht du den Code unnötig.
9. Schreibe Code in Etappen, teste diese und ergänze erst dann weiteren Code.
10. Der Datentyp "char" ist nur für die Aufnahme GENAU eines Zeichens ausgelegt (EG_LA), und ein string wird mit " nicht ' umschlossen. Letzeres wird nur für Einzelzeichen verwendet. hier solltest du lieber auf den Datentyp std::string (Header <string>) wechseln.
11. Was willst du bitte schön mit der Anweisung "bool bool1 = zahl3;" (zahl3 ist ein double, und zudem noch uninitialisiert), ebenso die Zeile danach?
12. Trenne Deklaration und Definition (Header/Source).
-
ok, ich werde den Code nochmal übersichtlicher "gestalten" und in den nächsten Tagen reinstellen .....
-
Lies dir unbedingt auch diesen Thread durch, dort hast du nämliche etliche Punkte missachtet.