Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.79
Ruger
1 / 1 / 0
Регистрация: 25.10.2011
Сообщений: 15
#1

Факториал в калькуляторе. - C++

13.11.2011, 22:40. Просмотров 1723. Ответов 5
Метки нет (Все метки)

Всем привет. Делаю очередное задание из книжки Страуструпа, был дан багованый калькулятор (основанный на разбиении выражений на лексемы). Баги исправил, работает исправно, вот код:
C++
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#include "stdafx.h"
#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) { }
};
 
//------------------------------------------------------------------------------
 
class Token_stream {
public: 
    Token_stream();   // make a Token_stream that reads from cin
    Token get();      // get a Token (get() is defined elsewhere)
    void putback(Token t);    // put a Token back
private:
    bool full;        // is there a Token in the buffer?
    Token buffer;     // here is where we keep a Token put back using putback()
};
 
//------------------------------------------------------------------------------
 
// The constructor just sets full to indicate that the buffer is empty:
Token_stream::Token_stream()
:full(false), buffer(0)    // no Token in buffer
{
}
 
//------------------------------------------------------------------------------
 
// The putback() member function puts its argument back into the Token_stream's buffer:
void Token_stream::putback(Token t)
{
    if (full) error("putback() into a full buffer");
    buffer = t;       // copy t to buffer
    full = true;      // buffer is now full
}
 
//------------------------------------------------------------------------------
 
Token Token_stream::get()
{
    if (full) {       // do we already have a Token ready?
        // remove token from buffer
        full=false;
        return buffer;
    } 
 
    char ch;
    cin >> ch;    // note that >> skips whitespace (space, newline, tab, etc.)
 
    switch (ch) {
    case '=':    // for "print"
    case 'q':    // for "quit"
    case '(': case ')': 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");
    }
}
 
//------------------------------------------------------------------------------
 
Token_stream ts;        // provides get() and putback() 
 
//------------------------------------------------------------------------------
 
double expression();    // declaration so that primary() can call expression()
 
//------------------------------------------------------------------------------
 
// deal with numbers and parentheses
double primary()
{
    Token t = ts.get();
    switch (t.kind) {
    case '(': case '{':    // handle '(' expression ')'
        {    
            double d = expression();
            t = ts.get();
            if (t.kind != ')' && t.kind != '}') error("')' or '}' expected");
            return d;
        }
    case '8':            // we use '8' to represent a number
        return t.value;  // return the number's value
    default:
        error("primary expected");
    }
}
 
//------------------------------------------------------------------------------
 
// deal with *, /, and %
double term()
{
    double left = primary();
    Token t = ts.get();        // get the next token from token stream
 
    while(true) {
        switch (t.kind) {
        case '*':
            left *= primary();
            t = ts.get();
            break;
        case '/':
            {    
                double d = primary();
                if (d == 0) error("divide by zero");
                left /= d; 
                t = ts.get();
                break;
            }
        default: 
            ts.putback(t);     // put t back into the token stream
            return left;
        }
    }
}
 
//------------------------------------------------------------------------------
 
// deal with + and -
double expression()
{
    double left = term();      // read and evaluate a Term
    Token t = ts.get();        // get the next token from token stream
 
    while(true) {    
        switch(t.kind) {
        case '+':
            left += term();    // evaluate Term and add
            t = ts.get();
            break;
        case '-':
            left -= term();    // evaluate Term and subtract
            t = ts.get();
            break;
        default: 
            ts.putback(t);     // put t back into the token stream
            return left;       // finally: no more + or -: return the answer
        }
    }
}
 
//------------------------------------------------------------------------------
 
int main()
try
{
    double val = 0;
    cout << "Welcome! Please enter an expression that contains floating-point numbers.\n";
    while (cin) {
        Token t = ts.get();
 
        if (t.kind == 'x') break; // 'x' for quit
        if (t.kind == '=')        // '=' for "print now"
            cout << "=" << val << '\n';
        else
            ts.putback(t);
        val = expression();
    }
    keep_window_open();
}
catch (exception& e) {
    cerr << "error: " << e.what() << '\n'; 
    keep_window_open();
    return 1;
}
catch (...) {
    cerr << "Oops: unknown exception!\n"; 
    keep_window_open();
    return 2;
}
 
//------------------------------------------------------------------------------
Собственно, нужно добавить вычисление факториала.
Что пытался делать:
добавил в Token_stream вариант с '!':
C++
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
Token Token_stream::get()
{
    if (full) {       // do we already have a Token ready?
        // remove token from buffer
        full=false;
        return buffer;
    } 
 
    char ch;
    cin >> ch;    // note that >> skips whitespace (space, newline, tab, etc.)
 
    switch (ch) {
    case '=':    // for "print"
    case 'q':    // for "quit"
    case '(': case ')': case '{': 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");
    }
}
Затем в функцию вычисление первичных выражений добавил case '!':
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
double primary()
{
    Token t = ts.get();
    switch (t.kind) {
    case '(': case '{':    // handle '(' expression ')'
        {    
            double d = expression();
            t = ts.get();
            if (t.kind != ')' && t.kind != '}') error("')' or '}' expected");
            return d;
        }
    case '!':     // handle '!' expression
    {
        double d = t.value;
        d = d+1;
        return d;
                t = ts.get();
    }
    case '8':            // we use '8' to represent a number
        return t.value;  // return the number's value
    default:
        error("primary expected");
    }
}
Пока что цель просто выполнить хотя бы выражение d+1 при вводе в консоль d! (сам алгоритм вычисления факториала я знаю и он не составит проблем, пока беру просто d+1 дабы не захламлять код), при этом не учитывая приоритетов (потом с целью распределения приоритетов сделаю вычисление факториала отдельной функцией, а не частью primary)

Сделав изменения, показанные в двух вышенаписанных отрывках кода, ничего путного не выходит, компилятор выдаёт дефолтный кейс: "primary expected"
Извиняюсь за большой пост, но очень прошу помочь, спасибо =)
З.Ы.: если моя идея реализации совсем кривая - приводите в пример свои, это неважно, цель - добавить этот драный факториал)))

Добавлено через 3 часа 0 минут
аапппп
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.11.2011, 22:40     Факториал в калькуляторе.
Посмотрите здесь:

C++ Строка ввода в калькуляторе
C++ исправить ошибки в калькуляторе
Помогите с оператором в комплексном калькуляторе на c++ builder 6 C++
Функция дужки(приоритет операций) в калькуляторе C++
Ошибка в калькуляторе. Не могу найти C++
История введеных даных в калькуляторе C++
в калькуляторе 2+2*2=8 C++
Ошибка в калькуляторе C++
C++ По поводу исспользования классов в арифметическом калькуляторе
Проверка на скобки в строчном калькуляторе C++
Найдите ошибку в моем калькуляторе C++
C++ ошибка в калькуляторе польской инверсной записи

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Dar101
40 / 40 / 1
Регистрация: 12.05.2011
Сообщений: 109
13.11.2011, 23:24     Факториал в калькуляторе. #2
Интересно, завтра посмотрю. Напишите, если забуду.
Ruger
1 / 1 / 0
Регистрация: 25.10.2011
Сообщений: 15
14.11.2011, 18:51  [ТС]     Факториал в калькуляторе. #3
cout << "Ап!\n"
Dar101
40 / 40 / 1
Регистрация: 12.05.2011
Сообщений: 109
14.11.2011, 20:05     Факториал в калькуляторе. #4
C++
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#include "stdafx.h"
#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) { }
};
 
//------------------------------------------------------------------------------
 
class Token_stream {
public: 
    Token_stream();   // make a Token_stream that reads from cin
    Token get();      // get a Token (get() is defined elsewhere)
    void putback(Token t);    // put a Token back
private:
    bool full;        // is there a Token in the buffer?
    Token buffer;     // here is where we keep a Token put back using putback()
};
 
//------------------------------------------------------------------------------
 
// The constructor just sets full to indicate that the buffer is empty:
Token_stream::Token_stream()
    :full(false), buffer(0)    // no Token in buffer
{
}
 
//------------------------------------------------------------------------------
 
// The putback() member function puts its argument back into the Token_stream's buffer:
void Token_stream::putback(Token t)
{
    if (full) error("putback() into a full buffer");
    buffer = t;       // copy t to buffer
    full = true;      // buffer is now full
}
 
//------------------------------------------------------------------------------
 
Token Token_stream::get()
{
    if (full) {       // do we already have a Token ready?
        // remove token from buffer
        full=false;
        return buffer;
    } 
 
    char ch;
    cin >> ch;    // note that >> skips whitespace (space, newline, tab, etc.)
 
    switch (ch) {
    case '=':    // for "print"
    case 'q':    // for "quit"
    case '(': case ')': case '{': 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");
    }
}
 
//------------------------------------------------------------------------------
 
Token_stream ts;        // provides get() and putback() 
 
//------------------------------------------------------------------------------
 
double expression();    // declaration so that primary() can call expression()
 
//------------------------------------------------------------------------------
 
// deal with numbers and parentheses
double primary()
{
    Token t = ts.get();
    switch (t.kind) {
 
    case '(': case '{':    // handle '(' expression ')'
        {    
            double d = expression();
            t = ts.get();
            if (t.kind != ')' && t.kind != '}') error("')' or '}' expected");
            return d;
        }
    case '8':            // we use '8' to represent a number
        return t.value;  // return the number's value
    default:
        error("primary expected");
    }
}
 
//------------------------------------------------------------------------------
 
// deal with *, /, and %
double term()
{
    double left = primary();
    Token t = ts.get();        // get the next token from token stream
 
    while(true) {
        switch (t.kind) {
        case '!':
            {
                int result = 1;
                for (int i=1; i<=left; i++) result *= i;
                left=result;
                t = ts.get();
                break;
            }
        case '*':
            left *= primary();
            t = ts.get();
            break;
        case '/':
            {    
                double d = primary();
                if (d == 0) error("divide by zero");
                left /= d; 
                t = ts.get();
                break;
            }
        default: 
            ts.putback(t);     // put t back into the token stream
            return left;
        }
    }
}
 
//------------------------------------------------------------------------------
 
// deal with + and -
double expression()
{
    double left = term();      // read and evaluate a Term
    Token t = ts.get();        // get the next token from token stream
 
    while(true) {    
        switch(t.kind) {
        case '+':
            left += term();    // evaluate Term and add
            t = ts.get();
            break;
        case '-':
            left -= term();    // evaluate Term and subtract
            t = ts.get();
            break;
        default: 
            ts.putback(t);     // put t back into the token stream
            return left;       // finally: no more + or -: return the answer
        }
    }
}
 
//------------------------------------------------------------------------------
 
int main()
    try
{
    double val = 0;
    cout << "Welcome! Please enter an expression that contains floating-point numbers.\n";
    while (cin) {
        Token t = ts.get();
 
        if (t.kind == 'x') break; // 'x' for quit
        if (t.kind == '=')        // '=' for "print now"
            cout << "=" << val << '\n';
        else
            ts.putback(t);
        val = expression();
    }
    keep_window_open();
}
catch (exception& e) {
    cerr << "error: " << e.what() << '\n'; 
    keep_window_open();
    return 1;
}
catch (...) {
    cerr << "Oops: unknown exception!\n"; 
    keep_window_open();
    return 2;
}
 
//------------------------------------------------------------------------------
Времени сейчас мало, если будут вопросы — завтра отвечу.
Ruger
1 / 1 / 0
Регистрация: 25.10.2011
Сообщений: 15
14.11.2011, 23:39  [ТС]     Факториал в калькуляторе. #5
Мда, ларчик реально просто открывался %)
Спасибо большое))

Добавлено через 14 минут
А вот, собственно, версия с правильными приоритетами (мало ли, понадобится кому):
C++
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
//
// This is one of the exercises I am making while mastering C++.
//
 
/*
    This programm is calculating logical binar expressions such as & and | .
    & is higher priority than |.
*/
 
#include "stdafx.h"
#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) { }
};
 
//------------------------------------------------------------------------------
 
class Token_stream {
public: 
        Token_stream();   // make a Token_stream that reads from cin
        Token get();      // get a Token (get() is defined elsewhere)
        void putback(Token t);    // put a Token back
private:
        bool full;        // is there a Token in the buffer?
        Token buffer;     // here is where we keep a Token put back using putback()
};
 
//------------------------------------------------------------------------------
 
// The constructor just sets full to indicate that the buffer is empty:
Token_stream::Token_stream()
        :full(false), buffer(0)    // no Token in buffer
{
}
 
//------------------------------------------------------------------------------
 
// The putback() member function puts its argument back into the Token_stream's buffer:
void Token_stream::putback(Token t)
{
        if (full) error("putback() into a full buffer");
        buffer = t;       // copy t to buffer
        full = true;      // buffer is now full
}
 
//------------------------------------------------------------------------------
 
Token Token_stream::get()
{
        if (full) {       // do we already have a Token ready?
                // remove token from buffer
                full=false;
                return buffer;
        } 
 
        char ch;
        cin >> ch;    // note that >> skips whitespace (space, newline, tab, etc.)
 
        switch (ch) {
        case '=':    // for "print"
        case 'q':    // for "quit"
        case '(': case ')': case '{': 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");
        }
}
 
//------------------------------------------------------------------------------
 
Token_stream ts;        // provides get() and putback() 
 
//------------------------------------------------------------------------------
 
double expression();    // declaration so that primary() can call expression()
 
//------------------------------------------------------------------------------
 
// deal with numbers and parentheses
double primary()
{
        Token t = ts.get();
        switch (t.kind) {
 
        case '(': case '{':    // handle '(' expression ')'
                {    
                        double d = expression();
                        t = ts.get();
                        if (t.kind != ')' && t.kind != '}') error("')' or '}' expected");
                        return d;
                }
        case '8':            // we use '8' to represent a number
                return t.value;  // return the number's value
        default:
                error("primary expected");
        }
}
 
//------------------------------------------------------------------------------
 
double factorial()
{
        double left = primary();
        Token t = ts.get();        // get the next token from token stream
 
        while(true) {
                switch (t.kind) {
                case '!':
                        {
                                int result = 1;
                                for (int i=1; i<=left; i++)     result *= i;
                                left=result;
                                t = ts.get();
                                break;
                        }
                default: 
                        ts.putback(t);     // put t back into the token stream
                        return left;
                }
        }
}
 
// deal with *, /, and %
double term()
{
        double left = factorial();
        Token t = ts.get();        // get the next token from token stream
 
        while(true) {
                switch (t.kind) {
                case '!':
                        {
                                int result = 1;
                                for (int i=1; i<=left; i++)     result *= i;
                                left=result;
                                t = ts.get();
                                break;
                        }
                case '*':
                        left *= factorial();
                        t = ts.get();
                        break;
                case '/':
                        {    
                                double d = factorial();
                                if (d == 0) error("divide by zero");
                                left /= d; 
                                t = ts.get();
                                break;
                        }
                default: 
                        ts.putback(t);     // put t back into the token stream
                        return left;
                }
        }
}
 
//------------------------------------------------------------------------------
 
 
// deal with + and -
double expression()
{
        double left = term();      // read and evaluate a Term
        Token t = ts.get();        // get the next token from token stream
 
        while(true) {    
                switch(t.kind) {
                case '+':
                        left += term();    // evaluate Term and add
                        t = ts.get();
                        break;
                case '-':
                        left -= term();    // evaluate Term and subtract
                        t = ts.get();
                        break;
                default: 
                        ts.putback(t);     // put t back into the token stream
                        return left;       // finally: no more + or -: return the answer
                }
        }
}
 
//------------------------------------------------------------------------------
 
int main()
        try
{
        double val = 0;
        cout << "Welcome! Please enter an expression that contains floating-point numbers.\n";
        while (cin) {
                Token t = ts.get();
 
                if (t.kind == 'x') break; // 'x' for quit
                if (t.kind == '=')        // '=' for "print now"
                        cout << "=" << val << '\n';
                else
                        ts.putback(t);
                val = expression();
        }
        keep_window_open();
}
catch (exception& e) {
        cerr << "error: " << e.what() << '\n'; 
        keep_window_open();
        return 1;
}
catch (...) {
        cerr << "Oops: unknown exception!\n"; 
        keep_window_open();
        return 2;
}
 
//------------------------------------------------------------------------------
Ура мне!
Dar101
14.11.2011, 23:53     Факториал в калькуляторе.
  #6

Не по теме:

Неплохо. Я когда думал над названием еще более приоритетной операции, решил вместо factorial написать superterm : )

Yandex
Объявления
14.11.2011, 23:53     Факториал в калькуляторе.
Ответ Создать тему
Опции темы

Текущее время: 07:18. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru