Taschenrechner-Funktionen



  • Hallo zusammen!

    Ich habe mich zwar schon des Öfteren im Studium (ET) mit C++ befasst, und es scheint zwar eine hübsche Sprache zu sein, aber ich werde nicht richtig warm damit. Meine Ambitionen reichen daher auch nicht so superweit... ^^ Ich wurde aus ähnlichen Threads hier nicht so ganz schlau, also hoffe ich, dass meine Frage hier passt.

    Meine jüngste Aufgabe schreibt mir vor, einen Taschenrechner mit 4 Grundrechenarten zu erstellen, der als Hardware nur den Nummernblock sowie eine Taste C und eine Taste A hat. 'C' soll die aktuelle Eingabe löschen, 'A' soll das Programm beenden. Es gab den Hinweis, dass man 5 Klassen erstellen könne, wenn man bemüßigt wäre.

    Darauf basierend habe ich für jede Rechenart eine Klasse erstellt und eine, die die Aufgabe einliest. (Wie sonst sollte man mit einem Taschenrechner 5 Klassen voll bekommen?) Von der Einlese-Klasse kann man das Rechenzeichen erfragen, so dass im main() dann eine switch-Abfrage läuft, die dann die passende Klassenfunktion aus der passenden Klasse aufruft. Dabei gibt es zwar ein kleines Problemchen, dass bei Divisionsaufgaben statt eines float-Wertes nur 0 ausgegeben wird, aber das ist nicht das Hauptproblem.

    Worüber ich mir seit Stunden den Kopf zerbreche, ist, wie ich diese C- und A-Funktion implementieren soll. Ich muss dazu, so denke ich, jeden einzelnen Tastendruck erstmal auswerten, um dann

    a) den Eingabepuffer zu löschen und das Einlesen von vorn zu beginnen
    b) das Programm zu beenden
    oder c) das Schreiben fortzusetzen.

    Das kann man zwar so machen, aber nach dem Prinzip würde ich doch bloß Arrays bzw. Vektoren als Eingabe erhalten, mit denen ich dann nicht rechnen kann, oder? Ganz abgesehen davon, dass ich nicht weiß, wie ich in dem Falle das Rechenzeichen da rauspfriemeln soll, und das ganze überhaupt ganz schön kompliziert werden würde.

    Edit: Nach etwas hin und her und verschiedenen Konzepten bleibt mein Problem das mit der Clear-Funktion für Taste C. (Eingabe der fertigen Aufgabe soll auch über = erfolgen und nicht über Enter.) C soll interpretiert werden, sobald es auf dem Bildschirm erscheint. Soweit ich weiß, speichert doch aber cin >> erst dann irgendwas in die angegebenen Variablen, wenn Enter gedrückt wird.?

    Gibt es vielleicht eine Möglichkeit, die aktuelle Eingabe (z.B. mit cin.getline(...)) als char einzulesen und die Speichervariable gleichzeitig auszulesen, also in ihr nach einem bestimmten Zeichen zu scannen? Das wäre gut, und dann bliebe nur noch das Problem, dass ich den Rest des chars bei Bedarf in zwei ints und ein Zeichen trennen müsste.

    Gruß

    die Trekkietante



  • Meine jüngste Aufgabe schreibt mir vor, einen Taschenrechner mit 4 Grundrechenarten zu erstellen, der als Hardware nur den Nummernblock sowie eine Taste C und eine Taste A hat.

    Das Problem ist, das weder Tastendrücke, noch Tasten oder Nummernblöcke Teil des C++-Standards sind.

    In C++ hast du also nur einen Strom von Zeichen, auf den du durch std::cin zugreifen kannst...

    Darauf basierend habe ich für jede Rechenart eine Klasse erstellt und eine, die die Aufgabe einliest.

    Völlig überflüssig. C++ ist nicht Java, wo man für jeden Quatsch eine Klasse erstellt. (Tut man das in Java? Ich weiß es nicht :p )

    Wie sonst sollte man mit einem Taschenrechner 5 Klassen voll bekommen?

    Gar nicht, man braucht keine Einzige um es schön hinzubekommen. Mach es ohne. Ich interpretiere den Hinweis als Hinweis und nicht als Muss.

    Worüber ich mir seit Stunden den Kopf zerbreche, ist, wie ich diese C- und A-Funktion implementieren soll - ohne großen Zirkus, denn das ganze ist ein Grundlagenkurs. Ich muss dazu, so denke ich, jeden einzelnen Tastendruck erstmal auswerten

    Und hier liegt schon das Problem... wie oben bereits angesprochen, kennt reines C++ keine Tastendrücke.

    Das heißt, etwas ähnliches wie den Windows-Rechner, der auf Tastendrücke selbst reagiert, bekommst du ohne weiteres nicht hin. Du musst immer mit der Enter-Taste arbeiten*: sprich, der User gibt eine Zeile ein, drückt die Enter-Taste, du wertest die Zeile irgendwie aus (kannst auch erst testen ob die Zeile "c" gleicht o.ä.), veränderst den internen "Status", und liest weiter ein.

    Sobald der User eine leere Zeile eingibt, gibst du das Ergebnis aus o.ä..

    * Da heute der internationale talk-like-a-pirate Tag ist... ist das witzig.



  • Danke für die schnelle Antwort!

    Ich hab in der Zwischenzeit eine andere Taschenrechner-Lösung hier versucht, für mich passend zu verwursten, aber der Aufwand wäre einer a+b - Rechenaufgabe wohl nicht angemessen gewesen.

    Gar nicht, man braucht keine Einzige um es schön hinzubekommen.

    Den Gedanken hatte ich zu Anfang auch! 😃 Nur: dann sieht es fast wie C aus, bis auf cin und cout... Mache ich es mir damit nicht ein bisschen zu einfach?



  • Mache ich es mir damit nicht ein bisschen zu einfach?

    Du sagst, C++ muss immer kompliziert und umständlich sein?

    Nur: dann sieht es fast wie C aus, bis auf cin und cout...

    Nicht unbedingt.



  • Du sagst, C++ muss immer kompliziert und umständlich sein?

    Keinesfalls 😃 C++ kann sehr elegant sein im Vergleich zu struktureller Programmierung. Ich dachte nur, dass es auch hier eine elegante Lösung geben müsste^^

    Dann tipp ich mal. Danke bis hierhin!

    TT



  • Aber sicher, dass man da nichts mit cin.peek() oder so was machen müsste?

    Der Gedanke lässt mir keine Ruhe ... ist immerhin eine Semesterarbeit^^



  • Nein, cin.peek() ist das völlig falsche Ende. Es gibt nur zurück, was das nächste Zeichen im Stream wäre. Das heißt, wenn du 3.684a eingibst, und einen float aus dem Stream extrahierst, dann liegt immer noch a im Buffer, und das würde peek() zurückgeben.

    Auf regulären Konsolen wie bei Windows musst du aber für jede Eingabe an stdin die Entertaste drücken.

    (Wenn du nur ein Zeichen extrahieren willst, dann nimm istream::get() )


  • Mod

    Trekkiebraut schrieb:

    Aber sicher, dass man da nichts mit cin.peek() oder so was machen müsste?

    Nein. Das was du beschreibst lässt sich weder in C noch C++ so umsetzen, da man in diesen Sprachen keinen direkten Zugriff auf die Tastatur hat. Man sieht bloß noch einen abstrakten Zeichenstrom, lange nachdem Betriebssystem und Konsole die Tastatureingaben ausgewertet haben. Von Tastendrücken und ähnlichem ist dann schon lange nichts mehr übrig.
    Wenn ich sage, dass man keinen Zugriff hätte, ist das jedoch etwas übertrieben. Streng nach Sprachstandard kann man da nichts machen. Jedoch bieten viele Systeme einem Programm die Möglichkeit, selber Tastendrücke auszuwerten. Da du anscheinend so auf Klassen stehst, folgender Vorschlag:

    Klasse Taschenrechner.
    Klasse Lesegerät.
    Klasse Ausgabegerät.

    Der Taschenrechner hat ein Lesegerät und ein Ausgabegerät. Das Lesegerät beinhaltet systemabhängigen Code, an den Taschenrechner wird nur noch das Ergebnis der Leseaktionen gegeben, also Zahlen und Rechenzeichen. Das Lesegerät verarbeitet dann intern die Tasten C und A. Der Taschenrechner rechnet nur und gibt Daten an das Ausgabegerät.
    So kannst du wunderbar den Taschenrechner immer wieder benutzen (das will man mit gutem Design schließlich erreichen), während Ein- und Ausgabe an die jeweiligen Gegebenheiten angepasst werden. So kannst du zu Testzwecken mit der Ein- und Ausgabe mittels der Streams arbeiten (dann eben ohne prompte Reaktion der C- und A-Tasten) und später auch eine richtig schicke grafische Oberfläche drumrum basteln.

    Als weitere Erweiterungen vorstellbar, die aber eindeutig Richtung Overdesign gehen: Das Rechenwerk und die Speichereinheiten des Taschenrechners könnten auch noch eigenständige Klassen sein, so dass man auch Taschenrechner mit Fähigkeiten nach Wunsch zusammen bauen kann. Der Taschenrechner selbst stellt dann bloß noch die Gesamtheit aus Ein- und Ausgabe und dem Rechenwerk dar, in seiner Aufgabe auf das reine Weiterleiten von Daten beschränkt.



  • So kannst du wunderbar den Taschenrechner immer wieder benutzen (das will man mit gutem Design schließlich erreichen), während Ein- und Ausgabe an die jeweiligen Gegebenheiten angepasst werden. So kannst du zu Testzwecken mit der Ein- und Ausgabe mittels der Streams arbeiten (dann eben ohne prompte Reaktion der C- und A-Tasten) und später auch eine richtig schicke grafische Oberfläche drumrum basteln.

    Hehehe, danke für den Vorschlag. Und ja, irgendwie kommt's mir vor, als wäre das Programm ohne Klassen nicht richtig objektorientiert ... mangels Objekten 😛

    Auf regulären Konsolen wie bei Windows musst du aber für jede Eingabe an stdin die Entertaste drücken.

    Das kommt mir sehr umständlich vor im Vergleich zu diesen kleinen 5-Euro-Taschenrechnern 😉 Aber anders wird's wohl nicht gehen.

    Ich versuche es jetzt mal mit sowas wie

    int a, b;
    char rz;
    
    cin >> a;
    get(rz);
    

    und dann einer Auswertung, ob "c", "a" oder +-*/, mit den entsprechenden Folgebefehlen.



  • mangels Objekten

    Ein Objekt muss keine Klasse als Typ haben.



  • Ein Objekt muss keine Klasse als Typ haben.

    Aber wo ist dann der Unterschied zwischen einem int-Objekt und einer int-Variablen?

    Ist jetzt vielleicht ein bisschen ot ...



  • Trekkiebraut schrieb:

    Ein Objekt muss keine Klasse als Typ haben.

    Aber wo ist dann der Unterschied zwischen einem int-Objekt und einer int-Variablen?

    Es gibt keinen.
    Du kannst dir vorstellen, dass eine int Variable ein Objekt der Klasse int ist*.

    *Der Standard-Disclaimer: Ja, ich weiß, dass das nicht so ist; das Beispiel dient lediglich zur Veranschaulichung.



  • Vorsicht mit der Terminologie. Das Wort Objekt hat zwei Bedeutungen, die man nicht verwechseln darf:

    Es gibt Objekte in der objektorientierten Programmierung. Das sind die Dinger, die Nachrichten austauschen.

    Es gibt im C++-Standard den technischen Begriff Objekt, der einen Speicherbereich bezeichnet, der einen Wert beinhalten kann. In diesem Sinne ist eine Variable ein Objekt mit einem Namen.

    Nun ist aus dem Kontext klar, dass du Objekt im ersten Sinne verstanden hast. Sone hat ihn im zweiten Sinne verstanden. Warum weiß ich nicht, wahrscheinlich seine komische Art von Humor.



  • SeppJ schrieb:

    Klasse Taschenrechner.
    Klasse Lesegerät.
    Klasse Ausgabegerät.

    Der Taschenrechner hat ein Lesegerät und ein Ausgabegerät.

    Wenn dein Prof von Java kommt leite stattdessen Taschenrechner von Lesegerät und Ausgabegerät ab. Ist zwar sinnlos, aber voll objektorientiert. Da es C++ statt Java ist brauchst du dir nichtmal zu überlegen, ob Lesegerät von Ausgabegerät ableiten soll oder andersrum.

    Ist denn das Ziel einen Taschenrechner oder ein objektorientiertes Programm zu schreiben?



  • Veranschaulichung

    Danke, hat geklappt 😉

    Ist denn das Ziel einen Taschenrechner oder ein objektorientiertes Programm zu schreiben?

    Der Kurs heißt "Objektorientierte Programmierung" ... und das ist die Abschlussarbeit^^ Sone hatte schon Recht, es sieht nicht aus wie C. Ich hab jetzt pro forma die Ausgabe als Klassenfunktion von "Display" gemacht, aber den Input so "auszulagern" erschien mir viel zu viel Text für so wenig Funktion. Leider kann ich meinen Prof da nicht einschätzen, ob er eher für maximale Flexibilität (also mit Input-Klasse) oder für bessere Lesbarkeit ist. Wird sich zeigen.



  • Man sollte Klassen auch dort einsetzen, wo es sinn macht. Ein Cmd-Taschenrechner gehoert da fuer mich nicht dazu.



  • edit: Der Professor will ausdrücklich, dass nach C oder A nicht Enter gedrückt wird. Die Eingabe der fertigen Aufgabe soll auch über = erfolgen und nicht über Enter. C soll interpretiert werden, sobald es auf dem Bildschirm erscheint. Soweit ich weiß, speichert doch aber cin >> erst dann irgendwas in die angegebenen Variablen, wenn Enter gedrückt wird.

    Gibt es vielleicht eine Möglichkeit, die aktuelle Eingabe mit cin.getline(...) als string einzulesen und diesen gleichzeitig (also während des Eintippens) auszulesen, also in ihm nach einem bestimmten Zeichen zu scannen?

    Gruß

    Trekkiebraut



  • *leises kleines Push*


  • Mod

    Trekkiebraut schrieb:

    *leises kleines Push*

    Du bekommst keine Antwort, weil die Frage unverständlich ist. Nach dem Lesen deines Beitrags weiß ich, dass das Ergebnis nicht zufriedenstellend war, aber ich weiß immer noch nicht, was gewünscht ist. Ich weiß auch nicht, was

    Nun bin ich jedenfalls wieder bei dem Problem mit der Clear-Funktion für Taste C.

    mit dem ganzen ersten Absatz zu tun hat. Einerseits scheint es um allgemeine Designprobleme zu gehen, andererseits hängst du nun aber an technischen Detailfragen, die längst beantwortet wurden. Heißt das, das Design steht?

    Der einzige Satz mit einem Fragezeichen am Ende ist leider komplett unverständlich:

    Gibt es vielleicht eine Möglichkeit, die aktuelle Eingabe mit cin.getline(...) als char einzulesen und die Speichervariable gleichzeitig auszulesen, also in ihr nach einem bestimmten Zeichen zu scannen?

    Häh? 😕 Selbst wenn ich mal annehme, dass du mit "char" so etwas wie "Zeichenkette" meinst (ein char ist ein Zeichen!) weiß ich nicht, wovon du hier redest und was das mit dem Rest des Beitrags zu tun hat. Wieso getline? Was ist eine Speichervariable? Was genau meinst du mit "gleichzeitig"? Ich vermute mal, dass du dir hier eine falsche technische Umsetzung ausgedacht hast und nun nach Details fragst, die einfach keinen Sinn machen, da der Ansatz falsch ist. Frag nach dem, was du erreichen möchtest, nicht danach, wie du getline so verbiegst, dass es etwas tut, wofür es nicht da ist.

    Ich vermute mal, dir geht es weiter um direkte Nutzerinteraktion über die Tastatur. Da wurde doch schon gesagt, dass die Streams nicht dafür geeignet sind, da diese auf einer ganz anderen Abstraktionsebene laufen, auf der so etwas wie Tastendrücke längst nicht mehr existieren. Das kannst du auch nicht so hinbiegen, dass wieder Tastendrücke herauskommen, die Information ist auf Streamebene einfach nicht vorhanden. Wenn du direkt die Tastatur eines Computers auslesen willst, dann musst du eben dies tun. Dir wurde im Verlauf des Threads bereits gesagt, dass es auf deinem System bestimmt Möglichkeiten gibt, direkt eine Tastatur anzusprechen. Dir wurde sogar der Vorschlag gemacht, diese Interaktion im Rahmen einer Klasse zu abstrahieren, damit sich der Rest des Programms nicht mit solchen systemabhängigen Details herumschlagen brauchst, was eine sehr sinnvolle Anwendung objektorientierten Designs wäre, was hier ja anscheinend gewünscht ist.

    Beantwortet dies deine Frage?



  • leider komplett unverständlich. (...) Frag nach dem, was du erreichen möchtest, nicht danach, wie du getline so verbiegst, dass es etwas tut, wofür es nicht da ist.

    Du musst mich nicht zusammenfalten, bloß weil ich mich vielleicht unklar ausdrücke. Ich wurschtel mich durch Bücher, weil ich versuche, irgendwas hinzukriegen, das scheinbar nicht machbar ist. Ich hatte nicht die Absicht, die Kreise der Wissenden zu stören, sondern ich frage hier, weil ich in den Büchern keine Antworten mehr gefunden habe. Aber scheinbar waren meine Fragen ja falsch.

    Es geht nicht um die Form, wie ich eigentlich dachte, klargemacht zu haben. Gerne lösche ich auch die entsprechenden Passagen wieder, damit sie nicht zu Verwirrung führen. Es geht darum, wie ich das laufende Programm dazu bringe, sobald 'C' und nur 'C' gedrückt wird, die aktuell eingegebene Zeile zu löschen, egal, was da steht, und sobald 'A' gedrückt wird, alles zu beenden. Wie man es von einem kleinen Taschenrechner kennt. Wenn '=' eingegeben wird, soll es wie 'Enter' wirken. (Das war der Grund, weshalb mich getline interessierte.)

    Aber gut, es scheint ja doch machbar zu sein. Und was ist dieser "systemabhängige Code", von dem du da schreibst? Davon höre ich zum ersten Mal. Woher weiß ich, was ich da für Befehle brauche? Gibt es da eine eigene Bibliothek?

    Gruß


Anmelden zum Antworten