Untitled
unknown
c_cpp
2 years ago
14 kB
5
Indexable
#include <iostream>
#include <sstream>
#include <cmath>
#include <stack>
#include <Windows.h>
#include <iomanip>
#include<fstream>
using namespace std;
const double Pi = acos(-1); //Объявляем значение числа Пи
double Sin(double x) { //Функция для округления значение синуса
return (round(sin(x) * 10000000) / 10000000);
}
double Cos(double x) { //Функция для округления значение косинуса
return (round(cos(x) * 10000000) / 10000000);
}
double Ctg(double x) { //Функция для расчета котангенса
double a = cos(x);
double b = Sin(x);
return (a / b);
}
double Log(double x) {
return (round(log(x) * 10000000) / 10000000);
}
struct calculate //Структура, описывающая любое число или операцию
{
char type; // 0 для чисел, "+" для операции сложения и т.д.
double value; //Значение (только для чисел). У операций значение всегда "0"
};
bool Maths(stack <calculate>& Stack_n, stack <calculate>& Stack_o, calculate& item) { //Математическая функция, которая производит расчеты
//Функция имеет тип bool, чтобы при возникновении какой-либо ошибки возвращать "false"
double a, b, c;
a = Stack_n.top().value; //Берется верхнее число из стека с числами
Stack_n.pop(); //Удаляется верхнее число из стека с числами
switch (Stack_o.top().type) { //Проверяется тип верхней операции из стека с операциями
case '+': //Если тип верхней операции из стека с операциями сложение
b = Stack_n.top().value;
Stack_n.pop();
c = a + b;
item.type = '0';
item.value = c;
Stack_n.push(item); //Результат операции кладется обратно в стек с числами
Stack_o.pop();
break;
case '-':
b = Stack_n.top().value;
Stack_n.pop();
c = b - a;
item.type = '0';
item.value = c;
Stack_n.push(item);
Stack_o.pop();
break;
case '^':
b = Stack_n.top().value;
Stack_n.pop();
c = pow(b, a);
item.type = '0';
item.value = c;
Stack_n.push(item);
Stack_o.pop();
break;
case '*':
b = Stack_n.top().value;
Stack_n.pop();
c = a * b;
item.type = '0';
item.value = c;
Stack_n.push(item);
Stack_o.pop();
break;
case '/':
b = Stack_n.top().value;
if (a == 0) {
cerr << "\nYou can't divide by 0\n";
return false;
}
else {
Stack_n.pop();
c = (b / a);
item.type = '0';
item.value = c;
Stack_n.push(item);
Stack_o.pop();
break;
}
case 's':
c = Sin(a);
item.type = '0';
item.value = c;
Stack_n.push(item);
Stack_o.pop();
break;
case 'c':
c = Cos(a);
item.type = '0';
item.value = c;
Stack_n.push(item);
Stack_o.pop();
break;
case 't':
if (Cos(a) == 0) {
cerr << "\nInvalid argument for tangent\n";
return false;
}
else {
c = tan(a);
item.type = '0';
item.value = c;
Stack_n.push(item);
Stack_o.pop();
break;
}
case 'g':
if (Sin(a) == 0) {
cerr << "\nInvalid argument for cotangent\n";
return false;
}
else {
c = Ctg(a);
item.type = '0';
item.value = c;
Stack_n.push(item);
Stack_o.pop();
break;
}
case 'e':
c = exp(a);
item.type = '0';
item.value = c;
Stack_n.push(item);
Stack_o.pop();
break;
case 'l':
if (a <= 0) {
cerr << "\nInvalid argument for logarithm\n";
return false;
}
else {
c = Log(a);
item.type = '0';
item.value = c;
Stack_n.push(item);
Stack_o.pop();
break;
}
default:
cerr << "\nError\n";
return false;
break;
}
return true;
}
int getRang(char Ch) {
if (Ch == 's' || Ch == 'c' || Ch == 't' || Ch == 'g' || Ch == 'e' || Ch == 'l') return 4;
if (Ch == '^') return 3;
if (Ch == '+' || Ch == '-') return 1;
if (Ch == '*' || Ch == '/') return 2;
if (Ch == 'l') return 5; // Операция логарифма имеет более высокий приоритет
else return 0;
}
int main() {
while (true) {
system("cls");
cout << " To use Pi enter 'p', to use e enter 'exp(1)'\n";
cout << " Enter expression: ";
string str;
getline(cin, str);
stringstream sstr{ str };
char Ch; //Переменная, в которую будет записываться текущий обрабатываемый символ
double value;
bool flag = true; //Нужен для того, чтобы программа смогла отличить унарный минус (-5) от вычитания (2-5)
stack<calculate> Stack_n; //Стек с числами
stack<calculate> Stack_o; //Стек с операциями
calculate item; //Объект типа calculate
while (true) {
Ch = sstr.peek(); //Смотрим на первый символ
if (Ch == '\377')break; //Если достигнут конец строки, выходим из цикла
if (Ch == ' ') { //Игнорирование пробелов
sstr.ignore();
continue;
}
if (Ch == 's' || Ch == 'c' || Ch == 't' || Ch == 'e') { //Если прочитана функция
char foo[3]; //массив на 3 символа для определения типа прочитанной функции
for (int i = 0; i < 3; i++) {
Ch = sstr.peek();
foo[i] = Ch;
sstr.ignore();
}
if (foo[0] == 's' && foo[1] == 'i' && foo[2] == 'n') { //Если прочитанная функция - синус
item.type = 's';
item.value = 0;
Stack_o.push(item); //Операция кладется в стек с операциями
continue;
}
if (foo[0] == 'c' && foo[1] == 'o' && foo[2] == 's') { //Если прочитанная функция - косинус
item.type = 'c';
item.value = 0;
Stack_o.push(item); //Операция кладется в стек с операциями
continue;
}
if (foo[0] == 't' && foo[1] == 'a' && foo[2] == 'n') { //Если прочитанная функция - тангенс
item.type = 't';
item.value = 0;
Stack_o.push(item); //Операция кладется в стек с операциями
continue;
}
if (foo[0] == 'c' && foo[1] == 't' && foo[2] == 'g') { //Если прочитанная функция - котангенс
item.type = 'g';
item.value = 0;
Stack_o.push(item); //Операция кладется в стек с операциями
continue;
}
if (foo[0] == 'e' && foo[1] == 'x' && foo[2] == 'p') { //Если прочитанная функция - экспонента
item.type = 'e';
item.value = 0;
Stack_o.push(item); //Операция кладется в стек с операциями
continue;
}
if (foo[0] == 'l' && foo[1] == 'o' && foo[2] == 'g') { // Если прочитанная функция - логарифм
item.type = 'l';
item.value = 0;
Stack_o.push(item); // Операция кладется в стек с операциями
continue;
}
}
if (Ch == 'p') { //Если прочитано число Пи
item.type = '0';
item.value = Pi;
Stack_n.push(item); //Число кладется в стек с числами
flag = 0;
sstr.ignore();
continue;
}
if (Ch >= '0' && Ch <= '9' || Ch == '-' && flag == 1) { //Если прочитано число
sstr >> value;
Ch = sstr.peek();
if (Ch == '(') {
item.type = '*';
item.value = 0;
Stack_o.push(item);
}
item.type = '0';
item.value = value;
Stack_n.push(item); //Число кладется в стек с числами
flag = 0;
continue;
}
if (Ch == '+' || Ch == '-' && flag == 0 || Ch == '*' || Ch == '/' || Ch == '^') { //Если прочитана операция
if (Stack_o.size() == 0) { //Если стек с операциями пуст
item.type = Ch;
item.value = 0;
Stack_o.push(item); //Операция кладется в стек с операциями
sstr.ignore();
continue;
}
if (Stack_o.size() != 0 && getRang(Ch) >
getRang(Stack_o.top().type)) { //Если стек с операциями НЕ пуст, но приоритет текущей операции выше верхней в стеке с операциями
item.type = Ch;
item.value = 0;
Stack_o.push(item); //Операция кладется в стек с операциями
sstr.ignore();
continue;
}
if (Stack_o.size() != 0 && getRang(Ch) <=
getRang(Stack_o.top().type)) {//Если стек с операциями НЕ пуст, но приоритет текущей операции ниже либо равен верхней в стеке с операциями
if (Maths(Stack_n, Stack_o, item) == false) { //Если функция вернет "false", то прекращаем работу
system("pause");
return 0;
}
continue;
}
}
if (Ch == '(') { //Если прочитана открывающаяся скобка
item.type = Ch;
item.value = 0;
Stack_o.push(item); //Операция кладется в стек с операциями
sstr.ignore();
continue;
}
if (Ch == ')') { //Если прочитана закрывающаяся скобка
while (Stack_o.top().type != '(') {
if (Maths(Stack_n, Stack_o, item) == false) { //Если функция вернет "false", то прекращаем работу
system("pause");
return 0;
}
else continue; //Если все хорошо
}
Stack_o.pop();
sstr.ignore();
continue;
}
else { //Если прочитан какой-то странный символ
cout << "\nInvalid expression entered\n";
Sleep(1500);
return main();
}
}
while (Stack_o.size() !=
0) { //Вызываем матем. функцию до тех пор, пока в стеке с операциями не будет 0 элементов
if (Maths(Stack_n, Stack_o, item) == false) { //Если функция вернет "false", то прекращаем работу
system("pause");
return 0;
}
else continue; //Если все хорошо
}
cout << setprecision(15) << "\nAnswer: " << Stack_n.top().value << endl; //Выводим ответ
string expression = str;
ofstream outputFile("expressions.txt", ios::app);
if (outputFile.is_open()) { // Запись выражения в файл
outputFile << expression << " = " << Stack_n.top().value << endl; // Закрытие файла
outputFile.close();
}
else {
cerr << "Unable to open the file for writing." << endl;
}
system("pause");
}
return 0;
}Editor is loading...