mir hat's mal wieder nach langer Zeit den Verstand geraubt...mit Bjarne Stroustrup Die C++ Programmierspache 3. Auflage



  • ich benutze
    gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)
    2.6.32-25-generic #45-Ubuntu SMP Sat Oct 16 19:48:22 UTC 2010 i686 GNU/Linux

    und habe kapitel 6 folgenden Source-code abgepinnt, wird auch compiliert ohne Warunungen und Fehler...

    [code]
    /*
    program:
    END // END ist Eingabeende
    expr_list END

    expr_list:
    expression PRINT // PRINT ist Semikolon
    expression PRINT expr_list

    expression:
    expression + term
    expression - term
    term

    term:
    term / primary
    term * primary
    primary

    primary:
    NUMBER
    NAME
    NAME = expression
    - primary
    ( expression )
    */

    #include <iostream>
    #include <string>
    #include <map>
    #include <cctype>

    using namespace std;

    int no_of_errors;

    double error( const string& s)
    {
    no_of_errors++;
    cerr << "Fehler: " << s << endl;
    return 1;
    }

    enum token_value{
    NAME, NUMBER, END,
    PLUS='+', MINUS='-', MUL='*', DIV='/',
    PRINT=';', ASSIGN='=', LP='(', RP=')'
    };

    token_value curr_tok = PRINT;
    double number_value;
    string string_value;

    double expr( bool get);
    double prim( bool get);
    token_value get_token();
    double error( const string& s);

    #if 0
    Token_value get_token()
    {
    char ch = 0;
    cin >> ch;

    switch( ch) {
    case 0:
    return curr_tok = END;
    case ';':
    case '*':
    case '/':
    case '+':
    case '-':
    case '(':
    case ')':
    case '=':
    return curr_tok = Token_value( ch);
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
    case '.':
    cin.putback( ch);
    cin >> number_value;
    return curr_tok = NUMBER;
    default:
    if( isalpha( ch)) {
    cin.putback( ch);
    cin >> string_value;
    return curr_tok = NAME;
    }
    error( "Falsches Token");
    return curr_tok = PRINT;
    }
    }
    #endif

    token_value get_token() // verbesserte eingabefunktion
    {
    char ch;

    do { // Überspringe Whitespace (Leerzeichen) außer '\n'
    if( !cin.get( ch))
    return curr_tok = END;
    } while( ch != '\n' && isspace( ch));
    switch( ch) {
    case ';':
    case '\n':
    return curr_tok = PRINT;
    case '*':
    case '/':
    case '+':
    case '-':
    case '(':
    case ')':
    case '=':
    return curr_tok=token_value(ch);
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
    case '.':
    cin.putback(ch);
    cin >> number_value;
    return curr_tok=NUMBER;
    default: // NAME, NAME= oder Fehler
    if( isalpha( ch)) {
    string_value = ch;
    while( cin.get( ch) && isalnum( ch))
    string_value += ch;
    cin.putback( ch);
    return curr_tok = NAME;
    }
    error( "Falsches Token");
    return curr_tok = PRINT;
    }
    }

    map< string, double> table;

    // return curr_tok=NUMBER;
    double prim( bool get) // Behandelt primaries
    {
    if( get)
    get_token();

    switch( curr_tok) {
    case NUMBER: // Gleitkommakonstante (reele Zahl)
    {
    double v = ::number_value;
    get_token();
    return v;
    }
    case NAME:
    {
    double& v = table[string_value];
    if( get_token() == ASSIGN)
    v = expr( true);
    return v;
    }
    case MINUS: // Einstelliges Minus
    return -prim( true);
    case LP:
    {
    double e = expr(true);
    if( curr_tok != RP)
    return error( ") erwartet");
    get_token(); // Verschlucke ')'
    return e;
    }
    default:
    return error( "primary erwartet");
    }
    }

    double term( bool get) // Multipliziere und dividiere
    {
    double left = prim( get);

    for(;;)
    switch( curr_tok) {
    case MUL:
    left *= prim( true);
    break;
    case DIV:
    if( double d = prim( true)) { // d != 0!!!
    left /= d;
    break;
    }
    return error( "Division durch 0");
    default:
    return left;
    }
    }

    double expr( bool get) // Addiere und subtrahiere
    {
    double left = term( get);

    for(;;) // forever Endlosschleife
    switch( curr_tok) {
    case PLUS:
    left += term( true);
    break;

    case MINUS:
    left -= term( true);
    break;
    default:
    return left;
    }
    }

    int main()
    {
    table["pi"] = 3.1415926535897932385; // vordefinierte Namen einfügen
    table["e"] = 2.71828182845904590452354;

    while( cin) {
    get_token();
    if( curr_tok == END)
    break;
    if( curr_tok == PRINT)
    continue;
    cout << expr( false) << endl;
    }
    return no_of_errors;
    }

    Wenn ich den Mist jetzt teste oder mit dem gdb laufen lassen, kommt folgendes:

    5+6=
    dc: stack empty
    6+5;
    dc: stack empty
    4*9 (return)
    +3 (return)

    (gdb) n
    4
    main () at dc.cc:223
    223 while (cin) {
    (gdb) n
    224 get_token();
    (gdb) n
    +
    225 if (curr_tok == END) break;
    (gdb) n
    226 if (curr_tok == PRINT) continue;
    (gdb) n

    Breakpoint 1, main () at dc.cc:227
    227 cout << expr(false) << '\n';
    (gdb) n
    error: primary expected
    error: primary expected
    2
    223 while (cin) {
    (gdb) n
    224 get_token();
    (gdb)

    ist jemand hier, der mir vielleicht sagen was ich da falsch gemacht habe?
    verliere komplett die Übersicht, weil ich auch mit der Stackfehlermeldung nichts anfangen kann...

    vielen Dank


  • Mod

    Du hast dein Programm nicht zufällig dc genannt?



  • 😮 Jetzt ist einiges klar.



  • An so einen einfachen fehler hab ich nicht gedacht, sollte mal mein OS besser kennnenlernen *schäm 😡



  • Ist mir eine Zeit lang regelmäßig mit man: test(1) passiert. 🙂



  • Mir auch schon -)

    Daher am besten immer lokal mittels "./prog" starten...


Anmelden zum Antworten