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

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

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 28, средняя оценка - 4.75
Wera
1 / 1 / 0
Регистрация: 21.07.2010
Сообщений: 11
#1

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

19.11.2010, 01:09. Просмотров 4446. Ответов 13
Метки нет (Все метки)

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

Разработать приложение для вычисления значения выражения - C++
attachmentid=195329&stc=1&d=1351422860 Простите но по другому не знаю как выложить задание!

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

Написать программу вычисления значения арифметического выражения - C++
Написать программу вычисления значения арифметического выражения, согласно варианта индивидуального задания. Исходные данные a и b...

Программа разбора и вычисления значения арифметического выражения - C++
Написать программу разбора и вычисления значения арифметического выражения. На входе программы — строка, содержащая числа, скобки «(» и...

Программа на С++ для вычисления арифметического выражения - C++
помогите пожалуйста написать программу, для вычисления ниже приведенного выражения само выражение

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

13
silent_1991
Эксперт С++
4993 / 3051 / 149
Регистрация: 11.11.2009
Сообщений: 7,038
Завершенные тесты: 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;
}
0
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;
        }
    }
}
0
silent_1991
Эксперт С++
4993 / 3051 / 149
Регистрация: 11.11.2009
Сообщений: 7,038
Завершенные тесты: 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;
}
0
Wera
1 / 1 / 0
Регистрация: 21.07.2010
Сообщений: 11
05.12.2010, 14:15  [ТС] #5
Спасибо , а еще как работает и зачем функция намбер ?
0
silent_1991
Эксперт С++
4993 / 3051 / 149
Регистрация: 11.11.2009
Сообщений: 7,038
Завершенные тесты: 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 - именно то, что мы и хотели получить.
0
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;
    }
}
0
Neptune
2 / 2 / 1
Регистрация: 14.06.2014
Сообщений: 27
19.05.2015, 15:02 #8
Если все выражение вводить в переменную char, а потом функциями из string.h разбить массив символов отдельно на числа и эти числа функциями преобразовать в double - будет нормально? другого не учил а тут дали такое задание.
0
silent_1991
Эксперт С++
4993 / 3051 / 149
Регистрация: 11.11.2009
Сообщений: 7,038
Завершенные тесты: 1
19.05.2015, 15:11 #9
Neptune, если по заданию скобок в выражении быть не может - нормально, можно вычислять последовательно (за исключением того, что следует учитывать приоритеты операций). Если скобки есть - решение выложено в этой теме.
0
Neptune
2 / 2 / 1
Регистрация: 14.06.2014
Сообщений: 27
19.05.2015, 15:18 #10
silent_1991, задание аналогично тому что написано у автора темы. Обычным циклом перебирать и искать скобки, написать алгоритм приоритетов для скобок. Будет долго и много возни с этим но библиотеки iomap и vector я впервые вижу.
0
silent_1991
Эксперт С++
4993 / 3051 / 149
Регистрация: 11.11.2009
Сообщений: 7,038
Завершенные тесты: 1
19.05.2015, 18:03 #11
Цитата Сообщение от Neptune Посмотреть сообщение
задание аналогично тому что написано у автора темы.
Значит, так просто не получится сделать. Нужно делать одним из "сложных способов", например, рекурсивным спуском, который и реализован в моём коде.
Цитата Сообщение от Neptune Посмотреть сообщение
библиотеки iomap и vector я впервые вижу.
Во-первых, не iomap, а iomanip. В моём коде она нужна только для вызова манипулятора std::setprecision(12), который заставляет поток вывести действительное число с 12 знаками (для большей точности). Удалите этот момент - и iomanip не потребуется.
vector же - это динамически расширяемый массив. Если не хотите разобраться с ним (а разбираться там практически нечего, если вы уже знаете, что такое обычные массивы) и блеснуть знаниями на сдаче лабы - перепишите код с использованием обычных массивов (либо статических с заранее заданной большой ёмкостью, либо динамических, реализованных вручную, через new и delete).
0
Neptune
2 / 2 / 1
Регистрация: 14.06.2014
Сообщений: 27
19.05.2015, 23:22 #12
silent_1991,
ха-ха.
Мне не нужно это на лабы, а лично для себя.
Динамически расширяемый массив я тоже учился писать без библиотеки vector потому, что ее в моем учебнике не было.
0
silent_1991
Эксперт С++
4993 / 3051 / 149
Регистрация: 11.11.2009
Сообщений: 7,038
Завершенные тесты: 1
20.05.2015, 07:24 #13
Neptune, ну а раз для себя, то тем более советую вам разобраться с такими вещами, как библиотечные контейнеры и алгоритмы. Это существенный пробел в знаниях, без этого невозможно поддерживать ни один сколько-нибудь серьёзный проект на C++. Если в вашем учебнике не было ни слова про стандартную библиотеку, то это плохой учебник. Это как если бы в учебнике по тригонометрии были описаны синус и косинус, а про тангенс ни слова бы не было.
Вообще, надо сказать, что этот код можно написать без использования vector. Главное в данном случае - составить правильную грамматику. Парсер, написанный по правильной грамматике, разрулит правоассоциативность операции возведения в степень сам, и рекурсия заменит цикл.
1
_Nemesis_
1 / 1 / 0
Регистрация: 02.07.2016
Сообщений: 11
01.10.2016, 16:07 #14
Подскажите пожалуйста, а как в вашей программе можно реализовать проверку на неверные символы, лишние скобки и прочее, чтобы выдавало подсказку в какой части выражения допустил ошибку?
0
01.10.2016, 16:07
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.10.2016, 16:07
Привет! Вот еще темы с ответами:

Организовать функцию для вычисления арифметического выражения записанного в постфиксной форме - C++
Нужна программа: Организовать функцию для вычисления арифметического выражения записанного в постфиксной форме Заранее благодарю ...

организовать функцию для вычисления арифметического выражения записанного в постфиксной форме - C++
Нужна программа: Организовать функцию для вычисления арифметического выражения записанного в постфиксной форме Заранее благодарю ...

Паскаль.Разработать программу для вычисления арифметического выражения и вывода полученного результата - C++
Ребят помогите Разработать программу для вычисления арифметического выражения и вывода полученного результата.Соответствующие исходные...

Приложение для вычисления выражения - C++
Нужно разработать приложение для вычисления выражения.Корень x в 5 степени умножить на сумму arctg z и квадратного cos от x. Я начал но...


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

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

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