push() pop()
-
Hallo!
bräuchten dringend hilfe!
folgendes problem.
wir wollen eine eingabe z.b. 20*40 auswerten d.h. 20 sollte gespeichert werden der operator sollte gespeichert werden und 40 sollte gespeichert werden.
wir versuchen schon seit stunden dies zu realisieren mit push und pop. Hat jemand vielleicht ahnung wie sich sowas am einfachsten lösen lässt. und wenn möglich erklärt
Wären sehr dankbar für eure hilfe.
-
schiessen hätte ich ne andere relativ einfacherer Idee auch ohne
gleich wirklich an nen richtigen Parser zu denken!!!!als Ausgangspunkt:
Rechenoperation=> Operand1 Operator Operand2
Es wird immer die kommplette Rechnung als String eingegeben!!!!!
Ihr braucht 2 Variablen vom Datentyp double.Jetzt scannt ihr in ner Schleife den eingegebenen String solange
bis ihr auf ;/;-;+*; und lest alles ein
was dem nicht entspricht (ist der erste Operand der Rechnung) und koennt das dann mit...wsprintf(...)
bzw.
...sprintf(...)
(eine der beiden Funktionen kann jedenfalls Strings in alle erdenklichen elementaren Datentypen wandeln!!!) in den konkreten Wert wandeln um das
einer Variablen "opernad1" vom Typ double zuzuführen die Schleife
hat nun ja abgebrochen weil sie auf ein Operationszeichen gestossen ist!Dises Operationszeichen merkt IHr euch!!!
Jetzt koennte ihr denn 2. Operanden aus dem Puffer lesen, um disen String wieder zu wandel fuer ne Variable operand2 vom Typ doubleIch hoffe mit dieser Idee ist Euch ein
aufgegangen
Achtung diese Idee berucksichtigt noch keine Vorzeichen sollte aber ausbaubar
seinGruss sclearscreen
-
hätte dazu zwar auch noch nen Codeschnipsel
der auf dieser Idee beruht
will euch aber nicht den Spass an eigner Kreativität nehmen!!!!mfg
-
meines Wissens gibt es glaube auch Algorithmen die dieses Problem wirklich mit
nem Stack regeln!!!
-
dank für deine Überlegungen. Werde das mal versuchen.
Wenns nicht funktioniert darf ich mich nochmal melden?
habe auch noch versucht mit der isdigit das auszulesen.DocFirestorm
-
könntest du uns das code schnipsel senden. damit wie einen anhaltspunkt haben.
Danke
-
entsprechende Funktionalitaet kann man sich aber aus dem entsprechenden
Methodenrümpfen auch nach direkten C coden!!!
hab nur die Methoden (Funktionen) aus der Klasse kopiert.int scanLine(char *line = NULL) // Aufgabe in Operanden und Operation teilen { // folglich darf spaeter diese String nur aus diesen zwei Ops und der Rechenoperation bestehen char sign = ' '; int i; int linker_oder_rechter = linker; if((line == NULL) || ((strcmp(line," ")) == 0)) { return 0; // ist kein berrechnbarer Ausdruck uebergeben worden } for(i = 0;((line[i] != NULL) || (line[i] != '\0')); i++) { if(line[i] == ',') line[i] = '.'; // Kommas zu Dezimalpunkten machen } for(i = 0;line[i] != NULL || line[i] != '\0'; i++) { sign = line[i]; switch(sign) { case '0':{ if(linker_oder_rechter == linker) { *(pOperand1 + i) = sign; *(pOperand1 + i + 1) = '\0'; } if(linker_oder_rechter == rechter) { *(pOperand2 + i) = sign; *(pOperand2 + i + 1) = '\0'; } break; } case '1':{ if(linker_oder_rechter == linker) { *(pOperand1 + i) = sign; *(pOperand1 + i + 1) = '\0'; } if(linker_oder_rechter == rechter) { *(pOperand2 + i) = sign; *(pOperand2 + i + 1) = '\0'; } break; } case '2':{ if(linker_oder_rechter == linker) { *(pOperand1 + i) = sign; *(pOperand1 + i + 1) = '\0'; } if(linker_oder_rechter == rechter) { pOperand2[i] = sign; *(pOperand2 + i + 1) = '\0'; } break; } case '3':{ if(linker_oder_rechter == linker) { *(pOperand1 + i) = sign; *(pOperand1 + i + 1) = '\0'; } if(linker_oder_rechter == rechter) { *(pOperand2 + i) = sign; *(pOperand2 + i + 1) = '\0'; } break; } case '4':{ if(linker_oder_rechter == linker) { *(pOperand1 + i) = sign; *(pOperand1 + i + 1) = '\0'; } if(linker_oder_rechter == rechter) { *(pOperand2 + i) = sign; *(pOperand2 + i + 1) = '\0'; } break; } case '5':{ if(linker_oder_rechter == linker) { *(pOperand1 + i) = sign; *(pOperand1 + i + 1) = '\0'; } if(linker_oder_rechter == rechter) { *(pOperand2 + i) = sign; *(pOperand2 + i + 1) = '\0'; } break; } case '6':{ if(linker_oder_rechter == linker) { *(pOperand1 + i) = sign; *(pOperand1 + i + 1) = '\0'; } if(linker_oder_rechter == rechter) { *(pOperand2 + i) = sign; *(pOperand2 + i + 1) = '\0'; } break; } case '7':{ if(linker_oder_rechter == linker) { *(pOperand1 + i) = sign; *(pOperand1 + i + 1) = '\0'; } if(linker_oder_rechter == rechter) { *(pOperand2 + i) = sign; *(pOperand2 + i + 1) = '\0'; } break; } case '8':{ if(linker_oder_rechter == linker) { *(pOperand1 + i) = sign; *(pOperand1 + i + 1) = '\0'; } if(linker_oder_rechter == rechter) { *(pOperand2 + i) = sign; *(pOperand2 + i + 1) = '\0'; } break; } case '9':{ if(linker_oder_rechter == linker) { *(pOperand1 + i) = sign; *(pOperand1 + i + 1) = '\0'; } if(linker_oder_rechter == rechter) { *(pOperand2 + i) = sign; *(pOperand2 + i + 1) = '\0'; } break; } case '.':{ if(linker_oder_rechter == linker) { *(pOperand1 + i) = sign; *(pOperand1 + i + 1) = '\0'; } if(linker_oder_rechter == rechter) { *(pOperand2 + i) = sign; *(pOperand2 + i + 1) = '\0'; } break; } case ' ':{ break;} // eliminiert bzw. uebergeht etwaige Leerzeichen case '+':{ // ab hier beginnen Rechenoperationen linker_oder_rechter = rechter; *pRechenart = sign; break; } case '-':{ linker_oder_rechter = rechter; *pRechenart = sign; break; } case '*':{ linker_oder_rechter = rechter; *pRechenart = sign; break; } case '/':{ linker_oder_rechter = rechter; *pRechenart = sign; break; } case '^':{ linker_oder_rechter = rechter; *pRechenart = sign; break; } } } sscanf(pOperand1, "%f", &m_numOperand1); sscanf(pOperand2, "%f", &m_numOperand2); return 1; // sind Operanden und Rechenvorschrift erflogreich zugewiesen // keehrt "scanLine" mit 1 zurueck } // findet in einen mathematischen Term die erste Position einer zu lösende Klammer // und gibt den Inhalt der Klammer als Teilstring zurueck char* find_clamp(char* pStr) { UINT cnt_klammer_auf, cnt_klammer_zu; cnt_klammer_auf = cnt_klammer_zu = 0; UINT str_laenge = strlen(pStr); UINT i; for(i = 0;i < str_laenge;i++) { if(pStr[i] == '[' || pStr[i] == '{') { pStr[i] = '('; } if(pStr[i] == ']' || pStr[i] == '}') { pStr[i] = ')'; } if(pStr[i] == '(') { cnt_klammer_auf++; } if(pStr[i] == ')') { cnt_klammer_zu++; } } // Hier beginnt die Klammersuche zuvor sollte natürlich die Laenge des STRING bekannt sein char *pKlammerzu = 0, *pKlammerauf = 0, *pAufKette = 0; pAufKette = pStr; // Zeiger auf die gesamte Zeichenkette pKlammerzu = pStr; // Zeiger auf die schliessende Klammer des innersten Klammerterms for(i = 0; i < str_laenge || pStr[i] == ')'; i++) { if(pStr[i] == ')') { pKlammerzu = &pStr[i]; } } while(pStr[i] != '(') { pKlammerauf = &pStr[i - 1]; i--; } // jetzt will ich den eigentlichen Inhalt der innersten Klammer noch separieren char mathSubstr[512] = ""; // hier wird der Inhalt der Klammer hinkopiert char *pSubstr = pKlammerauf; UINT j = 0; i = 1; // solange bis die schliessende Klammer erkannt wird ist es der Inhalt des Klammerterms while(pSubstr[i] != ')') { mathSubstr[j] = *(pSubstr + i); mathSubstr[j + 1] = '\0'; j++; i++; } /* Wir befinden uns in der Methode: "find_clamp" ------ Anmerkung zum weiteren Vorgehen am Matheparser ------ Achtung: Wenn der String in der Klammer gefunden wird dann kann er durch entsprechende Rechenoperationen bis nur noch ein String mit Zahlen übrig ist eingekürtzt werden. Ist dieser Vorgang abgeschlossen wird der Zeiger der auf die oeffnende Klammer zeigt dazu benutzt diese Klammer durch ein Stringende zu kenn- zeichnen und die ausgerechnet Zahl die als String konvertiert ist kann dort an- gehangen werden. Dann wird der Zeiger der auf die schliessende Klammer zeigt auf das Zahlensymbol verschoben! Dieser Zeiger wird dann benutzt um diesen dritten String an den zweiten String anzuhaengen! Das Parsen, konvertieren , berechnen und manipulieren von dem gesamten String ghet solange bis kein Rechenoperationssymbol bzw. Klammersymbol mehr vorhanden ist! Das Endekennzeichen "\0" wird korrekt von den Stringmanipulationsfunktionen erkannt!! Hab ich mit "strlen" getestet und funktioniert toll! */ return (char*) mathSubstr; } float calculate(void) { switch(*pRechenart) { case '+': return (m_numOperand1 + m_numOperand2); case '-': return (m_numOperand1 - m_numOperand2); case '*': return (m_numOperand1 * m_numOperand2); case '/':{ if(m_numOperand2 == 0.0) throw pzero_division; else return (m_numOperand1/m_numOperand2); } // Achtung noch keine gebrochenen und oder negativen Exponenten moeglich case '^': return mypow(m_numOperand1, m_numOperand2); } }
Korigiere mich zu meinen vorherigen Statments man wandelt mit "sscanf" Strings in konkrete numerische Wert.
fuer euch ist die Erste und Letzte Funktion dieses Codeauszuges von Interesse!!!!!mfg sclearscreen
and good luck
-
auf ne Idee gebracht wo manches einfacherer ist als Matheparser ueber
Syntaxbäume zu bauen! Ein Leistungsproblem wäre da nur die STACK - Tiefe
Die bei langen Rechenaufgaben einen hohen Speicherverbrauch zur Folge
hätte! Bäume im spezielleren Syntaxbäume sind aber wesentlich komplexer
vom Verstaendnis (wenn man die Traversierung in Bäumen nicht beherrscht)Wenn man eine Lösung aber hat die für einfache Sachen erstmal funzt
hat man viel ueber die Problemstellung gelernt und kann das Problem
dann mit komplexeren aber vieleicht effizienteren Algorithmen lösen!!!mfg