Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.82/11: Рейтинг темы: голосов - 11, средняя оценка - 4.82
0 / 0 / 0
Регистрация: 17.06.2016
Сообщений: 36

Вычислить значение арифметического выражения методом двух стеков

05.01.2018, 13:41. Показов 2416. Ответов 2
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Вычислить значение арифметического выражения методом двух стеков.
В общем это и всё задание.
Я написал просто класс с 2 стеками, для чисел и знаков.
C++ (Qt)
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
#include "MathEval.h"
#pragma once
class Stack
{
    int count;
    char arr_num[20];           //стэк для чисел
    int arr_zn[20];             //стек для знаков
    int idx_zn;                 //индекс стека знаков 
    int idx_num;                //индекс стека чисел 
public:
    friend MathEval;
    Stack();
    void Push_num(int);
    void Push_znak(char);
    int Pop_num();
    char Pop_znak();
    int Peek_num();
    char Peek_zn();
    ~Stack();
};
 
#include <iostream>
using namespace std;
#include "Stack.h"
#include "MathEval.h"
 
Stack::Stack() :idx_zn(-1), idx_num(-1) 
{
    cout << "\n\t Constr 0 STACK";
}
 
void Stack::Push_num(int NUM)
{
    arr_num[++idx_num] = NUM;
}
void Stack::Push_znak(char ZN)
{
    arr_zn[++idx_zn] = ZN;
}
int Stack::Pop_num()
{
    return arr_num[idx_num--];
}
char Stack::Pop_znak()
{
    return arr_zn[idx_zn--];
}
int Stack::Peek_num()
{
    return arr_num[idx_num];
}
char Stack::Peek_zn()
{
    return arr_zn[idx_zn];
}
 
Stack::~Stack()
{
}
Это даже без проверки полный или пустой стек.
И класс для передачи уравнения в виде массива char
C++ (Qt)
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
#pragma once
#include "Stack.h"
 
class MathEval
{
    Stack Uni;              //стеки
    char *mas;              //для хранения уравнения
    int len;                //размер массива где хранится уравнение
    int idx_mas;            //для движения по уравнению
public:
    MathEval();
    MathEval(char*);
    void Show_Uravn();
    ~MathEval();
};
 
#include <iostream>
using namespace std;
#include "MathEval.h"
#include "Stack.h"
 
MathEval::MathEval()
{
    mas = NULL;
    len = 0;
    cout << "\nConstr 0 MathEval";
}
MathEval::MathEval(char*arr)
{
    len = strlen(arr);
    mas = new char[len + 1];
    strncpy(mas, arr, len);
    mas[len] = '\0';
    cout << "\nConstr char MathEval";
}
void MathEval::Show_Uravn()
{
    cout << mas;
}
MathEval::~MathEval()
{
    delete[]mas;
    cout << "\nDestr MathEval"; 
}
Во первых я в ступоре как распарсить и какие условия надо ставить. Ну и еще не покидает ощущение, что пошел не по тому пути.
Кто понимает пожалуйста как это делается. Просьба доступными словами)
Спасибо
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
05.01.2018, 13:41
Ответы с готовыми решениями:

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

Вычислить значение арифметического выражения
Вычислить значение арифметического выражения

Вычислить значение арифметического выражения.
Дана последовательность символов, имеющая следующий вид: p1q1p2q2p3...qnpn, где pi — цифра, а qi — знак арифметического действия из набора...

2
0 / 0 / 0
Регистрация: 17.06.2016
Сообщений: 36
11.01.2018, 17:48  [ТС]
Ну же, подскажите, тем кто понимает в этом проблем 0
0
0 / 0 / 0
Регистрация: 17.06.2016
Сообщений: 36
15.01.2018, 12:05  [ТС]
В общем справился кое как сам, выложу сюда, может кому пригодится
Действия которые выполняет * умножение, / деление, + плюс, - минус, ^ возведение в степень, ( ) учитываются скобки. Вроде как работает, всё что проверял с онлайн калькуляторами считало. Найдете ошибки - пишите, мне только на пользу пойдет. Проверку на пробелы или неправильные знаки не делал, типа мы все пишем правильно.

Итак, класс под 2 стэка, разбивка на хидер и срр
C++ (Qt)
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
#pragma once
class Stack
{
    //int count;
    double arr_num[20];         //стэк для чисел
    char arr_zn[20];                //стек для знаков
    int idx_zn;                 //индекс стека знаков 
    int idx_num;                //индекс стека чисел 
public: 
    Stack();
    void Push_num(double);
    void Push_znak(char);
    double Pop_num();
    char Pop_znak();
    double Peek_num();
    char Peek_zn();
    const int Get_idx_num() const;
    const int Get_idx_zn() const;
    ~Stack();
};
 
 
#include <iostream>
using namespace std;
#include "Stack.h"
#include "MathEval.h"
 
Stack::Stack() :idx_zn(-1), idx_num(-1) 
{
    //cout << "\n\t Constr 0 STACK";
}
 
void Stack::Push_num(double NUM)
{
    arr_num[++idx_num] = NUM;
    //cout << "\narr_num[idx_num] = " << arr_num[idx_num];
}
void Stack::Push_znak(char ZN)
{
    arr_zn[++idx_zn] = ZN;
}
double Stack::Pop_num()
{
    return arr_num[idx_num--];
}
char Stack::Pop_znak()
{
    return arr_zn[idx_zn--];
}
double Stack::Peek_num()
{
    return arr_num[idx_num];
}
char Stack::Peek_zn()
{   
    return arr_zn[idx_zn];
}
const int Stack::Get_idx_num() const
{
    return idx_num;
}
const int Stack::Get_idx_zn() const
{
    return idx_zn;
}
Stack::~Stack()
{
    //cout << "\n\tDestr STack";
}
класс в котором уже именно расчеты идут

C++ (Qt)
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
//на пробелы и ошибки проверок не делалось, 
//при необходимости их можно убрать либо выводить индекс где ошибка.
 
#pragma once
#include "Stack.h"
 
class MathEval
{
    Stack Uni;              //стеки
    char *mas;              //для хранения уравнения
    int len;                //размер массива где хранится уравнение
    int idx_mas=0;          //для движения по уравнению
    double Rez = 0;
public:
    MathEval();
    MathEval(char*);
    void Show_Uravn();
    bool Uravnenie(double&);
    bool do_while();                    //вынесу в отдельное чтобы не повторяться в коде
    bool is_Number(char);
    ~MathEval();
};
 
#include <iostream>
#include <cmath>
using namespace std;
#include "MathEval.h"
#include "Stack.h"
 
MathEval::MathEval()
{
    mas = NULL;
    len = 0;
    //cout << "\nConstr 0 MathEval";    
}
MathEval::MathEval(char*arr)
{
    len = strlen(arr);
    mas = new char[len + 1];
    strncpy(mas, arr, len);
    mas[len] = '\0';
    //cout << "\nConstr char MathEval";
}
void MathEval::Show_Uravn()
{
    cout << mas;
}
bool MathEval::is_Number(char Symbol)   //проверка цифра или нет
{
    if (Symbol >= '0' && Symbol <= '9')
        return true;
    return false;
}
bool MathEval::Uravnenie(double &rez)
{
    char *pmas = mas;
    do{
        if (is_Number(*pmas))
        {
            Uni.Push_num(atof(pmas));
            while (is_Number(*pmas) || *pmas == ',' || *pmas == '.'){
                pmas++;
            }
        }
        else
        {
            if (*pmas == '^')   {           // возведение в степень
                double A = Uni.Pop_num();
                pmas++;
                if (*pmas == '(') {
                    Uni.Push_znak(*pmas); 
                    pmas++;
                }
                A = pow(A, atof(pmas));
                Uni.Push_num(A);
                if (*pmas == '-') pmas++;
                while (is_Number(*pmas) || *pmas == ',' || *pmas == '.'){
                    pmas++;
                }
                if (Uni.Peek_zn() == '(' && *pmas == ')') {
                    Uni.Pop_znak();
                    pmas++;
                }
            }
            else if (Uni.Get_idx_zn() < 0 || *pmas == '(')
            {
                Uni.Push_znak(*pmas);           //вталкиваем знак и увеличиваем индекс массива               
                pmas++;
            }
            else if (Uni.Peek_zn() == '(')
            {
                Uni.Push_znak(*pmas);           //вталкиваем знак и увеличиваем индекс массива               
                pmas++;
            }
            else if (*pmas == ')')
            {
                bool t = do_while();
                if (t == false) return false;
                pmas++;
            }
            else if (Uni.Peek_zn() == '+' || Uni.Peek_zn() == '-' && Uni.Peek_zn() != '(')
            {
                if (*pmas == '+' || *pmas == '-'){
                    //cout << "\n\n*pmas" << (char)(*pmas);
                    //cout << "\n\n*.Peek_zn()" << Uni.Peek_zn();                   
                    do{
                        char znak_pr = Uni.Pop_znak();          //znak_pr - previos
                        double A = Uni.Pop_num();
                        double B = Uni.Pop_num();
                        if (znak_pr == '+')     {
                            //cout << "\n B + A\t" << B << "+" << A << "=" << B + A;
                            Uni.Push_num(B + A);
                        }
                        else        {
                            Uni.Push_num(B - A);
                            //cout << "\n B - A\t" << B << "-" << A << "=" << B - A;
                        }
                    } while (Uni.Peek_zn() == '+' || Uni.Peek_zn() == '-' && *pmas == '+' || *pmas == '-');
                    Uni.Push_znak(*pmas);
                    //idx_mas++;
                    pmas++;
                }
                else if (*pmas == '*' || *pmas == '/')
                {
                    //cout << "\n\n*pmas" << (char)(*pmas);
                    //cout << "\n\n*.Peek_zn()" << Uni.Peek_zn();
                    Uni.Push_znak(*pmas);
                    pmas++;
                }
            }
 
            else if (Uni.Peek_zn() == '*' || Uni.Peek_zn() == '/' && *pmas == '+' || *pmas == '-' || *pmas == '*' || *pmas == '/' && Uni.Peek_zn() != '(')
            {
                char znak_pr = Uni.Pop_znak();          //znak_pr - previos
                double A = Uni.Pop_num();
                double B = Uni.Pop_num();
                if (znak_pr == '*')     {
                    //cout << "\n B * A=\t" << B << "*" << A << "=" << B * A;
                    Uni.Push_num(B * A);
                }
                else        {
                    if (A == 0){
                        //cout << "\nDivision by zero";
                        return false;
                    }
                    Uni.Push_num(B / A);
                    //cout << "\n B / A=\t" << B << "/" << A << "=" << B / A;
                }
                Uni.Push_znak(*pmas);
                pmas++;
            }
        }
    } while (*pmas != '\0');
    bool t = true;
    if (Uni.Get_idx_num()>0)t  = do_while();
    if (t == false) return false;
    rez = Uni.Pop_num();
    return true;
}
bool MathEval::do_while()               //просто вынесенный цикл в метод
{
    do{
        double A = Uni.Pop_num();
        double B = Uni.Pop_num();
        char znak_pr = Uni.Pop_znak();
        switch (znak_pr){
        case '+':
            Uni.Push_num(B + A);
            break;
        case '-':
            Uni.Push_num(B - A);
            break;
        case '*':
            Uni.Push_num(B*A);
            break;
        case'/':
            if (A == 0) {
                cout << "\nDivision by zero (do_while)";
                return 0;
            }
            else {
                Uni.Push_num(B / A);
                break;
            }
        }
    } while (Uni.Get_idx_num() != 0 && Uni.Peek_zn() != '(');
    if (Uni.Peek_zn() == '(')
        Uni.Pop_znak();
    return true;
}
MathEval::~MathEval()
{
    delete[]mas;
    //cout << "\nDestr MathEval";   
}
ну и мэйн, там есть ненужное, но убрать не составит никому труда

C++ (Qt)
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
#include <iostream>
#include <time.h>
#include <conio.h>
using namespace std;
 
#include "MathEval.h"
#include "Stack.h"
void main()
{
 
    
 
    //пример решения задачи методом двух стэков, сделано для + - * / () и возведение в степень, с проверкой деления на 0
    cout << "\n\n\t\tTwo-stack calculation\n\n";
    double Rez;
    bool T;
    //пример 1        ответ      0.00113781186834788035220
    MathEval G("2.6/(0.8*(66.12-1.36)+12.33*3^6/2/2.9-2)*6.3/3^2");     
    T = G.Uravnenie(Rez);
    if (T == false) cout << "\n\nDIVISION BY ZERO";
    else    cout << "\n\nRez=" << Rez;
    //пример 2        ответ      -791.9076893593264827
    MathEval K("4000/10^2.5-9.7*2.5^(-3)/(6^-4)");
    T = K.Uravnenie(Rez);
    if (T == false) cout << "\n\nDIVISION BY ZERO";
    else    cout << "\n\nRez=" << Rez;
    //пример 3        ответ      DIVISION BY ZERO
    MathEval H("2/(6-6)");
    T = H.Uravnenie(Rez);
    if (T == false) cout << "\n\nDIVISION BY ZERO";
    else    cout << "\n\nRez=" << Rez;  
    
    
    cout << "\n\n";
}
как-то так, коряво и длинно
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
15.01.2018, 12:05
Помогаю со студенческими работами здесь

Вычислить значение арифметического выражения
Всем Здравствуйте! Помогите пожалуйста сделать задание. Разработать программу для вычисления: 1) значения заданного...

Вычислить значение арифметического выражения
Строка символов состоит из десятичных цифр разделенных знаками сложения и вычитания. Вычислить значение арифметического выражения, а...

Вычислить значение арифметического выражения.
Вам дан набор корректных арифметических выражений,в которых используется целые числа, математические операции &quot;+,- и * и круглые...

Вычислить значение арифметического выражения:
Вычислить значение арифметического выражения:

Вычислить значение арифметического выражения
Помогите пожалуйста,на вас вся надежда! Записать и решить данное уравнение в тп,очень надо.


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

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Новые блоги и статьи
Модель заражения группы наркоманов
alhaos 17.04.2026
Условия задачи сформулированы тут Суть: - Группа наркоманов из 10 человек. - Только один инфицирован ВИЧ. - Колются одной иглой. - Колются раз в день. - Колются последовательно через. . .
Мысли в слух. Про "навсегда".
kumehtar 16.04.2026
Подумалось тут, что наверное очень глупо использовать во всяких своих установках понятие "навсегда". Это очень сильное понятие, и я только начинаю понимать край его смысла, не смотря на то что давно. . .
My Business CRM
MaGz GoLd 16.04.2026
Всем привет, недавно возникла потребность создать CRM, для личных нужд. Собственно программа предоставляет из себя базу данных клиентов, в которой можно фиксировать звонки, стадии сделки, а также. . .
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . . а удачный момент так и не приходит.
Фиксация колонок в отчете СКД
Maks 14.04.2026
Фиксация колонок в СКД отчета типа Таблица. Задача: зафиксировать три левых колонки в отчете. Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка) / / . . .
Настройки VS Code
Loafer 13.04.2026
{ "cmake. configureOnOpen": false, "diffEditor. ignoreTrimWhitespace": true, "editor. guides. bracketPairs": "active", "extensions. ignoreRecommendations": true, . . .
Оптимизация кода на разграничение прав доступа к элементам формы
Maks 13.04.2026
Алгоритм из решения ниже реализован на нетиповом документе, разработанного в конфигурации КА2. Задачи, как таковой, поставлено не было, проделанное ниже исключительно моя инициатива. Было так:. . .
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru