Some explanation

Hi,

I started to read Programming Principles and Practice using c++ of Bjarne Stroustrup and I need some explanation because I don't understand something.

I have the code from here



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

//
// This is example code from Chapter 6.6 "Trying the first version" of
// "Software - Principles and Practice using C++" by Bjarne Stroustrup
//

#include "../std_lib_facilities.h"

//------------------------------------------------------------------------------

class Token {
public:
    char kind;        // what kind of token
    double value;     // for numbers: a value 
    Token(char ch)    // make a Token from a char
        :kind(ch), value(0) { }    
    Token(char ch, double val)     // make a Token from a char and a double
        :kind(ch), value(val) { }
};

//------------------------------------------------------------------------------

Token get_token()    // read a token from cin
{
    char ch;
    cin >> ch;    // note that >> skips whitespace (space, newline, tab, etc.)

    switch (ch) {
 //not yet   case ';':    // for "print"
 //not yet   case 'q':    // for "quit"
    case '(': case ')': case '+': case '-': case '*': case '/': 
        return Token(ch);        // let each character represent itself
    case '.':
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
        {    
            cin.putback(ch);         // put digit back into the input stream
            double val;
            cin >> val;              // read a floating-point number
            return Token('8',val);   // let '8' represent "a number"
        }
    default:
        error("Bad token");
    }
}

//------------------------------------------------------------------------------

double expression();  // read and evaluate a Expression

//------------------------------------------------------------------------------

double term();        // read and evaluate a Term

//------------------------------------------------------------------------------

double primary()     // read and evaluate a Primary
{
    Token t = get_token();
    switch (t.kind) {
    case '(':    // handle '(' expression ')'
        {    
            double d = expression();
            t = get_token();
            if (t.kind != ')') error("')' expected");
            return d;
        }
    case '8':            // we use '8' to represent a number
        return t.value;  // return the number's value
    default:
        error("primary expected");
    }
}
//------------------------------------------------------------------------------

int main()
try {
    while (cin)
        cout << expression() << '\n';
    keep_window_open("~0");
}
catch (exception& e) {
    cerr << e.what() << endl;
    keep_window_open ("~1");
    return 1;
}
catch (...) {
    cerr << "exception \n";
    keep_window_open ("~2");
    return 2;
}

//------------------------------------------------------------------------------

double expression()
{
    double left = term();      // read and evaluate a Term
    Token t = get_token();     // get the next token
    while(true) {    
        switch(t.kind) {
        case '+':
            left += term();    // evaluate Term and add
            t = get_token();
            break;
        case '-':
            left -= term();    // evaluate Term and subtract
            t = get_token();
            break;
        default:
            return left;       // finally: no more + or -: return the answer
        }
    }
}

//------------------------------------------------------------------------------

double term()
{
    double left = primary();
    Token t = get_token();     // get the next token

    while(true) {
        switch (t.kind) {
        case '*':
            left *= primary();
            t = get_token();
            break;
        case '/':
            {    
                double d = primary();
                if (d == 0) error("divide by zero");
                left /= d; 
                t = get_token();
                break;
            }
        default: 
            return left;
        }
    }
}

//------------------------------------------------------------------------------ 


Well, I insert 2 3 4 and it outputs 2.My question is why 2 ?
Because I call expression function.Then it calls term() function which calls primary function and this calls get_token().In this one, I have cin >> ch...so this must be 2 no ?So i'm jumping to case '2'...but here is another cin...which reads another value(the val).So is not the 3 value ?Please explain me what I'm wrong because I'm too confuse :D

Thank you!

Much fun, isn't it?
main:79 calls expression()
 expression:97 calls term()
  term:119 calls primary()
   primary:59 calls get_token()
    get_token:26 reads character '2'
    get_token:37 returns '2' to the stream
    get_token:39 reads double value "2"
    get_token:40 returns a token to primary()
   it is case '8' and primary:69 returns value 2 to term()
  left = 2
  term:120 reads another token, a value "3" from your input
  term:switch uses default case and returns 2 to expression()
 expression:98 reads another token, a value "4" from your input
 expression:switch uses default case and returns 2 to main()
main:79 prints the value
Thank you very much for your reply.The problem that I don't understand is at line 39.
What is cin >> val doing ? Is reading the "ch" that is stored back in the stream ?
1
2
3
4
5
6
7
8
char ch;
cin >> ch; // read one character
cin.putback( ch ); // put the character back to the stream
// cin has now same content as before line 2
// (if we ignore the whitespaceskipping)

double val;
cin >> val; // read a double value from stream 

What does line 8 do?
http://www.cplusplus.com/reference/istream/basic_istream/operator%3E%3E/

"Extracts and parses characters sequentially from the stream to interpret them as the representation of a value of the proper type, which is stored as the value of val."

"Sets failbit, if either no characters were extracted, or the characters extracted could not be interpreted as a valid value of the appropriate type."

The stream had
2 3 4

and after first get_token it still has:
 3 4

and 2.0 is stored in t.value.

If the stream had had
2.54 3 4

then after first get_token it still has:
 3 4

and 2.54 is stored in t.value.

If the stream had had
.7 3 4

then after first get_token it still has:
 3 4

and 0.7 is stored in t.value.

If the stream had had
6.1foo 3 4

then after first get_token it still has:
foo 3 4

and 6.1 is stored in t.value, but the next get_token would encounter an error, because f is not a valid token.
Thank you very much keskiverto.You've been very helpfully. :P
Last edited on
Topic archived. No new replies allowed.