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

Приложение для вычисления значения арифметического выражения - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 28, средняя оценка - 4.75
Wera
1 / 1 / 0
Регистрация: 21.07.2010
Сообщений: 11
19.11.2010, 01:09     Приложение для вычисления значения арифметического выражения #1
Здравствуйте , подскажите пожалуйста как решить вот эту задачу :
Создать приложение для вычисления значения арифметического выражения, которое может включать в себя действительные числа, а также круглые скобки и следующие операции: +, -, *, /, ^ (возведение в степень). Вычисления должны производиться с учетом скобок и приоритетов используемых операций.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.11.2010, 01:09     Приложение для вычисления значения арифметического выражения
Посмотрите здесь:

Вычисления значения арифметического выражения на C++ C++
[C++] Разработать программу для вычисления арифметического выражения и вывода полученного результата C++
C++ Программа разбора и вычисления значения арифметического выражения
Разработать приложение для вычисления значения выражения C++
Программа на С++ для вычисления арифметического выражения C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.11.2010, 01:15     Приложение для вычисления значения арифметического выражения #2
Вот, недавно писал, тоже здесь просили)))

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
#include <iostream>
#include <vector>
#include <iomanip>
 
double expression();
double term();
double power();
double factor();
double number();
 
int main()
{
    double n;
 
    setlocale(LC_ALL, "Rus");
 
    std::cout << "Введите выражение: ";
    
    n = expression();
 
    std::cout << std::setprecision(12) << "Результат вычисления: " << n << std::endl;
 
    std::cin.get();
    std::cin.get();
    return 0;
}
 
double expression()
{
    double result;
    char operation;
 
    result = term();
 
    while (true)
    {
        operation = std::cin.get();
 
        switch (operation)
        {
        case '+':
            result += term();
            break;
        case '-':
            result -= term();
            break;
        default:
            std::cin.putback(operation);
            return result;
        }
    }
}
 
double term()
{
    double result;
    char operation;
    double temp;
 
    result = power();
 
    while (true)
    {
        operation = std::cin.get();
 
        switch (operation)
        {
        case '*':
            result *= power();
            break;
        case '/':
            temp = power();
 
            if (temp == 0.0)
            {
                std::cout << "Деление на нуль!" << std::endl;
                exit(-1);
            }
 
            result /= temp;
            break;
        default:
            std::cin.putback(operation);
            return result;
        }
    }
}
 
double power()
{
    double result;
    char operation;
    std::vector < double > args;
 
    args.push_back(factor());
 
    while (true)
    {
        operation = std::cin.get();
        
        while (operation == ' ')
            operation = std::cin.get();
 
        if (operation == '^')
            args.push_back(factor());
        else
        {
            std::cin.putback(operation);
            break;
        }
    }
 
    for (int i = args.size() - 1; i > 0; i--)
        args[i - 1] = pow(args[i - 1], args[i]);
 
    return args[0];
}
 
double factor()
{
    double result;
    char bracket;
    int sign = 1;
 
    bracket = std::cin.get();
 
    while (bracket == ' ')
        bracket = std::cin.get();
 
    switch (bracket)
    {
    case '-':
        sign = -1;
    case '+':
        bracket = std::cin.get();
        break;
    }
 
    while (bracket == ' ')
        bracket = std::cin.get();
 
    if (bracket == '(')
    {
        result = expression();
        bracket = std::cin.get();
 
        if (bracket != ')')
        {
            std::cout << "Неверная расстановка скобок!" << std::endl;
            exit(-1);
        }
    }
    else
    {
        std::cin.putback(bracket);
        result = number();
    }
 
    return sign * result;
}
 
double number()
{
    double result = 0.0;
    char digit;
    double k = 10.0;
    int sign = 1;
 
    digit = std::cin.get();
 
    switch (digit)
    {
    case '-':
        sign = -1;
        break;
    default:
        if (digit != '+')
            std::cin.putback(digit);
 
        break;
    }
 
    while (true)
    {
        digit = std::cin.get();
 
        while (digit == ' ')
            digit = std::cin.get();
 
        if (digit >= '0' && digit <= '9')
            result = result * 10.0 + (digit - '0');
        else
        {
            std::cin.putback(digit);
            break;
        }
    }
 
    digit = std::cin.get();
 
    if (digit == '.')
    {
        while (true)
        {
            digit = std::cin.get();
 
            while (digit == ' ')
                digit = std::cin.get();
 
            if (digit >= '0' && digit <= '9')
            {
                result += (digit - '0') / k;
                k *= 10.0;
            }
            else
            {
                std::cin.putback(digit);
                break;
            }
        }
    }
    else
        std::cin.putback(digit);
 
    return sign * result;
}
Wera
1 / 1 / 0
Регистрация: 21.07.2010
Сообщений: 11
03.12.2010, 22:32  [ТС]     Приложение для вычисления значения арифметического выражения #3
Вот по Вашему коду пыталась упростить задачу до посчета только + - * /
где тут ошибка :
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
#include <iostream>
using namespace std;
double expression();
double term();
 
 
 
int main()
{
    double n;
 
 
 
cout << "Vedite zadachu ";
    
    n = expression();
 
cout<< "Rezyltat: " << n << endl;
 
   cin.get();
cin.get();
    return 0;
}
 
double expression()
{
    double result;
    char operation;
 
    result = term();
 
    while (true)
    {
        operation = cin.get();
 
        switch (operation)
        {
        case '+':
            result += term();
            break;
        case '-':
            result -= term();
            break;
        default:
          cin.putback(operation);
            return result;
        }
    }
}
 
double term()
{
    double result;
    char operation;
    double temp;
    double power;
 
    result = power;
 
    while (true)
    {
        operation =cin.get();
 
        switch (operation)
        {
        case '*':
            result *= power;
            break;
        case '/':
            
            if (temp == 0.0)
            {
              cout << "Delenie na 0!" << endl;
                exit(-1);
            }
 
            result /= temp;
            break;
        default:
           cin.putback(operation);
            return result;
        }
    }
}
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
04.12.2010, 12:41     Приложение для вычисления значения арифметического выражения #4
Wera, вопрос - а зачем упрощали? У вас по заданию есть и возведение в степень, и круглые скобки.

Добавлено через 2 минуты
И ещё - это не упрощение - это, как говорится - "серпом по яйцам". Вы просто вырезали кучу кода, в том числе и жизненно важного для программы. Например, где функция number? Она, бедная, только и делала, что считывала числа, за что ж вы её так?

Добавлено через 13 минут
Если очень хочется, то вот так надо было переделать:

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
#include <iostream>
#include <iomanip>
 
double expression();
double term();
double number();
 
int main()
{
    double n;
 
    setlocale(LC_ALL, "Rus");
 
    std::cout << "Введите выражение: ";
    
    n = expression();
 
    std::cout << std::setprecision(12) << "Результат вычисления: " << n << std::endl;
 
    std::cin.get();
    std::cin.get();
    return 0;
}
 
double expression()
{
    double result;
    char operation;
 
    result = term();
 
    while (true)
    {
        operation = std::cin.get();
 
        switch (operation)
        {
        case '+':
            result += term();
            break;
        case '-':
            result -= term();
            break;
        default:
            std::cin.putback(operation);
            return result;
        }
    }
}
 
double term()
{
    double result;
    char operation;
    double temp;
 
    result = number();
 
    while (true)
    {
        operation = std::cin.get();
 
        switch (operation)
        {
        case '*':
            result *= number();
            break;
        case '/':
            temp = number();
 
            if (temp == 0.0)
            {
                std::cout << "Деление на нуль!" << std::endl;
                exit(-1);
            }
 
            result /= temp;
            break;
        default:
            std::cin.putback(operation);
            return result;
        }
    }
}
 
double number()
{
    double result = 0.0;
    char digit;
    double k = 10.0;
    int sign = 1;
 
    digit = std::cin.get();
    
    while (digit == ' ')
        digit = std::cin.get();
 
    switch (digit)
    {
    case '-':
        sign = -1;
        break;
    default:
        if (digit != '+')
            std::cin.putback(digit);
 
        break;
    }
 
    while (true)
    {
        digit = std::cin.get();
 
        while (digit == ' ')
            digit = std::cin.get();
 
        if (digit >= '0' && digit <= '9')
            result = result * 10.0 + (digit - '0');
        else
        {
            std::cin.putback(digit);
            break;
        }
    }
 
    digit = std::cin.get();
 
    if (digit == '.')
    {
        while (true)
        {
            digit = std::cin.get();
 
            while (digit == ' ')
                digit = std::cin.get();
 
            if (digit >= '0' && digit <= '9')
            {
                result += (digit - '0') / k;
                k *= 10.0;
            }
            else
            {
                std::cin.putback(digit);
                break;
            }
        }
    }
    else
        std::cin.putback(digit);
 
    digit = std::cin.get();
 
    while (digit == ' ')
        digit = std::cin.get();
 
    std::cin.putback(digit);
 
    return sign * result;
}
Wera
1 / 1 / 0
Регистрация: 21.07.2010
Сообщений: 11
05.12.2010, 14:15  [ТС]     Приложение для вычисления значения арифметического выражения #5
Спасибо , а еще как работает и зачем функция намбер ?
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
06.12.2010, 13:29     Приложение для вычисления значения арифметического выражения #6
Она посимвольно вытаскивает из потока число, пропуская при этом пробелы и учитывая знак числа.
Сначала происходит пропуск пробелов. Потом считывается символ и проверяется, не является ли он знаками "+" или "-". Если это знак "-", то в переменной sign сохраняется значение -1, иначе (если это "+") остаётся значение 1. Если это ни "+", ни "-", то считанный символ (чтобы не потеряться) возвращается обратно в поток ввода. Затем в цикле происходит считывание очередной цифры, и эта цифра "приписывается" к результат (т.е. предыдущее значение результата умножается на 10, а затем к полученному числу прибавляется только что считанная цифра). Затем, если мы считали не цифру - выходим из этого цикла, предварительно затолкав то, что мы только что считали, обратно в поток, чтобы это значение не потерялось. Затем мы снова считываем этот же символ и смотрим, не десятичная ли это точка. Если это так, то мы продолжаем считывание числа. Только теперь мы делим очередную считанную цифру на 10, на 100, на 1000 и т.д. и прибавляем полученное число к нашему результату. Ну а если мы считали не цифру - выходим из этого цикла, предварительно затолкнув считанный ранее символ обратно в поток (опять же, чтобы не потерялся). На этом считывание числа заканчивается. Разберём на примере.

Пусть в потоке ввода у нас -123.456
Считывание будет происходить так:
Сначала считается "-". В sign сохранится значение -1. result у нас равен 0. Считалась цифра 1. В result записывается 0 * 10 + 1, т.е. 1. Затем считалась 2. В result записывается 1 * 10 + 2 = 12. Затем считалась 3. result = 12 * 10 + 3 = 123. Считалась ".". Поскольку это не цифра, мы эту точку заталкиваем обратно в поток, чтобы считать её в другом месте. Выходим из цикла. Считываем точку. Поскольку это именно точка, заходим во второй цикл. k у нас изначально равна 10. Считываем 4. Получаем, что result равен 123 + 4 / 10 = 123 + 0.4 = 123.4, а k умножается на 10 и становится равна 100. Затем считываем 5. Получаем 123.4 + 5 / 100 = 123.45. k становится равна 1000. Считываем 6. Получаем result = 123.45 + 6 / 1000 = 123.45 + 0.006 = 123.456. Затем у нас в потоке будет неизвестно что (для функции number), поэтому мы выходим из цикла. Поскольку sign у нас равен -1, то функция вернёт значение -1 * 123.456, т.е. -123.456 - именно то, что мы и хотели получить.
frostua
0 / 0 / 0
Регистрация: 07.11.2011
Сообщений: 27
07.11.2011, 16:20     Приложение для вычисления значения арифметического выражения #7
Ещё вариант:

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
#include <iostream>
#include <stdio.h>
#include <math.h>
//#include <iomanip>
using namespace std;
 
double count (int n, int m, char ar[])
{
    double rez;
    bool flag=0;
    int skobka=0;
    
        
    for (int i=n; i<m; i++){
        if (ar[i]=='(')skobka+=1;
        else if (ar[i]==')')skobka-=1;
        if (skobka==0){
        if (ar[i]=='+'){
            rez = count(n,i,ar)+ count(i+1,m,ar);//сложение
            flag=1;
            break;
        }
        if (ar[i]=='-'&&ar[i-1]!='('&&i!=0){
            rez = count(n,i,ar)- count(i+1,m,ar);//вычитание
            flag=1;
            break;
        }
        }
    }
    if (flag==0)
    {
        for (int i=n; i<m; i++){
            if (ar[i]=='(')skobka+=1;
            else if (ar[i]==')')skobka-=1;
            if (skobka==0){
            if (ar[i]=='*'){
            rez = count(n,i,ar)* count(i+1,m,ar);//умножение
            flag=1;
            break;
            }
            if (ar[i]=='/'){
            rez = count(n,i,ar)/ count(i+1,m,ar);//деление
            flag=1;
            break;
            }
            }
        }
    }
    if (flag==0)
    {
        for (int i=n; i<m; i++){
            if (ar[i]=='(')skobka+=1;
            else if (ar[i]==')')skobka-=1;
            if (skobka==0){
            if (ar[i]=='^'){
            rez = pow (count(n,i,ar), count(i+1,m,ar));//возведение в степень
            flag=1;
            break;
            }
            }
        }
    }
    if (flag==0)
        if (ar[n+1]=='('&&ar[n]=='-'&&(ar[n-1]=='('||n==0))return -count(n+1,m-1,ar);
        else if (ar[n]=='(')return count(n+1,m-1,ar);
        else if (ar[n-1]=='-'&&(ar[n-2]=='('||n-2==0))return -atof(&ar[n]);
        else return atof(&ar[n]);
    else return rez;
}
 
void main()
{
 
    cout<<fixed;
    while(1){
    char a[100];
    gets(a);    
    //cout<<setprecision(20);
    cout<<count (0, strlen (a), a)<<endl;
    }
}
Neptune
2 / 2 / 1
Регистрация: 14.06.2014
Сообщений: 25
19.05.2015, 15:02     Приложение для вычисления значения арифметического выражения #8
Если все выражение вводить в переменную char, а потом функциями из string.h разбить массив символов отдельно на числа и эти числа функциями преобразовать в double - будет нормально? другого не учил а тут дали такое задание.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.05.2015, 15:11     Приложение для вычисления значения арифметического выражения #9
Neptune, если по заданию скобок в выражении быть не может - нормально, можно вычислять последовательно (за исключением того, что следует учитывать приоритеты операций). Если скобки есть - решение выложено в этой теме.
Neptune
2 / 2 / 1
Регистрация: 14.06.2014
Сообщений: 25
19.05.2015, 15:18     Приложение для вычисления значения арифметического выражения #10
silent_1991, задание аналогично тому что написано у автора темы. Обычным циклом перебирать и искать скобки, написать алгоритм приоритетов для скобок. Будет долго и много возни с этим но библиотеки iomap и vector я впервые вижу.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
19.05.2015, 18:03     Приложение для вычисления значения арифметического выражения #11
Цитата Сообщение от Neptune Посмотреть сообщение
задание аналогично тому что написано у автора темы.
Значит, так просто не получится сделать. Нужно делать одним из "сложных способов", например, рекурсивным спуском, который и реализован в моём коде.
Цитата Сообщение от Neptune Посмотреть сообщение
библиотеки iomap и vector я впервые вижу.
Во-первых, не iomap, а iomanip. В моём коде она нужна только для вызова манипулятора std::setprecision(12), который заставляет поток вывести действительное число с 12 знаками (для большей точности). Удалите этот момент - и iomanip не потребуется.
vector же - это динамически расширяемый массив. Если не хотите разобраться с ним (а разбираться там практически нечего, если вы уже знаете, что такое обычные массивы) и блеснуть знаниями на сдаче лабы - перепишите код с использованием обычных массивов (либо статических с заранее заданной большой ёмкостью, либо динамических, реализованных вручную, через new и delete).
Neptune
2 / 2 / 1
Регистрация: 14.06.2014
Сообщений: 25
19.05.2015, 23:22     Приложение для вычисления значения арифметического выражения #12
silent_1991,
ха-ха.
Мне не нужно это на лабы, а лично для себя.
Динамически расширяемый массив я тоже учился писать без библиотеки vector потому, что ее в моем учебнике не было.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
20.05.2015, 07:24     Приложение для вычисления значения арифметического выражения #13
Neptune, ну а раз для себя, то тем более советую вам разобраться с такими вещами, как библиотечные контейнеры и алгоритмы. Это существенный пробел в знаниях, без этого невозможно поддерживать ни один сколько-нибудь серьёзный проект на C++. Если в вашем учебнике не было ни слова про стандартную библиотеку, то это плохой учебник. Это как если бы в учебнике по тригонометрии были описаны синус и косинус, а про тангенс ни слова бы не было.
Вообще, надо сказать, что этот код можно написать без использования vector. Главное в данном случае - составить правильную грамматику. Парсер, написанный по правильной грамматике, разрулит правоассоциативность операции возведения в степень сам, и рекурсия заменит цикл.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.10.2016, 16:07     Приложение для вычисления значения арифметического выражения
Еще ссылки по теме:

организовать функцию для вычисления арифметического выражения записанного в постфиксной форме C++
C++ организовать функцию для вычисления арифметического выражения записанного в постфиксной форме
Реализовать программу для вычисления линейного арифметического выражения C++

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

Или воспользуйтесь поиском по форуму:
_Nemesis_
1 / 1 / 0
Регистрация: 02.07.2016
Сообщений: 10
01.10.2016, 16:07     Приложение для вычисления значения арифметического выражения #14
Подскажите пожалуйста, а как в вашей программе можно реализовать проверку на неверные символы, лишние скобки и прочее, чтобы выдавало подсказку в какой части выражения допустил ошибку?
Yandex
Объявления
01.10.2016, 16:07     Приложение для вычисления значения арифметического выражения
Ответ Создать тему
Опции темы

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