Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.89/18: Рейтинг темы: голосов - 18, средняя оценка - 4.89
2 / 2 / 0
Регистрация: 19.10.2017
Сообщений: 214
1

Ввод вывод в калькуляторе

11.11.2017, 20:45. Показов 3671. Ответов 17

Author24 — интернет-сервис помощи студентам
Дали задание сделать сложный калькулятор, я с помощью книги Страуструпа сделал класс Калькулятор, но мне ещё надо, сделать перегрузку <<,>> ввода/вывода, мои попытки не увенчались успехом, поэтому прощу помощи у вас
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
#include <iostream>                             
#include <string>                               
#include <map>                                  
#include <cctype>                               
#include <sstream>                              
#include <conio.h>
#include <math.h>
 
using namespace std;
 
 
int no_of_errors;
map<string, double> table;
 
double     number_value;                           
string     string_value;                            
 
int no_of_strings;
 
enum Token_value                                    
{
    NAME, NUMBER, END, PLUS = '+', MINUS = '-', MUL = '*', DIV = '/',
    PRINT = ',', ASSIGN = '=', LP = '(', RP = ')', ST = '^'
};
 
Token_value curr_tok;   
double term(bool get);                              
double prim(bool get);                               
double expr(bool get);                              
int error(const string s);                         
Token_value get_token();
 
 class Calculator
{
 
public:
    
    double expr(bool get);
    double term(bool get);
    double prim(bool get);
    Token_value get_token();
    int error(const string s);
};
 
  
 
double Calculator::expr(bool get)                               
{
    double left = term(get);
    for (;;)                                        
    {
        switch (curr_tok)                           
        {
        case PLUS:
           left += term(true);
        break;     
        case MINUS:
           left -= term(true); 
        break;       
        default:   
            return left;                    
        };
    };
};
 
double Calculator::term(bool get)                               
{
    double left = prim(get);
    for (;;)                                        
    {
        switch (curr_tok)
        {
        case MUL:
           left *= prim(true);
        break;      
        case DIV:   
            if (double d = prim(true))      
            {
            left /= d;
            break;
            };
                return error(" DIVIZION BY ZERO");   
        case ST:
           left = pow(left,prim(true));
        break;
        default:  
            return left;
        };
    };
};
 
double Calculator::prim(bool get)                               
{
    if (get) get_token();                            
    switch (curr_tok)
    {
    case NUMBER:                                    
    {
        get_token();
        return number_value;
    };
    case NAME:
    {
        double&v = table[string_value];
        
        if ((string_value == "sin") && (get_token() == LP)){
            v = sin(expr(true));
        }
        else if ((string_value == "cos") && (get_token() == LP)){
            v = cos(expr(true));
        }
        else if ((string_value == "tg") && (get_token() == LP)){
            v = tan(expr(true));
        }
        else if ((string_value == "ln") && (get_token() == LP)){
            v = log(expr(true));
        }
        else if (get_token() == ASSIGN){
            v = expr(true);
        }
        return v;
    };
    case MINUS:   
        return -prim(true);
    case LP:
    {
        double e = expr(true);
        if (curr_tok != RP)return error(") EXPECTED");
        get_token();
        return e;
    };
    default:   
        return error(" SHOULD BE PRIMARY");
    };
};
 
Token_value Calculator::get_token()                             
{
    char ch = 0;
    do { 
        if (!cin.get(ch))return curr_tok = END; } 
    while (ch != '\n'&&isspace(ch));
    
    switch (ch)
    {
    
    case ':': 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;
 
    case ';':
    case '\n':
        no_of_strings++;
        return curr_tok = PRINT;
 
    default:
        if (isalpha(ch))
        {
            string_value = ch;
            while (cin.get(ch) && isalnum(ch))
                string_value.push_back(ch);
            cin.putback(ch);
            return curr_tok = NAME;
        };
        error(" INCORECT WORD");
        return curr_tok = PRINT;
    };
};
 
int Calculator:: error(const string s)
{
    
    cerr << no_of_strings << " - ERROR:" << s << '\n';
    no_of_errors++;
    return 1;
};
 
int main()
{
    
    Calculator a;
 
    table["pi"] = 3.1415926535897932385;
    table["e"] = 2.7128272824590452354;
 
    while (cin)
    {
        a.get_token();
        if (curr_tok == END)break;
        if (curr_tok == PRINT)continue;
        cout << a.expr(false) << '\n';
    };
    
    return no_of_errors;
};
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
11.11.2017, 20:45
Ответы с готовыми решениями:

Заменить в программе, переводящую строку в двоичный код, консольный ввод/вывод на файловый ввод/вывод
Добрый день! Помогите, пожалуйста, с программой. Программа считывает строку с клавиатуры и...

Поменять консольный ввод-вывод на файловый ввод-вывод
вот у меня калькулятор как мне сделать что б числа вводились из файла и результат записывался в...

Запись выражений, ввод–вывод информацииЗапись выражений, ввод–вывод информации
Задача 2.1. Пользуясь только операцией умножения, вычислить (A в 7-ой степени) за четыре операции....

Файловый ввод-вывод, ввод с клавиатуры и обработка массива структур
Добрый вечер)) У меня небольшой вопрос. Почему первые буквы (в названии книг) не выводит на экран?...

17
7793 / 6560 / 2984
Регистрация: 14.04.2014
Сообщений: 28,672
11.11.2017, 20:51 2
И что они должны делать? Где попытки?
0
2 / 2 / 0
Регистрация: 19.10.2017
Сообщений: 214
12.11.2017, 19:06  [ТС] 3
nmcf, перегрузка << принимает от пользователя строку с арифметическим выражением, а >> выводит результат вычисления.

Добавлено через 4 часа 39 минут
Цитата Сообщение от nmcf Посмотреть сообщение
Где попытки?
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
class Calculator
{
private:
   string q;
public:
    
    double expr(bool get);
    double term(bool get);
    double prim(bool get);
    Token_value get_token();
    int error(const string s);
    friend  ostream& operator<< ( ostream &ost, Calculator &z);
    friend istream& operator>> (istream &ist, Calculator &z);
};
 
ostream &operator<<( ostream&ost, Calculator &z)
{
 
    ost << z.q;
    return ost;
}
istream &operator>>( istream&ist,  Calculator &z)
{
    ist >> z.q;   
    return ist;
}
Я пока не силён в операторах ввода/вывода
0
7793 / 6560 / 2984
Регистрация: 14.04.2014
Сообщений: 28,672
12.11.2017, 19:57 4
У тебя через get_token() ввод? Адаптируй его.
0
2 / 2 / 0
Регистрация: 19.10.2017
Сообщений: 214
13.11.2017, 13:07  [ТС] 5
Я так понял, надо функции get_token() и operator>> слить в одну, которая и будет нашей перегрузкой ввода, верно?

Добавлено через 15 часов 4 минуты
nmcf, не получается адаптировать get_token, можешь намекнуть в каком ключе двигаться?
0
7793 / 6560 / 2984
Регистрация: 14.04.2014
Сообщений: 28,672
13.11.2017, 14:52 6
При вводе просто сохраняй строку в поле класса. А при выводе используй цикл как в main(), только вместо cin - вводи из сохранённой строки через istringstream.
0
2 / 2 / 0
Регистрация: 19.10.2017
Сообщений: 214
16.11.2017, 21:07  [ТС] 7
nmcf, не получается, возможно я не так понял
0
7793 / 6560 / 2984
Регистрация: 14.04.2014
Сообщений: 28,672
16.11.2017, 21:28 8
Показывай.
0
2 / 2 / 0
Регистрация: 19.10.2017
Сообщений: 214
16.11.2017, 22:13  [ТС] 9
1)Как я понял то, что ты мне сказал. Создаём в классе строку, допустим q. Потом считываем её в поток
C++
1
2
3
4
5
6
istream &operator>>( istream&input,  Calculator &z)
{     
    istringstream ost(z.q);
    input >> z.q;   
    return input;
}
Ты мне сказал использовать её при выводе, но я не понял как.


2)Я хотел убрать cin и вместо него input добавить (поскольку мы перегрузку делаем), но выдаёт ошибку (типо он не объявлен), я понимаю, почему не работает, но как исправить не знаю (разве что объявить вне функций istream* input, но надо что бы всё в перегрузке ввода было). Скажи прав ли я, что начал так делать?


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
#include <iostream>                             
#include <string>                               
#include <map>                                  
#include <cctype>                               
#include <sstream>                              
#include <math.h>
 
using namespace std;
 
int no_of_errors;
map<string, double> table;
 
double     number_value;                           
string     string_value;                            
 
int no_of_strings;
 
enum Token_value                                    
{
    NAME, NUMBER, END, PLUS = '+', MINUS = '-', MUL = '*', DIV = '/',
    PRINT = ',', ASSIGN = '=', LP = '(', RP = ')', ST = '^'
};
 
Token_value curr_tok;   
double term(bool get);                              
double prim(bool get);                               
double expr(bool get);                              
int error(const string s);                         
Token_value get_token();
 
class Calculator
{
    string q;
public:
    
    double expr(bool get);
    double term(bool get);
    double prim(bool get);
    Token_value get_token();
    int error(const string s);
    friend ostream& operator<< (ostream &ost, Calculator &z);
    friend istream& operator>> (istream &input, Calculator &z);
};
 
ostream &operator<<( ostream&ost, Calculator &z)
{
    ost << z.q;
    return ost;
}
istream &operator>>( istream&input,  Calculator &z)
{
    input >> z.q;   
    return input;
}
 
  
 
double Calculator::expr(bool get)                               
{
    double left = term(get);
    for (;;)                                        
    {
        switch (curr_tok)                           
        {
        case PLUS:
           left += term(true);
        break;     
        case MINUS:
           left -= term(true); 
        break;       
        default:   
            return left;                    
        };
    };
};
 
double Calculator::term(bool get)                               
{
    double left = prim(get);
    for (;;)                                        
    {
        switch (curr_tok)
        {
        case MUL:
           left *= prim(true);
        break;      
        case DIV:   
            if (double d = prim(true))      
            {
            left /= d;
            break;
            };
                return error(" DIVIZION BY ZERO");   
        case ST:
           left = pow(left,prim(true));
        break;
        default:  
            return left;
        };
    };
};
 
double Calculator::prim(bool get)                               
{
    if (get) get_token();                            
    switch (curr_tok)
    {
    case NUMBER:                                    
    {
        get_token();
        return number_value;
    };
    case NAME:
    {
        double&v = table[string_value];
        
        if ((string_value == "sin") && (get_token() == LP)){
            v = sin(expr(true));
        }
        else if ((string_value == "cos") && (get_token() == LP)){
            v = cos(expr(true));
        }
        else if ((string_value == "tg") && (get_token() == LP)){
            v = tan(expr(true));
        }
        else if ((string_value == "ln") && (get_token() == LP)){
            v = log(expr(true));
        }
        else if (get_token() == ASSIGN){
            v = expr(true);
        }
        return v;
    };
    case MINUS:   
        return -prim(true);
    case LP:
    {
        double e = expr(true);
        if (curr_tok != RP)return error(") EXPECTED");
        get_token();
        return e;
    };
    default:   
        return error(" SHOULD BE PRIMARY");
    };
};
 
Token_value Calculator::get_token()                             
{
    
    char ch = 0;
    do { 
        if (!input->get(ch))return curr_tok = END; } 
    while (ch != '\n'&&isspace(ch));
    
    switch (ch)
    {
    
    case ':': 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 '.':
        input->putback(ch);
        *input >> number_value;
        return curr_tok = NUMBER;
 
    case ';':
    case '\n':
        no_of_strings++;
        return curr_tok = PRINT;
 
    default:
        if (isalpha(ch))
        {
            string_value = ch;
            while (input->get(ch) && isalnum(ch))
                string_value.push_back(ch);
            input->putback(ch);
            return curr_tok = NAME;
        };
        error(" INCORECT WORD");
        return curr_tok = PRINT;
    };
};
 
int Calculator:: error(const string s)
{
    
    cerr << no_of_strings << " - ERROR:" << s << '\n';
    no_of_errors++;
    return 1;
};
 
int main()
{
    
    Calculator b;
 
    table["pi"] = 3.1415926535897932385;
    table["e"] = 2.7128272824590452354;
    
    /*cin >> b;
    cout <<b;*/
    while (input)
    {
        b.get_token();
        if (curr_tok == END)break;
        if (curr_tok == PRINT)continue;
        cout << b.expr(false) << '\n';
    };
    
    return no_of_errors;
};
0
7793 / 6560 / 2984
Регистрация: 14.04.2014
Сообщений: 28,672
17.11.2017, 08:13 10
Лучший ответ Сообщение было отмечено Knzj как решение

Решение

Примерно так:
C++
1
2
3
4
5
istream &operator>>( istream&input,  Calculator &z)
{     
    std::getline(input, z.q);   
    return input;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
ostream &operator<<( ostream&ost, Calculator &z)
{
    istringstream iss(z.q);
    while (iss)
    {
        z.get_token_s(iss);
        if (curr_tok == END)break;
        if (curr_tok == PRINT)continue;
        ost << z.expr(false) << '\n';
    };
    return ost;
}
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
Token_value Calculator::get_token_s(istream &iss)
{
    char ch = 0;
    do { 
        if (!iss.get(ch))return curr_tok = END; } 
    while (ch != '\n'&&isspace(ch));
    
    switch (ch)
    {
    
    case ':': 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 '.':
        iss.putback(ch);
        iss >> number_value;
        return curr_tok = NUMBER;
 
    case ';':
    case '\n':
        no_of_strings++;
        return curr_tok = PRINT;
 
    default:
        if (isalpha(ch))
        {
            string_value = ch;
            while (iss.get(ch) && isalnum(ch))
                string_value.push_back(ch);
            iss.putback(ch);
            return curr_tok = NAME;
        };
        error(" INCORECT WORD");
        return curr_tok = PRINT;
    };
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
int main()
{
    
    Calculator a;
 
    table["pi"] = 3.1415926535897932385;
    table["e"] = 2.7128272824590452354;
 
    cin >> a;
    cout << a;
    
    return no_of_errors;
};
1
2 / 2 / 0
Регистрация: 19.10.2017
Сообщений: 214
17.11.2017, 21:27  [ТС] 11
Спасибо, вроде понял, только вот одна проблема: в функции prim. Что надо писать в аргумент функции get_token_s(?).
iss объект класса istream, считывает из строки, но вне функции get_token_s. А в аргумент к get_token_s надо взять объект класса istringstream, или нет? Извини, я не могу точно сформулировать свою мысль, но надеюсь ты поймёшь о чём я.
Цитата Сообщение от Knzj Посмотреть сообщение
double Calculator:rim(bool get) * * * * * * * * * * * * * * *
{
* * if (get) get_token(??); * * * * * * * * * * * * * *
* * switch (curr_tok)
* * {
* * case NUMBER: * * * * * * * * * * * * * * * * * *
* * {
* * * * get_token(??);
* * * * return number_value;
* * };
* * case NAME:
* * {
* * * * double&v = table[string_value];
if ((string_value == "sin") && (get_token(??) == LP)){
* * * * * * v = sin(expr(true));
* * * * }
* * * * else if ((string_value == "cos") && (get_token(??) == LP)){
* * * * * * v = cos(expr(true));
* * * * }
* * * * else if ((string_value == "tg") && (get_token(??) == LP)){
* * * * * * v = tan(expr(true));
* * * * }
* * * * else if ((string_value == "ln") && (get_token(??) == LP)){
* * * * * * v = log(expr(true));
* * * * }
* * * * else if (get_token(??) == ASSIGN){
* * * * * * v = expr(true);
* * * * }
* * * * return v;
* * };
* * case MINUS: *
* * * * return -prim(true);
* * case LP:
* * {
* * * * double e = expr(true);
* * * * if (curr_tok != RP)return error(") EXPECTED");
* * * * get_token(??);
* * * * return e;
* * };
* * default: *
* * * * return error(" SHOULD BE PRIMARY");
* * };
};
0
7793 / 6560 / 2984
Регистрация: 14.04.2014
Сообщений: 28,672
17.11.2017, 21:57 12
Возможно, имеет смысл сделать iss полем класса и вообще передачу не использовать.
0
2 / 2 / 0
Регистрация: 19.10.2017
Сообщений: 214
18.11.2017, 17:18  [ТС] 13
Что-то никак..
Можешь посоветовать какую-нибудь литературу для изучения с++. Многое прочитал в интернете, а всё равно мало что получается.
0
7793 / 6560 / 2984
Регистрация: 14.04.2014
Сообщений: 28,672
18.11.2017, 20:50 14
Что никак? Не компилируется или не работает?
0
2 / 2 / 0
Регистрация: 19.10.2017
Сообщений: 214
18.11.2017, 22:37  [ТС] 15
Цитата Сообщение от nmcf Посмотреть сообщение
Возможно, имеет смысл сделать iss полем класса
Когда я iss делаю полем класса, то у меня выскакивает много ошибок.
C++
1
2
3
4
5
6
class Calculator
{
     ....
     istream &iss;
     ....
};
Мне кажется, что так нельзя делать, потому что istream это тоже класс, который к нам, данном случае, не имеет отношения. Но инициализировать iss нам надо, а что делать я не знаю.

Добавлено через 1 час 8 минут
Цитата Сообщение от Knzj Посмотреть сообщение
потому что istream это тоже класс, который к нам, данном случае, не имеет отношения.
Т. е. iss это тип класса istream
0
7793 / 6560 / 2984
Регистрация: 14.04.2014
Сообщений: 28,672
18.11.2017, 22:43 16
Лучший ответ Сообщение было отмечено Knzj как решение

Решение

C++
1
istringstream iss;
C++
1
z.iss.str(z.q);
1
2 / 2 / 0
Регистрация: 19.10.2017
Сообщений: 214
18.11.2017, 23:31  [ТС] 17
Спасибо за помощь, наконец получилось
0
0 / 0 / 0
Регистрация: 14.01.2019
Сообщений: 1
14.01.2019, 16:42 18
Knzj,
Скинь, пожалуйста, окончательный результат калькулятора очень нужно, что-то никак не получается изменить
0
14.01.2019, 16:42
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.01.2019, 16:42
Помогаю со студенческими работами здесь

Реализовать вывод массива объектов типа Student на консоль (файловый ввод/вывод)
Как сделать чтобы список студентов выводился на экран в конце? #include&lt;iostream&gt; ...

Поиск в массиве структур по заданному полю и вывод в алфавитном порядке (файловый ввод/вывод)
Помогите с функцией void runFile() что бы с файла брал и выводил в алфавитном порядке список...

Вывод суммы в файл (файловый ввод/вывод)
Добрый день! Я пытался написать программу, которая должна вводить данные из файла №1, потом...

Ввод n-значного числа, вывод цифр, из которых оно состоит и вывод суммы его цифр
Написать программу, осуществляющую ввод n-значного числа, вывод цифр, из которых оно состоит и...


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

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru