diff --git a/include/tformula.h b/include/tformula.h index 1d7fa4a..9948437 100644 --- a/include/tformula.h +++ b/include/tformula.h @@ -1,13 +1,17 @@ -const int MaxLen=255; + +const int MaxLen = 255; class TFormula { - private: - char Formula[MaxLen]; // исходная формула - char PostfixForm[MaxLen]; // постфиксная форма - public: - TFormula(char *form); // конструктор - int FormulaChecker(int Brackets[],int size); // проверка корректности скобок - int FormulaConverter(); // преобразование в постфиксную форму - double FormulaCalculator(); // вычисление формулы +private: + char Formula[MaxLen]; // исходная формула + char PostfixForm[MaxLen]; // постфиксная форма +public: + TFormula(char *form); // конструктор + int FormulaChecker(int brackets[], int size); // проверка корректности скобок + int FormulaConverter(); // преобразование в постфиксную форму + double FormulaCalculator(); // вычисление формулы + + bool IsOperator(char str); // проверка оператора + int Priority(char str); // приоритет операции }; \ No newline at end of file diff --git a/include/tstack.h b/include/tstack.h index afb6e55..1f27669 100644 --- a/include/tstack.h +++ b/include/tstack.h @@ -3,14 +3,14 @@ class TStack :public TDataRoot { private: - int top; + int top; public: - TStack(int Size = DefMemSize); - ~TStack() {}; - void Put(const TData &Val); + TStack(int size); + TStack(const TStack &obj); + void Put(const TData &Val); TData Get(); - virtual TData TopElem(); + virtual TData TopElem(); int IsValid(); - void Print(); + void Print(); }; \ No newline at end of file diff --git a/src/tdataroot.cpp b/src/tdataroot.cpp index ad2233a..ddb0715 100644 --- a/src/tdataroot.cpp +++ b/src/tdataroot.cpp @@ -1,52 +1,52 @@ -// ННГУ, ВМК, Курс "Методы программирования-2", С++, ООП +// , , " -2", ++, // -// tdataroot.cpp - Copyright (c) Гергель В.П. 28.07.2000 (06.08) -// Переработано для Microsoft Visual Studio 2008 Сысоевым А.В. (21.04.2015) +// tdataroot.cpp - Copyright (c) .. 28.07.2000 (06.08) +// Microsoft Visual Studio 2008 .. (21.04.2015) // -// Динамические структуры данных - базовый (абстрактный) класс - версия 3.1 -// память выделяется динамически или задается методом SetMem +// - () - 3.1 +// SetMem #include #include "tdataroot.h" -TDataRoot::TDataRoot(int Size): TDataCom() +TDataRoot::TDataRoot(int Size) : TDataCom() { - DataCount = 0; - MemSize = Size; - if (Size == 0) // память будет установлена методом SetMem - { - pMem = NULL; - MemType = MEM_RENTER; - } - else // память выделяется объектом - { - pMem = new TElem[MemSize]; - MemType = MEM_HOLDER; - } + DataCount = 0; + MemSize = Size; + if (Size == 0) // SetMem + { + pMem = NULL; + MemType = MEM_RENTER; + } + else // + { + pMem = new TElem[MemSize]; + MemType = MEM_HOLDER; + } } /*-------------------------------------------------------------------------*/ TDataRoot::~TDataRoot() { - if (MemType == MEM_HOLDER) - delete [] pMem; - pMem = NULL; + if (MemType == MEM_HOLDER) + delete[] pMem; + pMem = NULL; } /*-------------------------------------------------------------------------*/ -void TDataRoot::SetMem(void *p, int Size) // задание памяти +void TDataRoot::SetMem(void *p, int Size) // { - if (MemType == MEM_HOLDER) - delete [] pMem; // ! информация не сохраняется - pMem = (TElem*) p; - MemType = MEM_RENTER; - MemSize = Size; + if (MemType == MEM_HOLDER) + delete[] pMem; // ! + pMem = (TElem*)p; + MemType = MEM_RENTER; + MemSize = Size; } /*-------------------------------------------------------------------------*/ -bool TDataRoot::IsEmpty(void) const // контроль пустоты СД +bool TDataRoot::IsEmpty(void) const // { - return DataCount == 0; + return DataCount == 0; } /*-------------------------------------------------------------------------*/ -bool TDataRoot::IsFull(void) const // контроль переполнения СД +bool TDataRoot::IsFull(void) const // { - return DataCount == MemSize; -} /*-------------------------------------------------------------------------*/ + return DataCount == MemSize; +} /*-------------------------------------------------------------------------*/ \ No newline at end of file diff --git a/src/tformula.cpp b/src/tformula.cpp new file mode 100644 index 0000000..d2efa65 --- /dev/null +++ b/src/tformula.cpp @@ -0,0 +1,206 @@ +#define _CRT_SECURE_NO_WARNINGS +#include "tformula.h" +#include "tstack.h" +#include +#include + +TFormula::TFormula(char *form) +{ + if (form != "") + { + std::strcpy(Formula, form); + std::strcpy(PostfixForm, ""); + + int i = 0; + int bracketCount = 0; + int closeBracket = 0; + int openBracket = 0; + while (Formula[i] != '\0') + { + if (Formula[i] == '(') + { + openBracket++; + bracketCount++; + } + else if (Formula[i] == ')') + { + closeBracket++; + bracketCount++; + } + + i++; + } + + for (int i = 0; i < closeBracket - openBracket; i++) + bracketCount++; + + for (int i = 0; i < openBracket - closeBracket; i++) + bracketCount++; + + int brackets[255]; + if (FormulaChecker(brackets, 255) != 0) + { + for (int i = 0; i < bracketCount; i += 2) + std::cout << brackets[i] + 1 << " | " << brackets[i + 1] + 1 << std::endl; + } + else + { + this->FormulaConverter(); + } + } +} +/*------------------------------------------------------------------------------*/ +int TFormula::FormulaChecker(int brackets[], int size) +{ + TStack mstack(size); + + int bracketsCount = 0; + int i = 0; + int errors = 0; + int bracketIndex = 0; + while (Formula[i] != '\0') + { + if (Formula[i] == '(') + mstack.Put(bracketIndex++); + + else if (Formula[i] == ')') + { + if (mstack.IsEmpty()) + { + brackets[bracketsCount++] = -1; + brackets[bracketsCount++] = bracketIndex++; + errors++; + } + + else + { + brackets[bracketsCount++] = mstack.Get(); + brackets[bracketsCount++] = bracketIndex++; + } + } + + i++; + } + + while (!mstack.IsEmpty()) + { + brackets[bracketsCount++] = mstack.Get(); + brackets[bracketsCount++] = -1; + errors++; + } + + return errors; +} +/*------------------------------------------------------------------------------*/ +bool TFormula::IsOperator(char str) +{ + return (str == '*' || str == '/' + || str == '+' || str == '-'); +} +/*------------------------------------------------------------------------------*/ +int TFormula::Priority(char str) +{ + if (str == '*' || str == '/') return 2; + if (str == '+' || str == '-') return 1; + return 0; +} +/*------------------------------------------------------------------------------*/ +int TFormula::FormulaConverter() +{ + TStack mstack(255); + + int i = 0; + int postFix = 0; + while (Formula[i] != '\0') + { + if (isdigit(Formula[i])) + { + while (isdigit(Formula[i])) + { + PostfixForm[postFix++] = Formula[i]; + i++; + } + PostfixForm[postFix++] = ' '; + i--; + } + + else if (IsOperator(Formula[i])) + { + if (Priority(Formula[i]) > Priority(mstack.TopElem()) || Priority(Formula[i]) == 0 || mstack.IsEmpty()) + mstack.Put(Formula[i]); + + else + { + while (!mstack.IsEmpty() && Priority(mstack.TopElem()) >= Priority(Formula[i]) && mstack.TopElem() != '(') + PostfixForm[postFix++] = mstack.Get(); + + mstack.Put(Formula[i]); + } + } + + if (Formula[i] == '(') + mstack.Put(Formula[i]); + + if (Formula[i] == ')') + { + while (!mstack.IsEmpty()) + { + if (mstack.TopElem() != '(') + PostfixForm[postFix++] = mstack.Get(); + + else + { + mstack.Get(); + break; + } + } + } + + i++; + } + + while (!mstack.IsEmpty()) + PostfixForm[postFix++] = mstack.Get(); + PostfixForm[postFix] = '\0'; + + return 0; +} +/*------------------------------------------------------------------------------*/ +double TFormula::FormulaCalculator() +{ + TStack mstack(255); + + int i = 0; + while (PostfixForm[i] != '\0') + { + if (isdigit(PostfixForm[i])) + mstack.Put(PostfixForm[i] - '0'); + + else if (IsOperator(PostfixForm[i])) + { + int rigthOperator = mstack.Get(); + int leftOperator = mstack.Get(); + + switch (PostfixForm[i]) + { + case'*': + mstack.Put(leftOperator * rigthOperator); + break; + case '/': + mstack.Put(leftOperator / rigthOperator); + break; + case '+': + mstack.Put(leftOperator + rigthOperator); + break; + case '-': + mstack.Put(leftOperator - rigthOperator); + break; + } + } + + i++; + } + + return mstack.Get(); +} +/*------------------------------------------------------------------------------*/ \ No newline at end of file diff --git a/src/tstack.cpp b/src/tstack.cpp new file mode 100644 index 0000000..1962bd4 --- /dev/null +++ b/src/tstack.cpp @@ -0,0 +1,81 @@ +#include "tstack.h" +#include +#include + +TStack::TStack(int size) : top(-1) +{ + if (size == 0) + { + MemSize = DefMemSize; + pMem = new int[MemSize]; + } + else if (size > 0) + { + MemSize = size; + pMem = new int[MemSize]; + } + else + throw "ERR"; +} + +/*-----------------------------------------------*/ +TStack::TStack(const TStack & obj) +{ + MemSize = obj.MemSize; + pMem = new int[MemSize]; + std::copy(pMem, pMem, obj.pMem); + top = obj.top; +} +/*-----------------------------------------------*/ +void TStack::Put(const TData &val) +{ + if (this->IsFull()) + SetRetCode(DataErr); + else + { + pMem[++top] = val; + DataCount++; + } +} +/*-----------------------------------------------*/ +TData TStack::Get() +{ + if (top != -1) + { + DataCount--; + return pMem[top--]; + } + else + { + SetRetCode(DataErr); + return DataEmpty; + } +} +/*-----------------------------------------------*/ +TData TStack::TopElem() +{ + if (top != -1) + return pMem[top]; + else + { + SetRetCode(DataErr); + return DataEmpty; + } +} +/*-----------------------------------------------*/ +int TStack::IsValid() +{ + int res = 0; + + if (pMem == NULL) res = 1; + if (MemSize < DataCount) res += 2; + + return res; +} +/*-----------------------------------------------*/ +void TStack::Print() +{ + for (int i = 0; i < DataCount; i++) + std::cout << pMem[i]; + std::cout << std::endl; +} \ No newline at end of file diff --git a/test/test_tformula.cpp b/test/test_tformula.cpp new file mode 100644 index 0000000..9d48663 --- /dev/null +++ b/test/test_tformula.cpp @@ -0,0 +1,108 @@ +#include "tformula.h" +#include "gtest.h" + +TEST(TFormula, can_check_formula) +{ + TFormula f("(1*2)+((3-4*5)/(6-7))+(8*9)"); + int Br[255]; + ASSERT_NO_THROW(f.FormulaChecker(Br, 255)); +} + +TEST(TFormula, formula_checker_is_correct) +{ + TFormula f("(1*2)+((3-4"); + int Br1[] = {1,2,0,0}; + int Br2[10]; + f.FormulaChecker(Br2, 30); + for (int i = 0; i<4; i++) + ASSERT_EQ(Br1[i], Br2[i]); +} + +TEST(TFormula, can_check_formula_without_brackets) +{ + TFormula f("1 + 2"); + int Br[10]; + ASSERT_NO_THROW(f.FormulaChecker(Br, 30);); + +} + +TEST(TFormula, can_convert_empty_formul) +{ + TFormula f(""); + ASSERT_NO_THROW(f.FormulaConverter()); +} + +TEST(TFormula, cant_convert_formul_with_wrong_symbols) +{ + TFormula f("dgsdsh"); + ASSERT_ANY_THROW(f.FormulaConverter()); +} + + +TEST(TFormula, can_calculate_sum) +{ + TFormula f("2+1"); + ASSERT_DOUBLE_EQ(3, f.FormulaCalculator()); +} + + +TEST(TFormula, can_calculate_difference) +{ + TFormula f("10-3"); + ASSERT_DOUBLE_EQ(7, f.FormulaCalculator()); +} + +TEST(TFormula, can_calculate_multipling) +{ + TFormula f("3*2"); + ASSERT_DOUBLE_EQ(6, f.FormulaCalculator()); +} + +TEST(TFormula, can_calculate_divide) +{ + TFormula f("50/5"); + ASSERT_DOUBLE_EQ(10, f.FormulaCalculator()); +} + +TEST(TFormula, can_calculate_sum_with_brackets) +{ + TFormula f("(1+2)+(3+4)"); + ASSERT_DOUBLE_EQ(10, f.FormulaCalculator()); +} + +TEST(TFormula, can_calculate_diff_with_brackets) +{ + TFormula f("(5-4)-(3-2)"); + ASSERT_DOUBLE_EQ(0, f.FormulaCalculator()); +} + +TEST(TFormula, can_calculate_multiplying_with_brackets) +{ + TFormula f("(2*3)*(1*5)"); + ASSERT_DOUBLE_EQ(30, f.FormulaCalculator()); +} + +TEST(TFormula, can_divide_with_brackets) +{ + TFormula f("(10/2)/(25/5)"); + EXPECT_DOUBLE_EQ(1, f.FormulaCalculator()); +} + +TEST(TFormula, can_calculate_multiple_operators) +{ + TFormula f("10+5*3-5/5"); + EXPECT_DOUBLE_EQ(24, f.FormulaCalculator()); +} + +TEST(TFormula, can_calculate_multiple_different_with_brackets) +{ + TFormula f("(10+5)*3-5/5"); + EXPECT_DOUBLE_EQ(44, f.FormulaCalculator()); +} + + +TEST(TFormula, cant_calculate_formula_with_wrong_symbols) +{ + TFormula f("fghdfigh"); + ASSERT_ANY_THROW(f.FormulaCalculator()); +} \ No newline at end of file diff --git a/test/test_tstack.cpp b/test/test_tstack.cpp new file mode 100644 index 0000000..6e2109f --- /dev/null +++ b/test/test_tstack.cpp @@ -0,0 +1,68 @@ +#include +#include "tstack.h" + + +TEST(TStack, can_create_stack_with_positive_length) +{ + ASSERT_NO_THROW(TStack mstack(5)); +} + +TEST(TStack, cant_create_stack_with_negative_lenght) +{ + ASSERT_ANY_THROW(TStack mstack(-10)); +} + +TEST(TStack, can_put_element_into_stack) +{ + TStack mstack(5); + + mstack.Put(13); + + EXPECT_EQ(mstack.GetRetCode(), 0); +} + +TEST(TStack, cant_put_element_into_full_stack) +{ + TStack mstack(1); + + mstack.Put(130); + mstack.Put(13); + + EXPECT_EQ(mstack.GetRetCode(), -1); +} + +TEST(TStack, can_get_top_element_with_deleting) +{ + TStack mstack(5); + + mstack.Put(13); + + EXPECT_EQ(mstack.Get(), 13); +} + +TEST(TStack, cant_get_top_element_if_stack_is_empty) +{ + TStack mstack(1); + + mstack.Get(); + + EXPECT_EQ(mstack.GetRetCode(), -1); +} + +TEST(TStack, can_get_top_element_without_deleting) +{ + TStack mstack(5); + + mstack.Put(14); + + EXPECT_EQ(14, mstack.TopElem()); +} + +TEST(TStack, cant_get_top_element_if_it_is_empty_without_deleting) +{ + TStack mstack(4); + + mstack.TopElem(); + + EXPECT_EQ(mstack.GetRetCode(), -1); +} \ No newline at end of file