First version

This commit is contained in:
2022-04-11 16:34:58 +03:00
committed by GitHub
parent 9d81fc50ca
commit ffaa619ec0
3 changed files with 400 additions and 0 deletions
+308
View File
@@ -0,0 +1,308 @@
#include <iostream>
#include <sstream>
#include <vector>
#include <stack>
#include <math.h>
#include "Wagon.h"
std::vector<Wagon *> toPostfix(std::string s);
std::vector<Wagon *> splitToZug(std::string s);
std::vector<Wagon *> shuffleZug(std::vector<Wagon *> zug);
double calculate(std::vector<Wagon *> zug);
std::string zugToStr(std::vector<Wagon *>zug, char separator);
int getPriority(char operation);
int main(int argc, const char * argv[]) {
std::string s;
if (argc == 1) {
std::cout << "Enter string:" << std::endl;
std::cin >> s;
}
else {
s = argv[1];
}
s += END_OF_ZUG;
std::vector<Wagon *>zug = toPostfix(s);
//std::cout << zugToStr(zug, ' ') << std::endl;
std::cout << calculate(zug) << std::endl;
return 0;
}
std::vector<Wagon *> toPostfix(std::string s)
{
return shuffleZug(splitToZug(s));
}
std::string zugToStr(std::vector<Wagon *>zug, char separator)
{
std::stringstream ss;
for (int i = 0; i < zug.size(); i++) {
if (zug[i]->isNumber())
ss << zug[i]->getNumber() << separator;
else
ss << zug[i]->getOperation() << separator;
}
return ss.str();
}
std::vector<Wagon *> splitToZug(std::string s)
{
std::vector<Wagon *>zug;
double num = -1;
long digitsAfterKomma = 0;
bool isAfterKomma = false;
for (int i = 0; i < s.length(); i++) {
if ((s[i] >= '0')&&(s[i] <= '9')) {
if (num < 0)
num = 0;
num += s[i] - '0';
num *= 10;
if (isAfterKomma) {
digitsAfterKomma++;
}
}
else if ((s[i] == ',')||(s[i] == '.')) {
isAfterKomma = true;
}
else {
if (num >= 0) {
num /= 10;
if (digitsAfterKomma) {
num /= pow(10, digitsAfterKomma);
}
Wagon *w = new Wagon();
w->setNumber(num);
zug.push_back(w);
num = -1;
digitsAfterKomma = 0;
isAfterKomma = false;
}
if (s[i] == ' ') {
continue;
}
Wagon *w = new Wagon();
w->setOperation(s[i]);
if (zug.size()) {
Wagon *lastWagon = zug[zug.size()-1];
if (((lastWagon->isOperation())&&(lastWagon->getOperation() != ')'))) {
if ((s[i] == '+')||(s[i] == '-'))
w->setOperation(-s[i]);
}
}
else {
if ((s[i] == '+')||(s[i] == '-'))
w->setOperation(-s[i]);
}
zug.push_back(w);
}
}
return zug;
}
//3+4*2/(1-5)^2
//3 4 2 * 1 5 - 2 ^ / +
//(8+2*5)/(1+3*2-4)
//8 2 5 * + 1 3 2 * + 4 - /
//1+2*3*4+(5-6)*(7*8+9)
//1 2 3 * 4 * + 5 6 - 7 8 * 9 + * +
std::vector<Wagon *> shuffleZug(std::vector<Wagon *> zug)
{
std::vector<Wagon *>endzug;
std::stack<Wagon *>warte;
for (int i = 0; i < zug.size(); i++) {
if (zug[i]->isNumber()) {
endzug.push_back(zug[i]);
}
else {
switch (zug[i]->getOperation()) {
case '(':
warte.push(zug[i]);
break;
case ')':
while (warte.size()) {
if (warte.top()->getOperation() != '(') {
endzug.push_back(warte.top());
if ((warte.size() == 1)&&(warte.top()->getOperation() != '(')) {
std::cout << "Error! '(' isn't fouded!" << std::endl;
exit(1);
}
warte.pop();
}
else {
warte.pop();
break;
}
}
break;
case '+':
case '-':
case '*':
case '/':
while ((warte.size())&&(getPriority(zug[i]->getOperation()) <= getPriority(warte.top()->getOperation()))) {
endzug.push_back(warte.top());
warte.pop();
}
warte.push(zug[i]);
break;
case '^':
case -'+':
case -'-':
while ((warte.size())&&(getPriority(zug[i]->getOperation()) < getPriority(warte.top()->getOperation()))) {
endzug.push_back(warte.top());
warte.pop();
}
warte.push(zug[i]);
break;
break;
case '|':
while (warte.size()) {
if (warte.top()->getOperation() != '(')
endzug.push_back(warte.top());
warte.pop();
}
break;
case ' ':
break;
default:
std::cout << "Error! Wrong symbol!" << std::endl;
exit(1);
break;
}
}
}
return endzug;
}
double calculate(std::vector<Wagon *> zug)
{
std::stack<Wagon *>stack;
for (int i = 0; i < zug.size(); i++) {
stack.push(zug[i]);
if (stack.top()->isOperation()) {
char operation = stack.top()->getOperation();
bool isUnary = stack.top()->isUnary();
stack.pop();
if (isUnary) {
double number = stack.top()->getNumber();
stack.pop();
switch (operation) {
case -'+':
stack.push(new Wagon(number));
break;
case -'-':
stack.push(new Wagon(-number));
break;
default:
std::cout << "Error! Wrong operation!" << std::endl;
exit(1);
break;
}
}
else {
double numberRight = stack.top()->getNumber();
stack.pop();
double numberLeft = stack.top()->getNumber();
stack.pop();
switch (operation) {
case '+':
stack.push(new Wagon(numberLeft + numberRight));
break;
case '-':
stack.push(new Wagon(numberLeft - numberRight));
break;
case '*':
stack.push(new Wagon(numberLeft * numberRight));
break;
case '/':
stack.push(new Wagon(numberLeft / numberRight));
break;
case '^':
stack.push(new Wagon(pow(numberLeft, numberRight)));
break;
default:
std::cout << "Error! Wrong operation!" << std::endl;
exit(1);
break;
}
}
}
}
if (stack.size() == 1) {
return stack.top()->getNumber();
}
return 0;
}
int getPriority(char operation)
{
switch (operation) {
case '(':
case ')':
return 0;
break;
case '+':
case '-':
return 1;
break;
case '*':
case '/':
return 2;
break;
case '^':
return 3;
break;
case -'+':
case -'-':
return 4;
break;
default:
return 5;
break;
}
}