Форум программистов, компьютерный форум, киберфорум
Наши страницы

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 27, средняя оценка - 4.96
ЛазаретЪ
1 / 1 / 0
Регистрация: 04.02.2011
Сообщений: 30
#1

Как работает калькулятор? - C++

23.05.2011, 20:42. Просмотров 3374. Ответов 21
Метки нет (Все метки)

Помогите подробней код разобрать и прокомментировать назначение переменных, функций...

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
#include <iostream>
#include <vector>
#include <cmath>
#include <iomanip>
 
double number();
double factor();
double expr();
double brackets();
double power();
 
int main()
{
    double n;
 
    setlocale(LC_ALL, "Rus");
 
    std::cout << "Введите выражение: ";
 
    n = expr();
 
    std::cout << "Результат вычисления: " << std::setprecision(10) << n << std::endl;
 
    std::cin.get();
    return 0;
}
 
double number()
{
    double result = 0.0;
    double k = 10.0;
    int sign = 1;
    char c;
 
    c = std::cin.get();
 
    while (c == ' ')
        c = std::cin.get();
 
    if (c == '-')
        sign = -1;
    else
    {
        if (c != '+')
            std::cin.putback(c);
    }
 
    while (true)
    {
        c = std::cin.get();
 
        while (c == ' ')
            c = std::cin.get();
 
        if (c >= '0' && c <= '9')
            result = result * 10.0 + (c - '0');
        else
        {
            std::cin.putback(c);
            break;
        }
    }
 
    c = std::cin.get();
 
    if (c == '.')
    {
        while (true)
        {
            c = std::cin.get();
 
            if (c >= '0' && c <= '9')
            {
                result += (c - '0') / k;
                k *= 10.0;
            }
            else
            {
                std::cin.putback(c);
                break;
            }
        }
    }
    else
        std::cin.putback(c);
 
    return sign * result;
}
 
double factor()
{
    double result;
    double temp;
    char op;
 
    result = power();
 
    while (true)
    {
        op = std::cin.get();
 
        while (op == ' ')
            op = std::cin.get();
 
        switch (op)
        {
        case '*':
            result *= power();
            break;
        case '/':
            temp = power();
 
            if (temp == 0.0)
            {
                std::cout << "Деление на нуль!" << std::endl;
                exit(-1);
            }
 
            result /= temp;
            break;
        default:
            std::cin.putback(op);
            return result;
        }
    }
}
 
double expr()
{
    double result;
    char op;
 
    result = factor();
 
    while (true)
    {
        op = std::cin.get();
 
        while (op == ' ')
            op = std::cin.get();
 
        switch (op)
        {
        case '+':
            result += factor();
            break;
        case '-':
            result -= factor();
            break;
        default:
            std::cin.putback(op);
            return result;
        }
    }
}
 
double brackets()
{
    double result;
    int sign = 1;
    char op;
 
    op = std::cin.get();
 
    while (op == ' ')
        op = std::cin.get();
 
    if (op == '-')
    {
        sign = -1;
        op = std::cin.get();
    }
    else
    {
        if (op == '+')
            op = std::cin.get();
    }
 
    while (op == ' ')
        op = std::cin.get();
 
    if (op == '(')
    {
        result = sign * expr();
 
        op = std::cin.get();
 
        if (op != ')')
        {
            std::cout << "Неверная расстановка скобок!" << std::endl;
            exit(-1);
        }
 
        return result;
    }
    else
    {
        std::cin.putback(op);
 
        return sign * number();
    }
}
 
double power()
{
    double result;
    char op;
    std::vector < double > args;
 
    args.push_back(brackets());
 
    while (true)
    {
        op = std::cin.get();
        
        while (op == ' ')
            op = std::cin.get();
 
        if (op == '^')
            args.push_back(brackets());
        else
        {
            std::cin.putback(op);
            break;
        }
    }
 
    for (int i = args.size() - 1; i > 0; i--)
        args[i - 1] = pow(args[i - 1], args[i]);
 
    return args[0];
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.05.2011, 20:42
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Как работает калькулятор? (C++):

Как работает калькулятор? - C++
100500-й раз задаю вопрос про этот калькулятор. Возможно, сам виноват - формулировал неточно. Ну, так вот: пожалуйста, опишите на примере...

Простой калькулятор: Не работает код, как это исправить? - C++
Здравствуйте! Вот имеется такой код, взят отсюда, https://code-live.ru/post/cpp-variables-and-datatypes/#more и он как бы получается не...

Почему так странно работает калькулятор - C++
Здраствуйте, я сегодня решил взяться за C++, решил написать самое простое, калькулятор: #include &lt;cstdlib&gt; #include &lt;iostream&gt; ...

Неправильно работает небольшая программа-калькулятор - C++
это калькулятор фунтов, шиллингов и пенсов по старой системе. он должен уметь складывать, вычитать суммы, а также, умножать на число....

Как это работает? Я хочу спросить как работает C++ и где можно про него почитать - C++
Привет, котоны. Заранее благодарю. Это будет моих общих вопросов нить, т.к. создавать целую ветку для каждого нецелесообразно. Я хочу...

Как доделать калькулятор на С/С++ ? - C++
Помогите пожалуйста в калькулятором. У меня есть уже скобки и возведение в степень. Мня нужно добавить ещё косинусы, синусы, квадратный...

21
yekka
386 / 150 / 8
Регистрация: 12.05.2011
Сообщений: 450
23.05.2011, 20:46 #2
а что конкретно непонятно?
0
ЛазаретЪ
1 / 1 / 0
Регистрация: 04.02.2011
Сообщений: 30
23.05.2011, 21:01  [ТС] #3
Больше всего интересует, как здесь происходит работа со скобками.
0
silent_1991
Эксперт С++
4993 / 3051 / 149
Регистрация: 11.11.2009
Сообщений: 7,038
Завершенные тесты: 1
24.05.2011, 00:45 #4
Логика работы подчиняется такой формальной грамматике
Код
// <цифра> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
// <число> ::= <цифра> { <цифра> } [ '.' <цифра> { <цифра> } ]
// 
// <выражение> ::= <слагаемое> [ ( '+' | '-' ) <слагаемое> ]
// <слагаемое> ::= <множитель> [ ( '*' | '/' ) <множитель> ]
// <множитель> ::= ( <число> | '(' <выражение> ')' ) [ '^' <множитель> ]
Правда в этом коде немножко набыдлокодил со степенью, можно было (если посмотреть на грамматику) реализовать куда проще и естественнее, но переделывать лень...
1
Chipnddail
14 / 14 / 1
Регистрация: 03.09.2009
Сообщений: 109
24.05.2011, 06:46 #5
Советую поискать про Обратную Польскую Запись.
С ее помощью можно наиболее эффективно разбирать даже сложные скобочные выражения.
Не так давно сам попробовал реализовать что-то вроде калькулятора на c99.

Возможно, пригодится мой код. Он довольно подробно прокомментирован.
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
/*Методы для преобразования входной текстовой строки в тесктовоую строку
 * в обратной польской записи для дальнейшего вычисления
 Бесскобочная символика Лукашевича*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include "Stack.h"
 
static struct stack *opers_head = NULL; //указатель вершины стека операторов
struct stack *operands = NULL; //указатель вершины стека операндов
extern void operate(char c);
 
int isDigit(char c){ //определяет цифру
    return (c>='0' && c<='9');
}
 
int get_prior(char c){ //возвращает приоритет операции
    switch(c){
        case '(':
            return 0;
        case ')':
            return 1;
        case '+':
        case '-':
            return 2;
        case '*':
        case '/':
            return 3;
        default:
            return -1;
    }
}
int CalcOPN(char *input){
    char c;//Входной символ для анализа
    char buff[11]; //буфер для символов числа для преобразования в число
    char* buff_ptr = buff; //указатель на буфер символов
    int prior; //Приоритет оператора
    int left_oper_count = 0; //число появления открывающей скобки
    //Вынимаем по одному символу из входной строки
    while ((c=*input++)!='\0'){
        //если входной символ операнд(цифра), пишем в буфер
        if (isDigit(c))
        {
            *(buff_ptr++) = c;
        }
        else
        {
            //если оператор, выясняем приоритет
            prior=get_prior(c);
            //символ не является цифрой или оператором
            if (prior==-1){
                //завершаем программу с ошибкой
                fputs("Введен неверный символ", stdout);
                return(EXIT_FAILURE);
            }
            else{
                //есть символы в буфере (был считан операнд)
                //преобразуем его в int и положим в стек операндов
                if (buff_ptr > buff){
                    *buff_ptr = '\0';//нулевой символ в конце строки
                //Преобразованный символ помещаем в стек операндов 
                    push(atoi(buff), &operands);
                //Возвращаем указатель на начало массива
                    buff_ptr = buff;
                }
                    switch(c) {
                        case '(':
                            //увеличить счетчик открытых скобок
                            ++left_oper_count;
                            //затолкать скобку в стек
                            push(c, &opers_head);
                            break;
                        case '+': case '-': case '/': case '*':
               //если стек непустой проверяем приоритеты
                            if (!isEmptyStack(opers_head)) {                              
               //выталкиваем из стека операторы с равным и большим приоритетом
                                while (get_prior(c) < get_prior(peek(opers_head)))
                //вычисляем результат операции и пишем в стек операндов
                                            operate(pop(&opers_head));
                            }
               //заталкиваем орератор в стек
                            push(c, &opers_head);
                            break;
                        case ')':
                            //если нет открывающей скобки
                            if (left_oper_count<=0){
                                fputs("Непарные скобки", stdout);
                                return(EXIT_FAILURE);
                            }
                            //если есть открывающие
                            else {
                             //выталкиваем из стека все, что между скобками
                                while ((c=pop(&opers_head)) != '(')
                             //вычисляем результат и пишем в стек операндов
                                    operate(c);
                                //уменьшаем счетчик открытых скобок
                                --left_oper_count;
                            }
                            break;
                    }
            }
        }
    }
    //если буфер символов не пуст (был считан операнд)
    //преобразуем его в int и положим в стек операндов
    if (buff_ptr>buff){
        *buff_ptr = '\0';//нулевой символ в конце строки
        //Преобразованный символ помещаем в стек операндов 
        push(atoi(buff), &operands);
        //Возвращаем указатель на начало массива
        buff_ptr = buff;
    }
     //выталкием все, что осталось в стеке опрераторов
    while(!isEmptyStack(opers_head))
        //вычисляем результат и пишем в стек операндов
        operate(pop(&opers_head));
    return(EXIT_SUCCESS);
}
 
//вычисление над операндами на основе поступившего оператора
//реализованы только бинарные операции
void operate(char c) {
    //Извлекаем из стека два операнда
    int b = pop(&operands);
    int a = pop(&operands);
    switch(c){
        case '+':
            push(a + b, &operands);
            break;
        case '-':
            push(a - b, &operands);
            break;
        case '/':
            push(a / b, &operands);
            break;
        case '*':
            push(a * b, &operands);
            break;
    }
}
1
Dejust
49 / 49 / 1
Регистрация: 31.01.2011
Сообщений: 156
24.05.2011, 08:30 #6
Цитата Сообщение от ЛазаретЪ Посмотреть сообщение
подробней код разобрать
По всей видимости, в листинге для решения задачи реализован нисходящий разбор.

Интересная штука кстати
0
Chipnddail
14 / 14 / 1
Регистрация: 03.09.2009
Сообщений: 109
24.05.2011, 09:39 #7
Алгоритм аналогичен алгоритму для перевода в Обратную польскую запись
Просто не выводит в строку, а сразу реализует вычисления без вывода в строку.
0
ЛазаретЪ
1 / 1 / 0
Регистрация: 04.02.2011
Сообщений: 30
24.05.2011, 14:27  [ТС] #8
А как "расшифровать" например строку
C++
1
std::cin.get();
?
Это что-то из области ООП?
0
diagon
Higher
1932 / 1198 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
24.05.2011, 14:29 #9
Ожидание ввода символа
get-метод объекта std::cin (да, это ООП)
0
silent_1991
Эксперт С++
4993 / 3051 / 149
Регистрация: 11.11.2009
Сообщений: 7,038
Завершенные тесты: 1
24.05.2011, 14:46 #10
Цитата Сообщение от Chipnddail Посмотреть сообщение
Алгоритм аналогичен алгоритму для перевода в Обратную польскую запись
Если вы про мой код, то никакой аналогии ОПЗ там нет.
0
ЛазаретЪ
1 / 1 / 0
Регистрация: 04.02.2011
Сообщений: 30
24.05.2011, 14:47  [ТС] #11
Цитата Сообщение от diagon Посмотреть сообщение
Ожидание ввода символа
get-метод объекта std::cin (да, это ООП)
ООП без классов?
0
silent_1991
Эксперт С++
4993 / 3051 / 149
Регистрация: 11.11.2009
Сообщений: 7,038
Завершенные тесты: 1
24.05.2011, 14:49 #12
ЛазаретЪ, кто сказал, что без классов? Да, программа написана в процедурном стиле, однако в ней используются стандартные объекты стандартных библиотечных классов (тот же std::cin - объект класса istrem).
1
ЛазаретЪ
1 / 1 / 0
Регистрация: 04.02.2011
Сообщений: 30
24.05.2011, 14:51  [ТС] #13
Т.е. классы уже прописаны в стандартной библиотеке?
0
silent_1991
Эксперт С++
4993 / 3051 / 149
Регистрация: 11.11.2009
Сообщений: 7,038
Завершенные тесты: 1
24.05.2011, 14:54 #14
ЛазаретЪ, разумеется, иначе какое удовольствие в использовании голого языка? Думаю, в любом более-менее приличном языке есть стандартная библиотека с реализациями часто используемого инструментария. Не будь её, вы бы даже на экран ничего вывести не смогли без использования низкоуровневых системных API.
1
ЛазаретЪ
1 / 1 / 0
Регистрация: 04.02.2011
Сообщений: 30
24.05.2011, 15:09  [ТС] #15
Спасибо, буду дальше разбираться и задавать вопросы, если что.
0
24.05.2011, 15:09
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.05.2011, 15:09
Привет! Вот еще темы с ответами:

Простой калькулятор и калькулятор с парсингом - C++
Ребят я совсем не давно только начал изучать сишку, решил написать простенький калькулятор который работает с 2 числами. Возник вопрос, как...

Посоветуйте как написать калькулятор - C++
Как применить знания на практике? Есть ли такие учебники с не сложными задачи? Как написать калькулятор? И Где лучше всего учить С++?

Как открыть калькулятор через С++ ? - C++
Здравствуйте! Меня интересует такой вопрос: как открыть в програме С++ например калькулятор ? Я просто пишу мини ОС и очень нужна помощ...

Как сделать с кода настоящий калькулятор? - C++
Вопрос: есть код,откомпилированный. Как сделать с него .exeшник? Можно сказать что моя первая программа, так что не судите строго)) ...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.