Wenn kein Operator vor (
-
Moin Moin,
war ja abzusehen das ich wieder schreibe ne ?
bin jetzt bei einem weiteren Problem angekommen wo ich einfach mal wieder Ideen Anstoss brauche
Problem:
Wenn bei einer Funktion die Berechnet wird ein 2(2+2) eingegeben wird muss das Programm ja wissen das 2*(2+2) gemeint ist.
heißt es muss ein * zwischengefügt werden und dann weiter bearbeitet werden.
meine ersten Gedanken dazu:
If "Kein Operator" -J> bis ( strcpy in bla1 -> strcpy ab ( in bla2 -> An bla1 ein * anhängen -> beide str wieder zusammenführen (bla1*bla2).
wär das ein richtiger Ansatz? Und bei der überprüfung weiß ich noch nicht sogenau weiter. deshalb auch nur ein If "Kein Operator"...
Danke schonmal
gruß
Viro
-
Verstehe ich das richtig, dass du ein Rechenprogramm entwickeln willst, das auch komplexere Terme mit Klammern u.ä. verstehen soll?
Ein Ansatz wäre es, den Term in sog. Tokens zu unterteilen. Tokens für Zahlen, Tokens für verschiedene Operatorklassen. Und dann schaust du einfach nach, ob vor oder nach einem Zahltoken direkt ein Klammertoken kommt. Da kann man dann einfach ein Multiplikationstoken einfügen.
Das ganze sollte direkt im Parser geschehen. Da können dann auch Fehler wie -+ erkannt werden. Das Ergebnis des Terms sollte in einem anderen Modul entwickelt werden, an einer Stelle, wo die syntaktische Richtigkeit des Terms gegeben ist.
Ein paar Ideen: http://tclab.kaist.ac.kr/~otfried/cs206/notes/calculator.pdf
Vielleicht hast du aber auch etwas anderes vor, dann war mein Beitrag wohl für die Katz
-
Er hatte schon einmal hier im Forum geschrieben, es ging tatsächlich um die Berechnung von Termen, damals noch immer in der Form ((a+b)+c) usw. Also jede Operation mit seinen Operanden jeweils geklammert.
Da ich davon ausgehe das der Term immernoch als ein string vorliegt, ist es wirklich das einfachste einfach Zeichen für Zeichen durchzugehen und zu schauen ob auf eine Ziffer eine öffnende Klammer folgt und in dem Fall ein * einzufügen und dann normal den Term aufzulösen.
-
Fellhuhn schrieb:
Er hatte schon einmal hier im Forum geschrieben, es ging tatsächlich um die Berechnung von Termen, damals noch immer in der Form ((a+b)+c) usw. Also jede Operation mit seinen Operanden jeweils geklammert.
genau darum gehts
also ich mache das Programm weder mit Tokens noch mit einem Baum... ich wurschtel mich sozusagen bisl durchs Programm.
Die Rechnung funktioniert auch das die Klammern wenn welche vorhanden sind vor dem Term (((2+2))) = 4 geht auch inzwischen ( Das war ja das was ich als letztes hier ins Forum geschrieben hatte)
jetzt bin ich soweit das ich halt Zeichen für Zeichen durchgehen muss/will um dann zu schauen ob auf eine Zahl eine KLammer folgt. dann ein * einzufügen.
Mein größter Problem ist die if Abfrage .. ich hab gerade keine idee wie ich sie formulieren muss/soll... hmm
da wollte ich einfach einpaar ideen von euch
gruß
PS: cool Fellhuhn das du dich an mich erinnerst hoffentlich ein gutes Zeichen
-
Auf die schnelle in etwa so:
std::string term = "(3(3+4))"; for(unsigned int i = 0; i < term.size() - 1; i++) if (std::isdigit(term[i]) && // aus <cctype> term[i+1] == '(') { std::string temp = term.substr(0, i+1); temp += '*'; temp += term.substr(i+1); term = temp; }
-
Virokams schrieb:
also ich mache das Programm weder mit Tokens noch mit einem Baum... ich wurschtel mich sozusagen bisl durchs Programm.
Aha, na gut. Wenn du unbedingt mit den Strings rumfummeln willst
Aber als Vorschlag, wenn du mal fertig bist: Probier mal die Variante mit Termbaum aus. Wäre ne nette Erweiterung und man lernt die Grundlagen vom Compilerbau. Falls dich sowas interessiert.
-
Abstrakte Semantik Bäume wären da zB ein Stichwort. Oder die simpleren Abstraken Syntax Bäume.
Über so einen anstrengenden Frickelkram habe ich damals meine Diplomarbeit geschrieben... in Ada... war die Hölle.
-
Fellhuhn schrieb:
Abstrakte Semantik Bäume wären da zB ein Stichwort. Oder die simpleren Abstraken Syntax Bäume.
Über so einen anstrengenden Frickelkram habe ich damals meine Diplomarbeit geschrieben... in Ada... war die Hölle.
Also ich werde das Programm bestimm nochmal "anders" lösen sobald es fertig ist.
Ist halt jetzt so angefangen, abgesprochen und genehmigt es erstmal so zu machen um so strcpy und so andere Problematiken mal kennen zu lernen und die Abläufe mal im Kopf zu verstehen.so zurück zum Code... bisl umgebaut sehen meine ersten schritte jetzt so aus:
for(int i = 0; i <= term[strlen(term)-1]; i++) { if (int isdigit(term[i]) && term[i+1] == '(') { strncpy (copyleft, term[0], term[i]); strncpy (copyright, term[i+1], term[strlen(term)-1); copyleft = // weiß ich noch nicht genau XD soll aber dann halt das + an copyleft angefügt werden und dann wieder zusammenführung mit copyright im nächsten Schritt strncat(); return berechne(temp); } } //hmmmmmmmmmmmm
-
Also da du mit char-Arrays arbeitest hast du natürlich etwas mehr Arbeit als wenn du std::string nehmen würdest. Aber das ist deine eigene geschaffene Hölle, da sind wir alle wohl mal durch.
In etwa so:
for(int i = 0; i < strlen(term)-1; i++) // du willst bis zum vorletzten Element { if (std::isdigit(term[i]) && term[i+1] == '(') { // jetzt hast du das Problem das du term theoretisch um 1 byte vergrößern musst. // ich gehe mal davon aus das term vom Typ char* ist. char *temp = new char[strlen(term)+2]; // neuer platz strncpy (temp, term, i+1); // alle zeichen bis zum neuen * kopieren temp[i+1] = '*'; // * einfügen strncpy (temp+i+2, term + i + 1, strlen(term)-i+1); delete[] term; // term wieder freigeben term = temp; // term zeigt jetzt auf den neu angeforderten speicher } }
-
Fellhuhn schrieb:
Also da du mit char-Arrays arbeitest hast du natürlich etwas mehr Arbeit als wenn du std::string nehmen würdest. Aber das ist deine eigene geschaffene Hölle, da sind wir alle wohl mal durch.
In etwa so:
for(int i = 0; i < strlen(term)-1; i++) // du willst bis zum vorletzten Element { if (std::isdigit(term[i]) && term[i+1] == '(') { // jetzt hast du das Problem das du term theoretisch um 1 byte vergrößern musst. // ich gehe mal davon aus das term vom Typ char* ist. char *temp = new char[strlen(term)+2]; // neuer platz strncpy (temp, term, i+1); // alle zeichen bis zum neuen * kopieren temp[i+1] = '*'; // * einfügen strncpy (temp+i+2, term + i + 1, strlen(term)-i+1); delete[] term; // term wieder freigeben term = temp; // term zeigt jetzt auf den neu angeforderten speicher } }
hehe ja richtig aber Hölle ist immer gut wie gesagt ich soll es erstmal so machen.
term ist const char * term ...
ansonsten Danke erstmal ich gucke gleich mal durch mache jetzt erstmal mittagspause
gruß
-
hab das jetzt mal so eingefügt... ausser das ich std:: vor dem isdigit wegmachen musste liefs dann... ABER ZACK sobald ich 2(2+2) zum Testen eingebe kommt error.
und zwar das angeblich irgendiwe der Hipe probleme kriegt oder so.
kann jetzt keinen Screen machen.aber es ist keine Fehlermeldung in der Fehlerliste sondern so ein Windoof Kritikal Error oder so... total wirsch...
ne ahnung?
-
Virokams schrieb:
hab das jetzt mal so eingefügt... ausser das ich std:: vor dem isdigit wegmachen musste liefs dann... ABER ZACK sobald ich 2(2+2) zum Testen eingebe kommt error.
und zwar das angeblich irgendiwe der Hipe probleme kriegt oder so.
kann jetzt keinen Screen machen.aber es ist keine Fehlermeldung in der Fehlerliste sondern so ein Windoof Kritikal Error oder so... total wirsch...
ne ahnung?
Alles was hier wirsch ist, ist deine Fehlerbeschreibung.
Was soll der Hipe sein? Was ist Windoof? Und was soll ein Kritikal Error sein?
-
Ahnung? Ja: char-Arrays.
Da wird wohl irgendwas mit der Allokierung und/oder Freigabe im Argen liegen.
-
Debug assertion failed!
Programm:...
dbgdel.ccp
Libe:52Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
so ich drücke retry
Das Programm hat einen Haltepunkt ausgelöst
ich kann damit garnichts anfangen.
Hipe ist doch der "kleine" Speicher wo Stacks oder locale Variablen gesp. werden
Windoof = Windowssry...
-
nochwas:
wenn ich schritt für schritt durchgehe
sobald ich diese Befehlszeile verlasse:
delete[] term; // term wieder freigeben
kommt der Fehler
also bei:
term = temp; // term zeigt jetzt auf den neu angeforderten speicher
SO die Lösung des Problems ist also:
Auskommentieren von: //delete[] term; // term wieder freigeben
for(int i = 0; i < strlen(term)-1; i++) // du willst bis zum vorletzten Element { if (isdigit(term[i]) && term[i+1] == '(') { // jetzt hast du das Problem das du term theoretisch um 1 byte vergrößern musst. // ich gehe mal davon aus das term vom Typ char* ist. char * temp = new char[strlen(term)+2]; // neuer platz strncpy (temp, term, i+1); // alle zeichen bis zum neuen * kopieren temp[i+1] = '*'; // * einfügen strncpy (temp+i+2, term + i + 1, strlen(term)-i+1); //delete[] term; // term wieder freigeben term = temp; // term zeigt jetzt auf den neu angeforderten speicher } }
Danke
Nur eins noch:
char * temp = new char[strlen(term)+2]; // neuer platz
was macht das ... versteh ich nicht
kann mir bestimmt jemand erläutern...
Danke Danke Danke
-
char * temp = new char[strlen(term)+2]; // neuer platz
Dynamische Anforderung von der Länge von term + 2 und temp auf den Anfang des C-Stringes zeigen lassen.
-
Hm, zeig mal die Initialisierung von term.
Mit new wird neuer Speicher angefordert und mit delete wird er wieder gelöscht. Läßt du das delete weg hast du ein klassisches Speicherleck.
-
Fellhuhn schrieb:
Hm, zeig mal die Initialisierung von term.
Mit new wird neuer Speicher angefordert und mit delete wird er wieder gelöscht. Läßt du das delete weg hast du ein klassisches Speicherleck.
int main()
{
char term[1024];double berechne (const char * term)
{}???
Ich habe dir mal peer Mail den kompletten Code geschickt... vielleicht ist es dann ersichtlicher WIE ich vorgehe... und vielleicht siehste dann besser den Fehler (obwohl es funktioniert )
-
for(int i = 0; i < strlen(term)-1; i++) // du willst bis zum vorletzten Element { if (std::isdigit(term[i]) && term[i+1] == '(') { // jetzt hast du das Problem das du term theoretisch um 1 byte vergrößern musst. // ich gehe mal davon aus das term vom Typ char* ist. char *temp = new char[strlen(term)+2]; // neuer platz strncpy (temp, term, i+1); // alle zeichen bis zum neuen * kopieren temp[i+1] = '*'; // * einfügen strncpy (temp+i+2, term + i + 1, strlen(term)-i+1); delete[] term; // term wieder freigeben term = temp; // term zeigt jetzt auf den neu angeforderten speicher } }
Entschuldigt bitte das ich mich hier mal mit reinhänge, aber irgendwie verstehe ich die oberen Zeilen nicht so ganz. Sollte dort vor verlassen der
for
-Schleife nicht auch wiedertemp
freigegeben werden? Oder habe ich vielleicht gerade ein Brett vorm Kopf?
-
Virokams schrieb:
Debug assertion failed!
Programm:...
dbgdel.ccp
Libe:52Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
Daran wirst du dich gewöhnen müssen, wenn du es mit
char*
und deinem Gefrickel durchziehen willst. Du solltest einfach wissen, dass es einfacher geht.Mizar schrieb:
Sollte dort vor verlassen der
for
-Schleife nicht auch wiedertemp
freigegeben werden? Oder habe ich vielleicht gerade ein Brett vorm Kopf?Nein, der von der alten Variable
term
referenzierte Speicherbereich wird ja in den neu angelegten Bereich (vom Zeigertemp
) kopiert. Anschliessend wird der alte Speicher vonterm
freigegeben. Zuletzt zeigtterm
auf den neuen Inhalt (vontemp
).