Загрузка данных
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
struct tstk {
double inf;
tstk *a;
};
tstk *AddStack(tstk *sp, double inf) {
tstk *spt = new tstk;
spt->inf = inf;
spt->a = sp;
return spt;
}
tstk *ReadStack(tstk *sp, double &inf) {
tstk *spt = sp;
inf = sp->inf;
sp = sp->a;
delete spt;
return sp;
}
// Стек для строк (для оптимизации RPN)
struct tstkStr {
char inf[100];
tstkStr *a;
};
tstkStr *AddStackStr(tstkStr *sp, char *inf) {
tstkStr *spt = new tstkStr;
strcpy(spt->inf, inf);
spt->a = sp;
return spt;
}
tstkStr *ReadStackStr(tstkStr *sp, char *inf) {
tstkStr *spt = sp;
strcpy(inf, sp->inf);
sp = sp->a;
delete spt;
return sp;
}
// Проверка, является ли строка числом
int isNumber(char *str) {
int i = 0;
if (str[0] == '-') i++;
int dotCount = 0;
for (; str[i]; i++) {
if (str[i] == '.') {
dotCount++;
if (dotCount > 1) return 0;
continue;
}
if (str[i] < '0' || str[i] > '9') return 0;
}
return 1;
}
// Проверка, является ли символ оператором
int isOperator(char ch) {
return (ch == '+' || ch == '-' || ch == '*' || ch == '/');
}
// Выполнение операции
double applyOp(double a, double b, char op) {
switch (op) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return a / b;
default: return 0;
}
}
// Оптимизация RPN: вычисление константных подвыражений
void OptimizeRPN(char *strin, char *strout) {
tstkStr *sp = NULL;
char token[100];
char a[100], b[100], res[100];
int n = 0;
// Разбиваем входную строку на токены (разделитель - пробел)
char *ptr = strtok(strin, " ");
while (ptr != NULL) {
// Если это не оператор (число или переменная)
if (strlen(ptr) == 1 && isOperator(ptr[0]) && ptr[0] != '-') {
// Это оператор
if (sp != NULL && sp->a != NULL) {
// Извлекаем два верхних элемента
sp = ReadStackStr(sp, b);
sp = ReadStackStr(sp, a);
// Проверяем, являются ли оба числами
if (isNumber(a) && isNumber(b)) {
double va = atof(a);
double vb = atof(b);
double r = applyOp(va, vb, ptr[0]);
// Формируем строку результата
if (r == (int)r)
sprintf(res, "%d", (int)r);
else
sprintf(res, "%g", r);
sp = AddStackStr(sp, res);
} else {
// Нельзя вычислить - возвращаем обратно в обратном порядке
sp = AddStackStr(sp, a);
sp = AddStackStr(sp, b);
sp = AddStackStr(sp, ptr);
}
} else {
sp = AddStackStr(sp, ptr);
}
} else {
// Число или переменная
sp = AddStackStr(sp, ptr);
}
ptr = strtok(NULL, " ");
}
// Собираем результат из стека
char temp[100][100];
int cnt = 0;
while (sp != NULL) {
sp = ReadStackStr(sp, temp[cnt++]);
}
// Формируем выходную строку (в обратном порядке)
strout[0] = '\0';
for (int i = cnt - 1; i >= 0; i--) {
strcat(strout, temp[i]);
if (i > 0) strcat(strout, " ");
}
}
int main() {
char rpn[200], optimized[200];
cout << "=== Оптимизация выражений в обратной польской записи ===" << endl;
cout << "Программа находит константные подвыражения и вычисляет их заранее." << endl;
cout << endl;
// Пример 1
cout << "Пример 1:" << endl;
strcpy(rpn, "2 3 + x *");
cout << "Исходное RPN: " << rpn << endl;
OptimizeRPN(rpn, optimized);
cout << "Оптимизированное: " << optimized << endl;
cout << "Пояснение: 2+3=5, результат '5 x *'" << endl;
cout << endl;
// Пример 2
cout << "Пример 2:" << endl;
strcpy(rpn, "3 4 + 5 2 - *");
cout << "Исходное RPN: " << rpn << endl;
OptimizeRPN(rpn, optimized);
cout << "Оптимизированное: " << optimized << endl;
cout << "Пояснение: 3+4=7, 5-2=3, 7*3=21, результат '21'" << endl;
cout << endl;
// Пример 3
cout << "Пример 3:" << endl;
strcpy(rpn, "10 2 / 3 * 4 +");
cout << "Исходное RPN: " << rpn << endl;
OptimizeRPN(rpn, optimized);
cout << "Оптимизированное: " << optimized << endl;
cout << "Пояснение: 10/2=5, 5*3=15, 15+4=19, результат '19'" << endl;
cout << endl;
// Пример 4
cout << "Пример 4:" << endl;
strcpy(rpn, "a 2 * 4 2 / +");
cout << "Исходное RPN: " << rpn << endl;
OptimizeRPN(rpn, optimized);
cout << "Оптимизированное: " << optimized << endl;
cout << "Пояснение: 4/2=2, результат 'a 2 * 2 +'" << endl;
cout << endl;
// Пример 5
cout << "Пример 5:" << endl;
strcpy(rpn, "x y + 5 3 - * z /");
cout << "Исходное RPN: " << rpn << endl;
OptimizeRPN(rpn, optimized);
cout << "Оптимизированное: " << optimized << endl;
cout << "Пояснение: 5-3=2, результат 'x y + 2 * z /'" << endl;
cout << endl;
// Ввод от пользователя
cout << "=== Ввод пользователя ===" << endl;
cout << "Введите RPN выражение (токены разделены пробелами): ";
cin.getline(rpn, 200);
// Сохраняем оригинал для вывода
char original[200];
strcpy(original, rpn);
OptimizeRPN(rpn, optimized);
cout << "Исходное: " << original << endl;
cout << "Оптимизированное: " << optimized << endl;
return 0;
}