einfacher Taschenrechner (Trennung von Char und Int)



  • Liest ein Zeichen (char) ein und prüf das in einem switch-case-Verteiler darauf ob es sich um einen Operanden handelt, wenn ja, dann kannst du dich um die Verarbeitung der rechten Seite kümmern. Wenn du in einen case-Zweig für die Zahlen kommst, pack das Zeichen in den Eingabestrom (putback) zurück und lies eine Zahl ein (cin >> zahlenVariable).

    Mal nen kleines Beispiel (nur für switch-case-Verteiler):

    switch(ch) {
      case '+':
      case '-':
         // weg damit und von vorne beginnen um nächstes zeichen zu lesen
      case '0': case '1': // ....
         cin.putback(ch);
         cin >> zahl;
    }
    


  • Danke für die Antwort.

    Ich weiß gerade nur nicht wie ich es jetzt realisiere.
    Es soll alles über ein cin funktionieren. d.h. eine Schleife

    Hier meine Aufgabe, weil mein Beispiel vorhin etwas kurz geraten ist.

    Alle Zahleneigaben sollen in einem Array gespeichert werden.
    So sollte es aussehen.
    Eingabe -> 12 -> Array[0]=12, Array[1]=0, ..., Array[7]=0
    Eingabe -> 3 -> Array[0]=12, Array[1]=3,...
    Eingabe -> 6 -> Array[0]=12, Array[1]=3, Array[2]=6, ...
    Eingabe -> "+" -> Array[0]=12, Array[1]=9,...
    Eingabe -> "-" -> Array[0]=3,...

    Also er solle immer die beiden letzten Werte vom Array berechnen sobald der Benutzer ein Operator eingibt.

    Ich meine ich kann die eingegeben Chars in ein Asciiwert umwandeln, aber dann nimmt er jeweil nur ein Zeichen an. Also wenn die Eingabe eine 12 ist nimmt er nur die 1 und das wäre dann der Wert 49. Ich könnte 48 vom ASCII wert abziehen dann hätte ich ja die Zahl, aber ich glaube das ist nicht gerade die schlauste Lösung.

    Bestimmt geht es voll einfach und ich denke mal wieder voll kompliziert.

    Danke.

    Gruss,
    Cyrill

    [Edit]
    Da war noch einer schneller mit dem tippen. Ich probiere es gleich mal aus. Danke.



  • Gut funktioniert wunderbar mit dem switch case.

    Vielen Dank.



  • Ich habe gerade ein Verständnissproblem.

    Den Taschenrechner muss ich für die UNI programmieren. Es hat bis jetzt fast alles geklappt.

    Hier ist unsere Übung als PDF-Datei: http://www2.fbi.fh-darmstadt.de/~schuette/Vorlesungen/ProgrammierenI/Praktikum/Uebungen/Uebung_4/Templates.pdf

    Wir sollen 3 Funktionen verwenden:
    - Hinzufügen eines Wertes

    void push(int operand)
    

    wirft Exception, wenn der Stack voll ist
    - Entnehmen des letzten Elementes

    int pop()
    

    wirft Exception, wenn der Stack leer ist
    - Abfrage auf leeren Keller

    boolean isEmpty()
    

    Das mit dem

    void push (int operand)
    

    hab ich so gut wie verstanden. 🙂 Diese Funktion soll ja den nächsten Wert in das Array speichern, aber wie sieht es mit der Exception aus? Die Funktion soll eine Fehlermeldung ausgeben wenn das Array voll ist. Bei einer void funktion kann ich die Fehlermeldung nur mit cout ausgeben.

    So nun die Funktion

    int pop()
    

    verstehe ich nicht ganz. Was ich verstanden habe ist, dass er den letzten Wert des Arrays wieder rausnehmen soll. Aber warum eine int Funktion? Ich verstehe die Rückgabe nicht? Dort soll auch wieder eine Fehlermeldung ausgegeben werden, dies könnte ich auch wieder mit cout machen.

    Was ich garnicht verstehe ist die

    boolean isEmpty()
    

    Funktion. Auf was bezieht sich die Funktion.

    Mein Problem ist das ich nicht genau weiß was sie mit den Ausdrücken "Exception, Stack, Keller" meinen.

    Mein Code bisher:

    meine Headerdatei:

    // Headerdatei für die Spezifizierung der Funktionsprototypen und die grösse des Arrays
    #include <iostream>
    using namespace std;
    
    #ifndef globaleDefinitionen
    #define globaleDefinitionen
    char eingabe;
    int rechnerinhalt[7] = {0,0,0,0,0,0,0};
    int arrayindex = 0;
    int zahl, element;
    #endif
    
    // Templates
    void push(int);
    int pop();
    //long zahl(char);
    

    Meine CPP-Datei:

    //#include <iostream>
    #include "stack.h"
    #include <string>
    //using namespace std;
    
    void main()
    {
    
    	do{	
    		cout << "Momentaner Arrayinhalt: ";
    
    		for (int aindex = 0; aindex <= 6; aindex++)
    		{
    			cout << rechnerinhalt[aindex] << " ";
    		}
    
    		cout << "\nGeben Sie eine Zahl oder einen Operator (+, -, *, /) [a = Abbruch]: ";
    		cin >> eingabe;
    		cout << endl;
    
    		switch(eingabe) 
    		{
    			case '+': break;
    			case '-': break; 
    			case '*': break;
    			case '/': break;
    			case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': 
    			cin.putback(eingabe);
    			cin >> zahl;
    			push(zahl);
    			break;
    			case 'a': cout << "Abbruch durch Benutzer\n"; break;
    			default: cout << "unzulässige Eingabe\n";
    		}
    
    	}while(eingabe != 'a');
    
    	cout << "vorletztes Element : " << pop() << endl;
    }
    
    void push(int operand)  // Element hinzufügen
    {
    	if (arrayindex <= 6)
    			rechnerinhalt[arrayindex++] = operand;
    		else
    			cout << "Fehler: Stack ist voll" << endl;
    
    }
    
    int pop()    // letztes Element entfernen
    {
    	rechnerinhalt[arrayindex--] = 0;
    	return 0;
    }
    

    Vielen Dank.

    Gruss,
    Cyrill



  • Als erstes solltest du die Methoden push(), pop() und isempty() zusammen mit deiner Datenstruktur in eine Klasse reinpacken:

    class Stack
    {
    public:
      void push(int val);
      int pop();
      bool isempty();
    private:
      //Datendarstellung (z.B. int-Array)
    }
    

    Zweitens: wenn du schon einen Include-Guard verwendest, dann bitte um den gesamten Header-Inhalt.

    Drittens: Expections sind Fehlerobjekte, die mit throw geworfen und mit catch wieder aufgefangen werden können - das hat nichts mit Rückgabewerten oder cout zu tun:

    #include <stdexcept>
    
    void Stack::push(int val)
    {
      if(/*voll*/)
        throw std::range_error("Stack ist voll");
      //...
    }
    
    int Stack::pop()
    {
      if(/*leer*/)
        throw std::range_error("Stack ist leer");
      //...
    }
    
    int main()
    {
      Stack my_stack;
      try
      {
        my_stack.push(6);
        //weitere Stack-Operationen
      }
      catch(std::execption& e)//fängt alle "Nachkommen" von Exception auf, also auch das oben verwendete 'range_error'
      {
        cout<<"Fehler:"<<e.what()<<endl;
      }
    }
    


  • Wir haben noch keine Klassen behandelt. Uns wurde gesagt das machen wir erst später. Da ich diese Woche krank war, könnten wir diese Woche den Fehlerabfang behandelt haben, aber eigentlich wollten wir diese Woche die Sortierungsmethoden kennenlernen. Dann beschäftige ich mich jetzt mal um die Fehlersache. Falls wir das noch nicht durchgemacht haben, gibt es bestimmt noch eine andere möglichkeit.

    Aber vielen Dank für die Hilfe.

    Gruss,
    Cyrill



  • Wenn es für deine Anwendung reicht, kannst du auch bei deinen globalen Deklarationen bleiben 😉



  • switch(eingabe)
            {
                case '+': break;
                case '-': break;
                case '*': break;
                case '/': break;
                    /* HIER sollte was hin */
                    break;
                case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
                cin.putback(eingabe);
                cin >> zahl;
                push(zahl);
                break;
                case 'a': cout << "Abbruch durch Benutzer\n"; break;
                default: cout << "unzulässige Eingabe\n";
            }
    

    Eigentlich sollte da wo ich den kommentar gemacht habe hinter den Operatoren etwas hin. Wenn du ein + hast, dieses zurückpackst und dann ne Zahl lesen willst geht das eigentlich schief, weil dann das Zeichen wieder dadrin wäre. Du solltest an der Stelle wo du +, -, * oder / erkennst, dieses irgendwie speichern um später die richtige Berechnung durchzuführen.

    Z.B. könnte man ein enum benutzen, eine variable davon anlegen und dann an den Typ dieser Variablen zuweisen:

    enum Token { DEFAULT=0, PLUS='+', MINUS='-', MUL='*', DIV'/' };
    Token op=DEFAULT;
    
    /* im case teil für plus, minus... */
    if(op!=DEFAULT) exit(1); // irgendwas machen, um sicherzustellen das der operator nicht überschrieben wird
    op = Token(ch);
    break;
    


  • Vellas schrieb:

    Z.B. könnte man ein enum benutzen, eine variable davon anlegen und dann an den Typ dieser Variablen zuweisen:

    Oder an dieser Stelle zwei Werte vom Stack holen, entsprechend des gelesenen Symbols verrechnen und zurück auf den Stack legen:

    case '+':
      op1=pop();
      op2=pop();
      push(op1+op2);
      break;
    //übrige case analog
    


  • Ja, sofern zuerst die Werte eingegeben werden und dann die Operation und nicht in dieser Form (von der ich ausgegangen bin): 10+10



  • Tja, ich bin von den Voraussetzungen im Ursprungspost ausgegangen:

    DragonShaolin schrieb:

    So sollte es aussehen:
    Eingabe -> 10
    Eingabe -> 4
    Eingabe -> +
    Ausgabe -> 14

    (wie war nochmal der Fachbegriff dafür? "umgekehrte polnische Notation"?)

    Bei einer Infix-Eingabe dürfte das parsen tatsächlich etwas schwieriger werden, besonders wenn du auf Punkt-vor-Strich und Klammern achten willst.



  • Oh stimmt, da habe ich den Ursprungspost wohl nicht ganz richtig gelesen gehabt *g* Hoffe trotzdem geholfen zu haben 🙂


Anmelden zum Antworten