upn taschenrechner (ascii problem)



  • Kleiner tipp - oder + ascii bleiben sollte. ^^

    Du macht da glaub ein Chr-wert.



  • isiprimax schrieb:

    Kleiner tipp - oder + ascii bleiben sollte. ^^

    Du macht da glaub ein Chr-wert.

    miam, sorry, aber das hab ich jetzt nicht ganz verstanden den tipp 😉



  • Du musst eine If-Abfrage einbauen, das einliest was eine zahl ist die dann mit "atoi" umgewandelt wird. Und was ein Ascii bleiben soll wie zb + - * / usw...

    Glaub wen du + atoi machst bekommste den keycode.



  • hmm. aber ich muss ja die ganze argumentenliste zuerst in integer werte umwandeln, damit ich überhaupt entscheiden kann ob es sich um eine zahl oder um einen operanden handelt. Wie kann ich dann einen operand wieder zurückwandeln?

    gruss



  • einzelne chars vergleichen geht einfach mit ==:

    char c = '+';
    if(c == '+')
       do_bla();
    

    Bei arrays:

    char c[] = "abcd";
    if(c[0] == 'a')
        //true
    


  • ja, schon klar, aber ich hab ja eine argumentenliste wie zb: "4 2 3 + /". Diese wandle ich in integers um, und speichere sie in einem array. Wie kann ich aber in dem array prüfen, ob nun zb bei array[i] ein "+" abgespeichert ist?

    gruss



  • Habs eben mal getestet.

    #include <iostream>
    
    using namespace std;
    
    int main(int argc, char* argv[])
    {
        int a;
        for(int i=0; i<argc; i++)
        {
            a = atoi(argv[i]);
            cout << a << " : " << argv[i] << endl;
        }
        return 0;
    }
    

    Ascii zeichen sind 0.



  • genau... Aber weiterhelfen tuts mir irgendwie doch nicht so recht 😞



  • Du prüfst einfach ab, ob es sich um einen Operator handelt (s. obige Abfragen) und wenn nicht, dann wandelst du den Wert erst in eine Zahl um. (Warum einfach, wenn's auch kompliziert geht?)



  • habs mal so versucht, da bekomm ich ein compilerfehler:
    http://666kb.com/i/atfnck2lzrq0ywc9x.jpg



  • Du verwendest eine Zuweisung statt eines Vergleichs ('=' statt '==').

    Aber das ist sowieso alles nicht optimal, denn in C++ programmiert man anders.



  • naja ich weiss. Bin aber auch erst am anfang meiner programmierkarriere, sprich, ich hab vor 6 wochen angefangen 😉

    thx anyway



  • man man. Habs geändert, aber er meckert immer noch:
    http://666kb.com/i/atfo49qr3tw5hvspx.jpg



  • andigr schrieb:

    naja ich weiss. Bin aber auch erst am anfang meiner programmierkarriere, sprich, ich hab vor 6 wochen angefangen 😉

    Jupp, man kann aber gleich „richtig“ anfangen. Das heißt insbesondere, dass man gleich die korrekten Datenstrukturen verwendet und keine Low-Level Pointer-Arrays oder C-Funktionen wie 'atoi'. Das ist fehleranfällig und erschwert nur alles.

    Folgender Code behebt diese Probleme (allerdings *nur* diese).

    #include <iostream>     // Für die cout und endl.
    #include <stack>        // Für stack.
    #include <string>       // Für string.
    #include <sstream>      // Für stringstream.
    #include <map>          // Für pair.
    #include <functional>   // Für for_each.
    #include <algorithm>    // Für bind_1st, mem_fun
    
    typedef std::pair<int, int> operators;
    
    // Extrahiert die obersten beiden Zahlen aus einem Stack
    // und gibt sie als Zahlenpaar zurück.
    operators get_ops(std::stack<int>& stack) {
        operators ret;
        ret.second = stack.top();
        stack.pop();
        ret.first = stack.top();
        stack.pop();
        return ret;
    }
    
    int main(int argc, char* argv[]) {
        std::stack<int> stack;
        std::stringstream input;
    
        // Schiebt die Kommandozeilenargumente in einen Stream,
        // aus dem wir im folgenden die Eingabe lesen.
        for (int i = 1; i < argc; ++i) {
            input << argv[i] << ' ';
        }
    
        std::string token;
        while (input >> token)  {
            if (token == "+") {
                operators ops = get_ops(stack);
                stack.push(ops.first + ops.second);
            }
            else if (token == "-") {
                operators ops = get_ops(stack);
                stack.push(ops.first - ops.second);
            }
            else if (token == "*") {
                operators ops = get_ops(stack);
                stack.push(ops.first * ops.second);
            }
            else if (token == "/") {
                operators ops = get_ops(stack);
                stack.push(ops.first / ops.second);
            }
            else {
                // Es wurde kein Rechenzeichen eingegeben, wir erwarten also
                // eine Zahl. Um diese zu lesen, müssen wir den gelesenen
                // String aber erst wieder zurück in den Stream schieben,
                // und zwar zeichenweise rückwärts.
                std::for_each(
                    token.rbegin(), token.rend(),
                    std::bind1st(std::mem_fun(&std::istream::putback), &input)
                );
                int number;
                input >> number;
                stack.push(number);
            }
        }
    
        std::cout << stack.top() << std::endl;
    }
    

    Bis auf die Sache mit 'std::for_each' sollte das alles einigermaßen verständlich sein. Zu dem for_each-Dings ist nur wichtig zu verstehen, dass der String hier rückwärts zeichenweise durchgegangen wird, und für jedes Zeichen wird die Funktion 'putback' auf dem 'input'-Stream aufgerufen, also im Prinzip dasselbe wie 'input.putback(c)', wobei 'c' das aktuelle Zeichen ist.



  • andigr schrieb:

    man man. Habs geändert, aber er meckert immer noch:
    http://666kb.com/i/atfo49qr3tw5hvspx.jpg

    Das dauernde Posten von Screenshots ist doch wohl sowohl für Dich als auch für uns ein wenig aufwendig, oder? Poste doch einfach den relevanten Code + Fehlermeldung. In diesem Fall liegt der Fehler daran, dass Du einen Zeiger auf Zeichen mit einem Zeichen vergleichst, das geht natürlich nicht, hatte ich vorher übersehen. Aber auch ansonsten wird es Fehler geben. Schon die erste Zeile Deiner 'main'-Funktion ist in C++ undefiniert.



  • mhm. Naja, das atoi usw hab ich alles an der uni gelernt... Dein programm ist mir schon etwas zu kompliziert, kenn die hälfte der bibliotheken nicht, drum hätt ich noch ne andere frage:

    Ich habs mal geschaft, auf der konsole die eingegebenen werte wieder auszugeben.

    http://666kb.com/i/atfokxwdxk24fq7mt.jpg

    in der blau unterlegten zeile hat es noch eine if schleife. Wieso ignoriert er diese, wenn er das "minus" zeichen auf der konsole korrekt ausgiebt?



  • ok sorry wegen den screenshots, ich dachte das sei einfach für die hilfe...



  • andigr schrieb:

    mhm. Naja, das atoi usw hab ich alles an der uni gelernt... Dein programm ist mir schon etwas zu kompliziert, kenn die hälfte der bibliotheken nicht, drum hätt ich noch ne andere frage:

    „Die Hälfte der Bibliotheken“ … ich verwende da nur *eine* Bibliothek, nämlich die C++-Standardbibliothek. Und wenn Du die noch nicht kennst, wird es Zeit. Alles andere ist unwichtig.

    Allerdings sind die letzten zwei Header wirklich Overkill, dieses for_each-Ding (dafür brauche ich die) kann man auch einfacher machen:

    typedef std::string::const_reverse_iterator It;
    for (It i = token.rbegin(); i != token.rend(); ++i)
        input.putback(*i);
    

    Na ja …

    in der blau unterlegten zeile hat es noch eine if schleife. Wieso ignoriert er diese, wenn er das "minus" zeichen auf der konsole korrekt ausgiebt?

    Weil Du hier Zeiger vergleichst und nicht den String-Inhalt. Das ist eben das Problem, wenn Du Low-Level-Zeiger statt vernünftiger Klassen verwendest. Wenn Du, wie in meinem Code, die std::string-Klasse benutzt, dann hast Du dieses Problem nicht.



  • hi konrad
    vielen dank für deine hilfe. Ich habs nun so halbwegs hinbekommen, und es funktioniert auch gar nicht schlecht.

    also, vielen dank nochmal
    lg


Anmelden zum Antworten