Mehrstellige Zahlen aus string fischen



  • Hi,

    im Zuge des Studiums ist es meine Aufgabe einen Taschenrechner zu programmieren, der seine Berechnung nach Eingabe eines kompletten Terms durchführt.

    Ich bin dahingehend, prozedural erstmal, schon recht weit gekommen.

    Stehe aber nun vor dem Problem, wie ich mehrstellige Zahlen aus meinem String fischen kann.

    Simpel fällt mir hier ein, über eine Schleife wieder zu prüfen, ob ein Operand kommt oder noch eine Ziffer. Danach kann ich jede Stelle anhand des Stellenwertes im Dezimalsystem (*10^2 etc.) nehmen, addieren, und hätte die Zahl.
    In meinen Augen aber doch kein intelligenter Weg, es muss doch anders gehen.

    Hat jemand Tipps/Ideen für mich?

    Mein Code so far:

    #include <iostream>
    #include <string>
    using namespace std;
    
    int main()
    {
    	int zahlen[10];
    	int stackpointeroperand=0;
    	int stackpointerzahlen=0;
    	int stackpointerzaehler=0;
    	int ergebnis=0,zwischenschritt=0;
    	char operanden[10];
    	string term;
    
    	//arrays auf 0 setzen
    	for(int i=0;i<10;i++)
    	{
    		zahlen[i]=0;
    		operanden[i]=0;
    	}
    
    	cout << "\nBitte Term eingeben: ";
    	cin >> term;
    	cout << "\nDer Term ist " << term.length() << " Stellen lang\n";
    
    	// String durchforsten und entsprechende Operanden auf eigenen Stack schreiben. Zahlenstack + Operationsstack
    	for(int y=0;y<int(term.length());y++)
    	{
    		if(term[y]=='+' || term[y]=='-' || term[y]=='*' || term[y]=='/')
    		{
    			operanden[stackpointeroperand]=term[y];
    			stackpointeroperand++;
    		}
    		else
    		{
    			zahlen[stackpointerzahlen]=term[y]-48; //einfache Konvertierung ascii to decimal
    			stackpointerzahlen++;
    			cout << "\n\n" << term[y];
    		}
    	}
    
    	cout << "\nDer String term: " << term;
    	cout << "\nDer Zahlenstack: " << zahlen[0] << " " << zahlen[1] << " " << zahlen[2] << endl;
    	cout << "\nDer Operandenstack: " << operanden[0] << " " << operanden[1] << " " << operanden[2] << endl;
    
    	// Berechnung mit Zwischenschritten. jeweils 2 zahlen aus dem Zahlenstack = 1 Operation. Operandenstack wird extra gezählt
    	for(int x=0;x<int(term.length());x=x+2)
    	{
    		cout << "\nzahlen[" << x << "] = " << zahlen[x] << endl << "zahlen[" << x+1 << "] = " << zahlen[x+1] << endl;
    		cout << "\noperanden[" << stackpointerzaehler << "] = " << operanden[stackpointerzaehler] << endl;
    		switch(operanden[stackpointerzaehler])
    		{
    		case '+':
    			zwischenschritt=zahlen[x]+zahlen[x+1];
    			ergebnis=ergebnis+zwischenschritt;
    			cout << "\n\n ergebnis = " << ergebnis << "\nzwischenschritt = " << zwischenschritt << endl;
    			break;
    		case '-':
    			zwischenschritt=zahlen[x]-zahlen[x+1];
    			ergebnis=ergebnis+zwischenschritt;
    			cout << "\n\n ergebnis = " << ergebnis << "\nzwischenschritt = " << zwischenschritt << endl;
    			break;
    		case '*':
    			zwischenschritt=zahlen[x]*zahlen[x+1];
    			ergebnis=ergebnis+zwischenschritt;
    			cout << "\n\n ergebnis = " << ergebnis << "\nzwischenschritt = " << zwischenschritt << endl;
    			break;
    		case '/':
    			zwischenschritt=zahlen[x]/zahlen[x+1];
    			ergebnis=ergebnis+zwischenschritt;
    			cout << "\n\n ergebnis = " << ergebnis << "\nzwischenschritt = " << zwischenschritt << endl;
    			break;
    		}
    
    			zwischenschritt=0; // zwischenschritt wieder auf 0 setzen um manipulation vorzubeugen
    			stackpointerzaehler++; //stackpointerzähler für operandenstack, darf ja nicht +2 sondern step-by-step abgearbeitet
    
    	}
    
    	cout << "\n\nDas Endergebnis deiner Rechenoperation lautet: " << ergebnis << endl;
    
    	system("pause");
    	return 0;
    }
    

  • Mod

    Pack das Ding in einen Stringstream und wende den Operator >> mit einem Zahlentyp darauf an. Gelingt die Aktion, hast du eine Zahl. Scheitert die Aktion, überspringst du das nächste Zeichen. Wiederholen bis Streamende.



  • Offen gesagt habe ich deine Antwort nicht 100% verstanden. 😕

    Unabhängig davon habe ich einen anderen Lösungsansatz entwickelt durch weitere Recherche, dabei ist folgendes herausgekommen:

    #include <iostream>
    using namespace std;
    
    int main()
    {
        char c,operanden[10];
        int n[10],i=0,b=0,zwischenschritt=0,stackpointer=1,ergebnis=0;
    
        for(int x=0;x<10;x++)
        {
            operanden[x]=0;
            n[x]=0;
        }
    
        cout << "Term eingeben: ";
    
        do
        {
        c=cin.peek();
    
        if((c>='0') && (c<='9'))
        {
            cout <<"\n b = " << b << endl;
            cin >> n[b];
            cout << "N = " << n[b] << endl;
            b++;
        } 
        else if((c=='+' || c=='-' || c=='*' || c=='/'))
        {
            cin >> operanden[i];
            cout << "Operand: " << operanden[i] << endl;
            i++;
        }
        else if(c=='X')
        {
            break;
            return 0;
        }
    
        }while(c!='=');
    
        cout << "\n ergebnis = " << ergebnis << endl;
    
        switch(operanden[0])
        {
        case '+':
            ergebnis=n[0]+n[1];
            cout << "\n ergebnis = " << ergebnis << endl;
            break;
        case '-':
            ergebnis=n[0]-n[1];
            cout << "\n ergebnis = " << ergebnis << endl;
            break;
        case '*':
            ergebnis=n[0]*n[1];
            cout << "\n ergebnis = " << ergebnis << endl;
            break;
        case '/':
            ergebnis=n[0]/n[1];
            cout << "\n ergebnis = " << ergebnis << endl;
            break;
        }
    
        for(int x=2;x<=b;x+=2)
        {
            switch(operanden[stackpointer])
            {
            case '+':
                zwischenschritt=n[x]+n[x+1];
                ergebnis=ergebnis+zwischenschritt;
                cout << "\n\nPLUS ergebnis = " << ergebnis << "\nzwischenschritt = " << zwischenschritt << endl;
                break;
            case '-':
                zwischenschritt=n[x]-n[x+1];
                ergebnis=ergebnis-zwischenschritt;
                cout << "\n\nMINUS ergebnis = " << ergebnis << "\nzwischenschritt = " << zwischenschritt << endl;
                break;
            case '*':
                zwischenschritt=n[x]*n[x+1];
                ergebnis=ergebnis*zwischenschritt;
                cout << "\n\nMUL ergebnis = " << ergebnis << "\nzwischenschritt = " << zwischenschritt << endl;
                break;
            case '/':
                zwischenschritt=n[x]/n[x+1];
                ergebnis=ergebnis/zwischenschritt;
                cout << "\n\nDIV ergebnis = " << ergebnis << "\nzwischenschritt = " << zwischenschritt << endl;
                break;
            }
    
                zwischenschritt=0; // zwischenschritt wieder auf 0 setzen um manipulation vorzubeugen
                stackpointer++; //stackpointerzähler für operandenstack, darf ja nicht +2 sondern nur step-by-step abgearbeitet werden
    
                cout << "\nEndergebnis: " << ergebnis << endl;
    
        }
    
    }
    

    Das ganze Teil kann jetzt soweit den Stream aufbrechen und entsprechend verbauen.

    Jetzt fehlt an Implementation noch die vorzeichenbehaftete Berücksichtigung (sprich +-3 = -3) sowie Punkt-vor-Strich Rechnung.

    Hier will ich aber erstmal selber knobeln 😃





  • ... oder hier
    http://www.c-plusplus.net/forum/viewtopic-var-p-is-1642138.html#1642138

    Die dort gezeigte Lösung kann auch Zahlen mit Vorzeichen und berücksichtigt Punkt vor Strich.

    Stefan_B schrieb:

    Offen gesagt habe ich deine Antwort nicht 100% verstanden. 😕

    Was SeppJ meint ist, dass Du Zahlen idealerweise direkt aus einem Stream liest. Hier mal eine Skizze wie das gehen kann:

    #include <iostream>
    
    int main()
    {
        using namespace std;
        cout << "Term eingeben: ";
        double a1, a2;
        char operator_;
        if( cin >> a1 >> operator_ >> a2 ) // hier kannst Du die Zahlen direkt vom Stream lesen
        {
            switch( operator_ )
            {
            case '+':
                cout << a1 << " + " << a2 << " = " << (a1 + a2) << endl;
                break;
            case '-':
                cout << a1 << " - " << a2 << " = " << (a1 - a2) << endl;
                break;
            // case .. usw.
            default:
                cerr << "unbekannter Operator" << endl;
            }
        }
        return 0;
    }
    

    Gruß
    Werner





  • Das ist eine schöne Übungsaufgabe: einen Eingabestring in Zahlen und Operatoren aufzudröseln. So etwas leistet kein Compiler von allein. Man muss das schon selbst machen mit zeichenweiser Betrachtung des Eingabestrings. Das nennt sich dann Programmieren. 🙂



  • berniebutt schrieb:

    Das ist eine schöne Übungsaufgabe:

    ja - aber nicht unbedingt für Anfänger.

    berniebutt schrieb:

    einen Eingabestring in Zahlen und Operatoren aufzudröseln. So etwas leistet kein Compiler von allein. Man muss das schon selbst machen mit zeichenweiser Betrachtung des Eingabestrings. Das nennt sich dann Programmieren. 🙂

    .. würde ich eher als Hacken bezeichnen 😉
    Das zeichenweise Einlesen und Umwandeln in eine Integer- oder Fließkommazahl ist z.B. nichts anderes als die Facette num_get nachzuprogrammieren. Das kann man machen - klar, viel wichtiger finde ich, den Umgang mit streams zu üben. Das nennt sich dann C++ Programmieren.

    Gruß
    Werner


Anmelden zum Antworten