diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..378eac2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..7d0835f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,18 @@ +language: cpp +only: + - calculator + +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-4.9 + - g++-4.9 + +script: + - mkdir build && cd build && g++ -std=c++0x -o Calculator ../CalculatorSources/Source.cpp ../CalculatorSources/Calculator.cpp + +notifications: + email: + - valera.malkof@gmail.com \ No newline at end of file diff --git a/CalculatorSources/Calculator.cpp b/CalculatorSources/Calculator.cpp new file mode 100755 index 0000000..a97cddf --- /dev/null +++ b/CalculatorSources/Calculator.cpp @@ -0,0 +1,217 @@ +#include"Calculator.h" +double Calculator::calculate(const char* s) +{ + char strochka[255]; + Stack operations; + int i = 0; + while (*s) + { + while (!isCorrect(*s))s++; + if (isdigit(*s)) + { + while (*s == '.' || isdigit(*s)) + { + strochka[i] = *s; + i++; + s++; + } + strochka[i] = ' '; + i++; + if (!operations.isEmpty()) + { + if (*s != '^'&&*s != '*'&&*s != '/') + { + if (operations.popReturn() == '-') + { + strochka[i] = operations.pop(); + i++; + } + } + + } + } + else if (*s == ')') + { + + while (operations.popReturn() != '(') + { + strochka[i] = operations.pop(); + i++; + } + s++; + if (*s == '^') + { + operations.push(*s); + s++; + if (isdigit(*s)) + { + while (*s == '.' || isdigit(*s)) + { + strochka[i] = *s; + i++; + s++; + } + } + strochka[i] = operations.pop(); + i++; + } + if (*s == '/') + { + operations.push(*s); + s++; + if (isdigit(*s)) + { + while (*s == '.' || isdigit(*s)) + { + strochka[i] = *s; + i++; + s++; + } + } + strochka[i] = operations.pop(); + i++; + } + if (*s == '*') + { + operations.push(*s); + s++; + if (isdigit(*s)) + { + while (*s == '.' || isdigit(*s)) + { + strochka[i] = *s; + i++; + s++; + } + } + strochka[i] = operations.pop(); + i++; + } + operations.pop(); + if (!operations.isEmpty()) + { + if (operations.popReturn() == '*' || operations.popReturn() == '/' || operations.popReturn() == '-') + { + strochka[i] = operations.pop(); + i++; + } + } + + strochka[i] = ' '; + i++; + } + else if (*s == '(') + { + operations.push(*s); + s++; + } + else if (*s == '*' || *s == '/' || *s == '^') + { + operations.push(*s); + s++; + } + else if (*s == '+' || *s == '-') + { + char op; + if (!operations.isEmpty()) + { + if (operations.popReturn() == '*' || operations.popReturn() == '/' || operations.popReturn() == '^') + { + while (!operations.isEmpty()) + { + if (operations.popReturn() == '*' || operations.popReturn() == '/' || operations.popReturn() == '^') + { + strochka[i] = operations.pop(); + i++; + } + else break; + } + operations.push(*s); + s++; + } + else + { + operations.push(*s); + s++; + } + } + else + { + operations.push(*s); + s++; + } + } + } + while (!operations.isEmpty()) + { + + strochka[i] = operations.pop(); + i++; + } + if (strochka[i - 1] == ' ') + strochka[i - 1] = '\0'; + else strochka[i] = '\0'; + cout << endl; + return postFix(strochka); +} +double Calculator::postFix(const char* s) +{ + double a = 0; + double b = 0; + Stack numbers; + while (*s) + { + while (!isCorrect(*s))s++; + if (isdigit(*s)) + { + double d = atof(s); + numbers.push(d); + while (*s == '.' || isdigit(*s))s++; + } + else if (*s == '+') + { + b = numbers.pop(); + a = numbers.pop(); + numbers.push(a + b); + s++; + + } + else if (*s == '-') + { + b = numbers.pop(); + a = numbers.pop(); + numbers.push(a - b); + s++; + } + else if (*s == '*') + { + b = numbers.pop(); + a = numbers.pop(); + numbers.push(a * b); + s++; + } + else if (*s == '/') + { + b = numbers.pop(); + a = numbers.pop(); + numbers.push(a / b); + s++; + } + else if (*s == '^') + { + b = numbers.pop(); + a = numbers.pop(); + numbers.push(pow(a, b)); + s++; + } + } + + return numbers.pop(); +} +bool Calculator::isCorrect(const char s) +{ + return isdigit(s) || s == '.' || + s == '+' || s == '-' || s == '*' || + s == '/' || s == '^' || s == '(' || + s == ')'; +} \ No newline at end of file diff --git a/CalculatorSources/Calculator.h b/CalculatorSources/Calculator.h new file mode 100755 index 0000000..ce0fb67 --- /dev/null +++ b/CalculatorSources/Calculator.h @@ -0,0 +1,16 @@ +#ifndef CALCULATOR_H +#define CALCULATOR_H +#include"Stack.h" +#include +#include +using namespace std; +class Calculator +{ +public: + static double calculate(const char* s); +private: + static double postFix(const char* s); + static bool isCorrect(const char s); +}; + +#endif; diff --git a/CalculatorSources/Double_list.h b/CalculatorSources/Double_list.h new file mode 100755 index 0000000..dd04b88 --- /dev/null +++ b/CalculatorSources/Double_list.h @@ -0,0 +1,300 @@ +#ifndef DOUBLE_LIST +#define DOUBLE_LIST +#include +#include"Node.h" +#include"Iterator.h" +using namespace std; + +template +class CDoubleList +{ +public: + CDoubleList(); + CDoubleList(const CDoubleList & object); + CDoubleList(CDoubleList && obj); + CDoubleList& operator=(const CDoubleList& object); + CDoubleList & operator=(CDoubleList && obj); + T & operator[](size_t index); + ~CDoubleList(); +public: + unsigned int getSize(); + void addToStart(const T & v); + void addToEnd(const T & v); + void addToIndex(size_t index, const T & v); + void removeFromIndex(size_t index); + void removeAll(); + void removeFromStart(); + void removeFromEnd(); + CIterator getBegin() { return CIterator(start); } + CIterator getEnd() { return CIterator(nullptr); } +private: + + List::Node* start; + List::Node* end; + unsigned int count; +private: + List::Node* getNode(unsigned int index) + { + if (index >= count) + exit(1); + List::Node * node; + if (index < count / 2) + { + node = start; + for (size_t i = 0; i < index; i++) + { + node = node->next; + } + } + else + { + node = end; + for (size_t i = count - 1; i > index; i--) + { + node = node->previous; + } + } + return node; + } +}; + +template +CDoubleList::CDoubleList() +{ + //cout << "Default constr"< +CDoubleList::CDoubleList(CDoubleList&& obj) +{ + //cout << "Move constr"<start = obj.start; + this->end = obj.end; + this->count = obj.count; + obj.start = nullptr; +} +template +CDoubleList::CDoubleList(const CDoubleList& object):CDoubleList() +{ + //cout << "Copy constr" << endl; + List::Node * node = object.start; + while (node) + { + this->addToEnd(node->value); + node = node->next; + } +} + +template +T& CDoubleList::operator[](size_t index) +{ + return getNode(index)->value; +} + +template +CDoubleList& CDoubleList::operator=(const CDoubleList& object) +{ + //cout << "operator= copy" << endl; + if (this == &object) + return *this; + this->removeAll(); + List::Node * node = object.start; + while (node) + { + this->addToEnd(node->value); + node = node->next; + } + return *this; +} + +template +CDoubleList & CDoubleList::operator=(CDoubleList && obj) +{ + //cout << "operator= move" << endl; + if (this == &obj) + return *this; + this->removeAll(); + + this->start = obj.start; + this->end = obj.end; + this->count = obj.count; + obj.start = nullptr; + + return *this; +} + +template +CDoubleList::~CDoubleList() +{ + //cout << "Destroy" << endl; + this->removeAll(); +} + + + +template +unsigned int CDoubleList::getSize() +{ + return count; +} + +template +void CDoubleList::addToEnd(const T & v) +{ + List::Node* node =new List::Node(v); + if (count == 0) + start = node; + else + end->next = node; + node->previous = end; + end = node; + count++; +} +template +void CDoubleList::addToStart(const T & v) +{ + if (count == 0) + { + this->addToEnd(v); + return; + } + List::Node * node = new List::Node(v); + node->next = start; + start->previous = node; + start = node; + count++; +} + + +template +void CDoubleList::addToIndex(size_t index, const T & v)//����� ���������� �� ������� +{ + if (count == 0 || index == 0) + { + this->addToStart(v); + return; + } + if (index == count || index>count) + { + this->addToEnd(v); + return; + } + List::Node * node = start; + count = NULL; + start = end = nullptr; + + for (size_t i = 0;i <= index;i++) + { + if (i < index) + { + addToEnd(node->value); + node = node->next; + } + if (i == index) + { + addToEnd(v); + while (node) + { + addToEnd(node->value); + node = node->next; + } + return; + } + } +} + +template +void CDoubleList::removeFromIndex(size_t index) +{ + if (index == 0) + { + removeFromStart(); + return; + } + if (index == count || index > count) + { + removeFromEnd(); + return; + } + List::Node * node = start; + count = NULL; + start = end = nullptr; + for (size_t i = 0;i <= index;i++) + { + if (i < index) + { + addToEnd(node->value); + node = node->next; + } + if (i == index) + { + node = node->next; + while (node) + { + addToEnd(node->value); + node = node->next; + } + return; + } + } +} + +template +void CDoubleList::removeFromEnd() +{ + if (count == 0) + return; + else if (count == 1) + { + delete start; + start = end = nullptr; + count = 0; + } + else + { + List::Node * beforeEnd = end->previous; + beforeEnd->next = nullptr; + delete end; + end = beforeEnd; + count--; + } +} + +template +void CDoubleList::removeFromStart() +{ + if (count == 0) + return; + else if (count == 1) + { + delete start; + start = end = nullptr; + count = 0; + } + else + { + List::Node * p = start->next; + delete start; + start = p; + start->previous = nullptr; + count--; + } +} + +template +void CDoubleList::removeAll() +{ + List::Node * node = start; + while (node) + { + List::Node * p = node; + node = node->next; + delete p; + } + start = end = nullptr; + count = 0; +} +#endif + diff --git a/CalculatorSources/Iterator.h b/CalculatorSources/Iterator.h new file mode 100755 index 0000000..c9f4d17 --- /dev/null +++ b/CalculatorSources/Iterator.h @@ -0,0 +1,62 @@ +#ifndef ITERATOR_H +#define ITERATOR_H +#include"Node.h" +template +class CIterator +{ +public: + CIterator(List::Node* current); +public: + T & operator*(); + CIterator & operator++(); + CIterator & operator--(); + bool operator!=(CIterator & obj); + bool hasNext(); + bool hasPrevious(); +private: + List::Node * current; +}; +template +T &CIterator::operator*() +{ + return current->value; +} + +template +CIterator::CIterator(List::Node* current) +{ + this->current = current; +} + +template +CIterator& CIterator:: operator++() +{ + current = current->next; + return *this; +} + +template +CIterator &CIterator:: operator--() +{ + current = current->prev; + return *this; +} + +template +bool CIterator:: operator!=(CIterator & obj) +{ + return current != obj.current; +} + +template +bool CIterator::hasNext() +{ + return (current->next() != nullptr ? true : false); +} + +template +bool CIterator::hasPrevious() +{ + return (current->previous() != nullptr ? true : false); +} +#endif; diff --git a/CalculatorSources/Node.h b/CalculatorSources/Node.h new file mode 100755 index 0000000..6c194ba --- /dev/null +++ b/CalculatorSources/Node.h @@ -0,0 +1,16 @@ +#ifndef NODE_H +#define NODE_H + +namespace List +{ + template + struct Node + { + T value; + Node* next; + Node* previous; + Node(const T& val) :value(val), next(nullptr), previous(nullptr) {} + }; +} + +#endif; diff --git a/CalculatorSources/Source.cpp b/CalculatorSources/Source.cpp new file mode 100755 index 0000000..8ac68de --- /dev/null +++ b/CalculatorSources/Source.cpp @@ -0,0 +1,28 @@ +#include"Calculator.h" +int main() +{ + char stroka1[255] = "((3.36+2.549)/5.03+(3+4*(5-2)-1)/2)^0.5"; + char stroka2[255] = "3.5+2*5"; + char stroka9[255] = "(3+2)*5"; + char stroka3[255] = "(3+4*(5-2)-1)/2"; + char stroka4[255] = "(3+2)/5 + (3+4*(5-2)-1)/2"; + char stroka5[255] = "16.8/((3+2)/5 +(3+4*(5-2)-1)/2)"; + char stroka6[255] = "(64/32)+78-(20/4)+(2*(11-6))+45+2/2"; + char stroka7[255] = "(3+5)^2-60-2^3"; + char stroka8[255] = "((3+2)/5 + (3+4*(5-2)-1)/2)^0.5"; + char stroka10[255]="3*((1+3)*2-((2-1)*(4+2)-2)/2)/4"; + + cout << stroka10 << "=" << Calculator::calculate(stroka10) << endl; + cout << stroka1 << "=" << Calculator::calculate(stroka1) << endl; + cout << stroka2 << "=" << Calculator::calculate(stroka2) << endl; + cout << stroka9 << "=" << Calculator::calculate(stroka9) << endl; + cout << stroka3 << "=" << Calculator::calculate(stroka3) << endl; + cout << stroka4 << "=" << Calculator::calculate(stroka4) << endl; + cout << stroka5 << "=" << Calculator::calculate(stroka5) << endl; + cout << stroka6 << "=" << Calculator::calculate(stroka6) << endl; + cout << stroka7 << "=" << Calculator::calculate(stroka7) << endl; + cout << stroka8 << "=" << Calculator::calculate(stroka8); + cout << endl; + getchar(); + getchar(); +} diff --git a/CalculatorSources/Stack.h b/CalculatorSources/Stack.h new file mode 100755 index 0000000..1572562 --- /dev/null +++ b/CalculatorSources/Stack.h @@ -0,0 +1,47 @@ +#ifndef STACK_H +#define STACK_H +#include"Double_list.h" + +template +class Stack +{ +public: + void push(const T & value); + T pop(); + T popReturn(); + bool isEmpty(); + T getSize(); +private: + CDoubleList list; +}; + +template +void Stack::push(const T& value) +{ + list.addToEnd(value); +} + +template +T Stack::pop() +{ + T buffer = list[list.getSize()-1]; + list.removeFromEnd(); + return buffer; +} +template +T Stack::popReturn() +{ + return list[list.getSize() - 1]; +} +template +bool Stack::isEmpty() +{ + if (list.getSize() == 0)return true; + return false; +} +template +T Stack::getSize() +{ + return list.getSize(); +} +#endif; diff --git a/README.md b/README.md index f811e88..bbca37f 100644 --- a/README.md +++ b/README.md @@ -1 +1,9 @@ -### This repo for studying only \ No newline at end of file +### This repo for studying only + +# How to build project on like UNIX system + + 1. Create `build` directory `mkdir build` + 2. Checkout to `build` directory `cd build` + 3. Run `g++` compiler. Use the next command: + `g++ -std=c++0x -o Calculator ../CalculatorSources/Source.cpp ../CalculatorSources/Calculator.cpp` + 4. If building was succesfull run executable file `Calculator` like `./Calculator`