diff --git a/Wagon.cpp b/Wagon.cpp new file mode 100644 index 0000000..1a3fdcd --- /dev/null +++ b/Wagon.cpp @@ -0,0 +1,61 @@ +#include "Wagon.h" + +Wagon::Wagon() { + this->number = -1; + this->operation = '\0'; +} + +Wagon::Wagon(double number) +{ + this->number = number; + this->operation = '\0'; +} + +Wagon::Wagon(char operation) +{ + this->number = -1; + this->operation = operation; +} + +double Wagon::getNumber() +{ + return this->number; +} + +char Wagon::getOperation() +{ + return this->operation; +} + +void Wagon::setNumber(double number) +{ + if (number < 0) { + return; + } + this->number = number; +} + +void Wagon::setOperation(char operation) +{ + this->operation = operation; +} + +bool Wagon::isNumber() +{ + return !this->isOperation(); +} + +bool Wagon::isOperation() +{ + return this->getOperation(); +} + +bool Wagon::isUnary() +{ + return this->operation < 0; +} + +bool Wagon::isEnd() +{ + return this->operation == END_OF_ZUG; +} \ No newline at end of file diff --git a/Wagon.h b/Wagon.h new file mode 100644 index 0000000..7b49168 --- /dev/null +++ b/Wagon.h @@ -0,0 +1,31 @@ +#ifndef __calc__Wagon__ +#define __calc__Wagon__ + +#include + +#define END_OF_ZUG '|' + +class Wagon +{ +private: + double number; + char operation; + +public: + Wagon(); + Wagon(double number); + Wagon(char operation); + + double getNumber(); + char getOperation(); + + void setNumber(double number); + void setOperation(char operation); + + bool isNumber(); + bool isOperation(); + bool isUnary(); + bool isEnd(); +}; + +#endif diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..e1eaecb --- /dev/null +++ b/main.cpp @@ -0,0 +1,308 @@ +#include +#include +#include +#include +#include +#include "Wagon.h" + +std::vector toPostfix(std::string s); +std::vector splitToZug(std::string s); +std::vector shuffleZug(std::vector zug); +double calculate(std::vector zug); +std::string zugToStr(std::vectorzug, 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::vectorzug = toPostfix(s); + + //std::cout << zugToStr(zug, ' ') << std::endl; + + std::cout << calculate(zug) << std::endl; + + return 0; +} + +std::vector toPostfix(std::string s) +{ + return shuffleZug(splitToZug(s)); +} + +std::string zugToStr(std::vectorzug, 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 splitToZug(std::string s) +{ + std::vectorzug; + + 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 shuffleZug(std::vector zug) +{ + std::vectorendzug; + std::stackwarte; + + 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 zug) +{ + std::stackstack; + 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; + } +} \ No newline at end of file