From 08f63320cad802b8b4538981bcb9fd6885f49be0 Mon Sep 17 00:00:00 2001 From: SandalovKY Date: Fri, 20 Dec 2019 21:29:07 +0300 Subject: [PATCH 1/3] Vol1.1 --- include/TFormula.h | 42 +++++----- include/TStack.h | 66 +++++++-------- samples/TMain.cpp | 6 +- src/TFormula.cpp | 194 ++++++++++++++++++++++++++++----------------- 4 files changed, 182 insertions(+), 126 deletions(-) diff --git a/include/TFormula.h b/include/TFormula.h index 31303d2..f03a19c 100644 --- a/include/TFormula.h +++ b/include/TFormula.h @@ -1,29 +1,35 @@ #ifndef TFORMULA_H #define TFORMULA_H #include "TStack.h" -const int MaxLength = 255; -const int OPER = 6; +#include +const int MaxLength = 255; // максимальная длина исходной формулы +const int OPER = 6; // число допустимых операций в выражении class TFormula { private: - int infSize; - int postSize; - char Infix[MaxLength]; - char Postfix[MaxLength]; + int infSize; // размер инфиксной записи формулы + int postSize; // размер постфиксной записи формулы + char Infix[MaxLength]; // собственно сама инфиксная + char Postfix[MaxLength]; // и постфиксная записи соответственно - char operations[OPER]; - int priorities[OPER]; - - void SetOpTable(); - void FormulaConverter(); - bool FormulaChecker(char form[], int size); + char operations[OPER]; // список операторов, которые возможны в записи формулы + int priorities[OPER]; // список приоритетов этих операторов + void SetOpTable(); // метод, задающий выше указанные списки public: - TFormula(); - TFormula(char const form[]); - void SetInfixForm(char const form[]); - char const* GetInfixFormula() const; - char const* GetPostfixFormula() const; - double Calculate(); + TFormula(); // конструктор по умолчанию + TFormula(char const form[]); // конструктор преобразования типа + TFormula(std::string form); // конструктор преобразования типа + void SetInfixForm(char const form[]); // функция, позваляющая поменять исходную инфиксную формулу + void SetInfixForm(std::string form); // функция, позваляющая поменять исходную инфиксную формулу + + + char const* GetInfixFormula() const; // возвращает инфиксную форму записи + char const* GetPostfixFormula() const; // возвращает постфиксную форму записи + + double Calculate(); // вычисление значение выражения + int FormulaChecker(int* Brackets, char const form[], int& size); // проверка правильность записанной исходной формулы + void FormulaConverter(); // конвертация формулы в постфиксную форму }; + #endif diff --git a/include/TStack.h b/include/TStack.h index bcb5e72..c0fd872 100644 --- a/include/TStack.h +++ b/include/TStack.h @@ -1,30 +1,29 @@ #ifndef TSTACK_H #define TSTACK_H #include -const int maxMemSize = 100; +const int maxMemSize = 100; // максимальная длина стека template -class TStack -{ +class TStack { protected: - T* pMem; - int MemSize; - int DataCount; + T* pMem; // массив элементов стека + int MemSize; // размер стека + int DataCount; // количество элементов стека public: - TStack(int size = maxMemSize); - TStack(TStack const& st); - ~TStack(); + TStack(int size = maxMemSize); // конструктор с параметрами/по молчанию + TStack(TStack const& st); // конструктор копирования + ~TStack(); // деструктор - TStack& operator=(TStack const& st); - bool isEmpty() const; - bool isFull() const; - void Put(const T& Val); - virtual T Get(); - T CheckLast(); + TStack& operator=(TStack const& st); // операция присваивания + bool isEmpty() const; // проверка стека на пустоту + bool isFull() const; // проверка стека на полноту + void Put(const T& Val); // помещение нового элемента в стек + virtual T Get(); // выталкивание элемента из стека + T CheckLast(); // просмотр последнего элемента стека }; - +//..............................................................................................// template -TStack::TStack(int size) { +TStack::TStack(int size) { // конструктор с параметрами(по умолчанию) if (size < 0 || size > maxMemSize) throw std::out_of_range("Было введено некорректное значение длины создаваемого стека"); if (size == 0) @@ -33,16 +32,17 @@ TStack::TStack(int size) { DataCount = 0; pMem = new T[MemSize]; } - +//...............................................................................................// template -TStack::~TStack() { +TStack::~TStack() { // деструктор if (pMem != NULL) { delete[] pMem; pMem = NULL; } } +//...............................................................................................// template -TStack::TStack(TStack const& st) { +TStack::TStack(TStack const& st) { //конструктор копирования MemSize = st.MemSize; DataCount = st.DataCount; pMem = new T[MemSize]; @@ -50,9 +50,9 @@ TStack::TStack(TStack const& st) { pMem[i] = st.pMem[i]; } } - +//................................................................................................// template -TStack& TStack::operator=(TStack const& st) { +TStack& TStack::operator=(TStack const& st) { // операция присваивания if (this != &st) { if (MemSize != st.MemSize) { delete[] pMem; @@ -66,15 +66,15 @@ TStack& TStack::operator=(TStack const& st) { } return *this; } - +//.................................................................................................// template -bool TStack::isEmpty() const { return (DataCount == 0); } - +bool TStack::isEmpty() const { return (DataCount == 0); } // проверка на пустоту +//.................................................................................................// template -bool TStack::isFull() const { return (DataCount == MemSize); } - +bool TStack::isFull() const { return (DataCount == MemSize); } // проверка на полноту +//.................................................................................................// template -void TStack::Put(const T& Val) { +void TStack::Put(const T& Val) { // добавление элемента в стек if (isFull()) throw std::out_of_range("Стек полон!"); else { @@ -82,9 +82,9 @@ void TStack::Put(const T& Val) { pMem[DataCount - 1] = Val; } } - +//.................................................................................................// template -T TStack::Get() { +T TStack::Get() { // выталкивание элемента из стека if (isEmpty()) throw std::out_of_range("Стек пуст!"); else { @@ -93,9 +93,11 @@ T TStack::Get() { return(tmp); } } - +//..................................................................................................// template -T TStack::CheckLast() { +T TStack::CheckLast() { // просмотр последнего элемента стека + if (isEmpty()) + throw std::out_of_range("Стек пуст!"); return(pMem[DataCount - 1]); } diff --git a/samples/TMain.cpp b/samples/TMain.cpp index 74dd609..7f4adeb 100644 --- a/samples/TMain.cpp +++ b/samples/TMain.cpp @@ -2,13 +2,15 @@ #include "TStack.h" #include "TFormula.h" #include +#include +#include int main(int argc, char** argv) { setlocale(LC_ALL, "RUSSIAN"); TFormula fml; std::cout << "Введите уравнение: "; - char a[255]; - std::cin >> a; + std::string a; + std::getline(std::cin, a); fml.SetInfixForm(a); std::cout << "Результат: " << fml.Calculate() << '\n'; diff --git a/src/TFormula.cpp b/src/TFormula.cpp index ef1127e..147aaf4 100644 --- a/src/TFormula.cpp +++ b/src/TFormula.cpp @@ -1,8 +1,10 @@ #include "TFormula.h" #include #include +#include +#include -void TFormula::SetOpTable() { +void TFormula::SetOpTable() { // задает списоп применимых в формуле операций, а так же их приоритеты operations[0] = '('; operations[1] = ')'; operations[2] = '+'; @@ -18,13 +20,38 @@ void TFormula::SetOpTable() { priorities[5] = 3; } -TFormula::TFormula() { +void PrintErrTable(int Brackets[], int brckts, int erCnt) { // печать таблицы с ошибочной расстановкой скобок + std::cout << "Неверная запись исхондной формулы\n"; + std::cout << "Открывающая" << ' ' << "Закрывающая" << std::endl; + for (int i = 0; i < brckts; i += 2) { + if(Brackets[i] == 0) + std::cout << std::setw(6) << '-' << std::setw(12) << Brackets[i + 1] << '\n'; + else + if(Brackets[i+1] == 0) + std::cout << std::setw(6) << Brackets[i] << std::setw(12) << '-' << '\n'; + else + std::cout << std::setw(6) << Brackets[i] << std::setw(12) << Brackets[i + 1] << '\n'; + } + std::cout << "Число ошибок в записи скобок: " << erCnt << '\n'; +} + +TFormula::TFormula() { // конструктор по умолчанию + SetOpTable(); infSize = 0; postSize = 0; +} + +TFormula::TFormula(char const form[]) { // конструктор преобразования типа SetOpTable(); + SetInfixForm(form); } -TFormula::TFormula(char const form[]) { + +TFormula::TFormula(std::string form) { // конструктор преобразования типа SetOpTable(); + SetInfixForm(form); +} + +void TFormula::SetInfixForm(char const form[]) { // позволяет поменять исходную инфиксную форму int counter = 0; while (form[counter] != '\0') { if (counter > MaxLength - 1) @@ -34,114 +61,133 @@ TFormula::TFormula(char const form[]) { } Infix[counter] = '\0'; infSize = counter; - FormulaConverter(); + postSize = 0; + int br[MaxLength]; + int brckts; + int erCnt = FormulaChecker(br, Infix, brckts); + if (erCnt) { + PrintErrTable(br, brckts, erCnt); + throw std::logic_error("Неверная запись исходной формулы"); + } } -void TFormula::SetInfixForm(char const form[]) { +void TFormula::SetInfixForm(std::string form) { // позволяет поменять исходную инфиксную форму + if (form.size() > MaxLength) + throw std::out_of_range("Попытка присвоить формульной строке значение строки, превосходящей максимально возможную длину формулы"); int counter = 0; - while (form[counter] != '\0') { - if (counter > MaxLength - 1) - throw std::out_of_range("Попытка присвоить формульной строке значение строки, превосходящей максимально возможную длину формулы"); + for (; counter < form.size(); ++counter) { Infix[counter] = form[counter]; - counter++; } Infix[counter] = '\0'; infSize = counter; - FormulaConverter(); + postSize = 0; + int br[MaxLength]; + int brckts; + int erCnt = FormulaChecker(br, Infix, brckts); + if (erCnt) { + PrintErrTable(br, brckts, erCnt); + throw std::logic_error("Неверная запись исходной формулы"); + } + } -bool TFormula::FormulaChecker(char form[], int size) { - TStack a; - int cnt = 0; - for (int i = 0; i < size; ++i) { +int TFormula::FormulaChecker(int* Brackets, char const form[], int& size) { // проверяет исходную формулу на корректность + TStack a; + int cnt = 1; + size = 0; + int ercnt = 0; + for (int i = 0; form[i] != '\0'; ++i) { if (form[i] == '(') { - cnt++; a.Put(cnt); + cnt++; } if (form[i] == ')') { if (a.isEmpty()) { - return 0; + Brackets[size++] = 0; + Brackets[size++] = cnt; + cnt++; + ercnt++; } else { - a.Get(); + Brackets[size++] = a.Get(); + Brackets[size++] = cnt; + cnt++; } } } - if (a.isEmpty()) { - return 1; - } - else { - return 0; + while (!a.isEmpty()) { + Brackets[size++] = a.Get(); + Brackets[size++] = 0; + ercnt++; } + return ercnt; } -void TFormula::FormulaConverter() { - if (FormulaChecker(Infix, infSize)) { - int cnt = 0; - TStack symb; - for (int i = 0; i < infSize; ++i) { - bool flag = true; - for (int j = 0; j < OPER; ++j) { - if (Infix[i] == operations[j]) { - flag = false; - if (symb.isEmpty()) { +void TFormula::FormulaConverter() { // преобразование инфиксной записи в постфиксную + int cnt = 0; + TStack symb; + for (int i = 0; i < infSize; ++i) { + bool flag = true; + for (int j = 0; j < OPER; ++j) { + if (Infix[i] == operations[j]) { + flag = false; + if (symb.isEmpty()) { + symb.Put(j); + } + else { + if (priorities[symb.CheckLast()] < priorities[j] && priorities[j] > 1) { symb.Put(j); } else { - if (priorities[symb.CheckLast()] < priorities[j] && priorities[j] > 1) { + if (priorities[j] == 0) { symb.Put(j); } - else { - if (priorities[j] == 0) { - symb.Put(j); - } - if (priorities[j] == 1) { - while (!symb.isEmpty() && priorities[symb.CheckLast()] > 0) { - Postfix[cnt++] = operations[symb.Get()]; - } - symb.Get(); + if (priorities[j] == 1) { + while (!symb.isEmpty() && priorities[symb.CheckLast()] > 0) { + Postfix[cnt++] = operations[symb.Get()]; } - if (priorities[j] > 1) { - while (!symb.isEmpty() && priorities[symb.CheckLast()] >= priorities[j]) { - Postfix[cnt++] = operations[symb.Get()]; - } - symb.Put(j); + symb.Get(); + } + if (priorities[j] > 1) { + while (!symb.isEmpty() && priorities[symb.CheckLast()] >= priorities[j]) { + Postfix[cnt++] = operations[symb.Get()]; } + symb.Put(j); } } - break; } + break; } - if (flag && ((Infix[i] >= 48 && Infix[i] <= 57) || Infix[i] == 46 || Infix[i] == 44)) { - Postfix[cnt++] = Infix[i]; - if (i == infSize - 1) - Postfix[cnt++] = ' '; - else { - bool tr = false; - for (int j = 0; j < OPER; ++j) { - if (Infix[i + 1] == operations[j] || Infix[i + 1] == ' ') - tr = true; - } - if (tr) - Postfix[cnt++] = ' '; + } + if (flag && ((Infix[i] >= 48 && Infix[i] <= 57) || Infix[i] == 46 || Infix[i] == 44)) { + Postfix[cnt++] = Infix[i]; + if (i == infSize - 1) + Postfix[cnt++] = ' '; + else { + bool tr = false; + for (int j = 0; j < OPER; ++j) { + if (Infix[i + 1] == operations[j] || Infix[i + 1] == ' ') + tr = true; } + if (tr) + Postfix[cnt++] = ' '; } - else - if (flag && Infix[i] != ' ') - throw std::logic_error("В записи выражения используются недопустивые(пока) символы"); - } - while (!symb.isEmpty()) - { - Postfix[cnt++] = operations[symb.Get()]; } - Postfix[cnt] = '\0'; - postSize = cnt; + else + if (flag && Infix[i] != ' ') + throw std::logic_error("В записи выражения используются недопустивые символы"); } - else - throw std::out_of_range("Эта формула не корректна"); + while (!symb.isEmpty()) + { + Postfix[cnt++] = operations[symb.Get()]; + } + Postfix[cnt] = '\0'; + postSize = cnt; } -double TFormula::Calculate() { +double TFormula::Calculate() { // произведение вычислений + if (postSize == 0) + FormulaConverter(); if (postSize == 0) return 0; TStack st; @@ -224,10 +270,10 @@ double TFormula::Calculate() { return st.Get(); } -char const* TFormula::GetInfixFormula() const { +char const* TFormula::GetInfixFormula() const { // возвращает инфиксную форму записи return Infix; } -char const* TFormula::GetPostfixFormula() const { +char const* TFormula::GetPostfixFormula() const { // возвращает постфиксную форму записи return Postfix; } \ No newline at end of file From 29956fce32a1db708aaa28f283c3309ee008c085 Mon Sep 17 00:00:00 2001 From: SandalovKY Date: Mon, 23 Dec 2019 17:50:06 +0300 Subject: [PATCH 2/3] Fin --- include/TFormula.h | 35 +++++++----- include/TStack.h | 12 ++-- samples/TMain.cpp | 4 +- src/TFormula.cpp | 138 ++++++++++++++++++++++----------------------- 4 files changed, 99 insertions(+), 90 deletions(-) diff --git a/include/TFormula.h b/include/TFormula.h index f03a19c..3ae80a2 100644 --- a/include/TFormula.h +++ b/include/TFormula.h @@ -2,34 +2,39 @@ #define TFORMULA_H #include "TStack.h" #include -const int MaxLength = 255; // максимальная длина исходной формулы +const int MaxLength = 256; // максимальная длина исходной формулы const int OPER = 6; // число допустимых операций в выражении +struct Operations { + char operation; + int priority; +}; +struct Frmla { + int size; // длина формулы + char Frml[MaxLength]; // сама формула +}; class TFormula { private: - int infSize; // размер инфиксной записи формулы - int postSize; // размер постфиксной записи формулы - char Infix[MaxLength]; // собственно сама инфиксная - char Postfix[MaxLength]; // и постфиксная записи соответственно + Frmla infix; // инфиксная фома записи числа + Frmla postfix; // постфиксная форма записи - char operations[OPER]; // список операторов, которые возможны в записи формулы - int priorities[OPER]; // список приоритетов этих операторов - void SetOpTable(); // метод, задающий выше указанные списки + Operations ops[OPER]; // операции, которые можно применять в формуле + void SetOpTable(); // метод, задающий выше указанный список + void FormulaConverter(); // конвертация формулы в постфиксную форму + int FormulaChecker(int* Brackets, char const* form, int& size) const; // проверка правильность записанной исходной формулы public: TFormula(); // конструктор по умолчанию - TFormula(char const form[]); // конструктор преобразования типа - TFormula(std::string form); // конструктор преобразования типа - void SetInfixForm(char const form[]); // функция, позваляющая поменять исходную инфиксную формулу - void SetInfixForm(std::string form); // функция, позваляющая поменять исходную инфиксную формулу + TFormula(char* form); // конструктор преобразования типа + TFormula(std::string const& form); // конструктор преобразования типа + void SetInfixForm(char* form); // функция, позволяющая поменять исходную инфиксную формулу + void SetInfixForm(std::string const& form); // функция, позволяющая поменять исходную инфиксную формулу char const* GetInfixFormula() const; // возвращает инфиксную форму записи char const* GetPostfixFormula() const; // возвращает постфиксную форму записи double Calculate(); // вычисление значение выражения - int FormulaChecker(int* Brackets, char const form[], int& size); // проверка правильность записанной исходной формулы - void FormulaConverter(); // конвертация формулы в постфиксную форму -}; + }; #endif diff --git a/include/TStack.h b/include/TStack.h index c0fd872..400647f 100644 --- a/include/TStack.h +++ b/include/TStack.h @@ -18,8 +18,8 @@ class TStack { bool isEmpty() const; // проверка стека на пустоту bool isFull() const; // проверка стека на полноту void Put(const T& Val); // помещение нового элемента в стек - virtual T Get(); // выталкивание элемента из стека - T CheckLast(); // просмотр последнего элемента стека + T Get(); // выталкивание элемента из стека + T const& CheckLast() const; // просмотр последнего элемента стека }; //..............................................................................................// template @@ -31,6 +31,9 @@ template MemSize = size; DataCount = 0; pMem = new T[MemSize]; + for (int i = 0; i < MemSize; ++i) { + pMem[i] = 0; + } } //...............................................................................................// template @@ -88,14 +91,13 @@ template if (isEmpty()) throw std::out_of_range("Стек пуст!"); else { - T tmp = pMem[DataCount - 1]; DataCount--; - return(tmp); + return(pMem[DataCount]); } } //..................................................................................................// template -T TStack::CheckLast() { // просмотр последнего элемента стека +T const& TStack::CheckLast() const{ // просмотр последнего элемента стека if (isEmpty()) throw std::out_of_range("Стек пуст!"); return(pMem[DataCount - 1]); diff --git a/samples/TMain.cpp b/samples/TMain.cpp index 7f4adeb..f3d2de4 100644 --- a/samples/TMain.cpp +++ b/samples/TMain.cpp @@ -12,7 +12,9 @@ int main(int argc, char** argv) { std::string a; std::getline(std::cin, a); fml.SetInfixForm(a); - + TFormula b = a; + std::cout << "Формула, записанная в инфиксной форме: " << b.GetInfixFormula() << std::endl; + std::cout << "В постфиксной: " << b.GetPostfixFormula() << std::endl; std::cout << "Результат: " << fml.Calculate() << '\n'; return 0; } \ No newline at end of file diff --git a/src/TFormula.cpp b/src/TFormula.cpp index 147aaf4..4f36068 100644 --- a/src/TFormula.cpp +++ b/src/TFormula.cpp @@ -5,19 +5,18 @@ #include void TFormula::SetOpTable() { // задает списоп применимых в формуле операций, а так же их приоритеты - operations[0] = '('; - operations[1] = ')'; - operations[2] = '+'; - operations[3] = '-'; - operations[4] = '*'; - operations[5] = '/'; - - priorities[0] = 0; - priorities[1] = 1; - priorities[2] = 2; - priorities[3] = 2; - priorities[4] = 3; - priorities[5] = 3; + ops[0].operation = '('; + ops[0].priority = 0; + ops[1].operation = ')'; + ops[1].priority = 1; + ops[2].operation = '+'; + ops[2].priority = 2; + ops[3].operation = '-'; + ops[3].priority = 2; + ops[4].operation = '*'; + ops[4].priority = 3; + ops[5].operation = '/'; + ops[5].priority = 3; } void PrintErrTable(int Brackets[], int brckts, int erCnt) { // печать таблицы с ошибочной расстановкой скобок @@ -37,61 +36,62 @@ TFormula::TFormula() { // конструктор по умолчанию SetOpTable(); - infSize = 0; - postSize = 0; + infix.size = 0; + postfix.size = 0; + infix.Frml[0] = '\0'; + postfix.Frml[0] = '\0'; } -TFormula::TFormula(char const form[]) { // конструктор преобразования типа - SetOpTable(); +TFormula::TFormula(char* form):TFormula() { // конструктор преобразования типа SetInfixForm(form); } -TFormula::TFormula(std::string form) { // конструктор преобразования типа - SetOpTable(); +TFormula::TFormula(std::string const& form):TFormula() { // конструктор преобразования типа SetInfixForm(form); } -void TFormula::SetInfixForm(char const form[]) { // позволяет поменять исходную инфиксную форму +void TFormula::SetInfixForm(char* form) { // позволяет поменять исходную инфиксную форму int counter = 0; while (form[counter] != '\0') { if (counter > MaxLength - 1) throw std::out_of_range("Попытка присвоить формульной строке значение строки, превосходящей максимально возможную длину формулы"); - Infix[counter] = form[counter]; + infix.Frml[counter] = form[counter]; counter++; } - Infix[counter] = '\0'; - infSize = counter; - postSize = 0; + infix.Frml[counter] = '\0'; + infix.size = counter; + postfix.size = 0; int br[MaxLength]; int brckts; - int erCnt = FormulaChecker(br, Infix, brckts); + int erCnt = FormulaChecker(br, infix.Frml, brckts); if (erCnt) { PrintErrTable(br, brckts, erCnt); throw std::logic_error("Неверная запись исходной формулы"); } + FormulaConverter(); } -void TFormula::SetInfixForm(std::string form) { // позволяет поменять исходную инфиксную форму +void TFormula::SetInfixForm(std::string const& form) { // позволяет поменять исходную инфиксную форму if (form.size() > MaxLength) throw std::out_of_range("Попытка присвоить формульной строке значение строки, превосходящей максимально возможную длину формулы"); int counter = 0; for (; counter < form.size(); ++counter) { - Infix[counter] = form[counter]; + infix.Frml[counter] = form[counter]; } - Infix[counter] = '\0'; - infSize = counter; - postSize = 0; + infix.Frml[counter] = '\0'; + infix.size = counter; + postfix.size = 0; int br[MaxLength]; int brckts; - int erCnt = FormulaChecker(br, Infix, brckts); + int erCnt = FormulaChecker(br, infix.Frml, brckts); if (erCnt) { PrintErrTable(br, brckts, erCnt); throw std::logic_error("Неверная запись исходной формулы"); } - + FormulaConverter(); } -int TFormula::FormulaChecker(int* Brackets, char const form[], int& size) { // проверяет исходную формулу на корректность +int TFormula::FormulaChecker(int* Brackets, char const* form, int& size) const { // проверяет исходную формулу на корректность TStack a; int cnt = 1; size = 0; @@ -126,31 +126,31 @@ void TFormula::FormulaConverter() { // преобразование инфиксной записи в постфиксную int cnt = 0; TStack symb; - for (int i = 0; i < infSize; ++i) { + for (int i = 0; i < infix.size; ++i) { bool flag = true; for (int j = 0; j < OPER; ++j) { - if (Infix[i] == operations[j]) { + if (infix.Frml[i] == ops[j].operation) { flag = false; if (symb.isEmpty()) { symb.Put(j); } else { - if (priorities[symb.CheckLast()] < priorities[j] && priorities[j] > 1) { + if (ops[symb.CheckLast()].priority < ops[j].priority && ops[j].priority > 1) { symb.Put(j); } else { - if (priorities[j] == 0) { + if (ops[j].priority == 0) { symb.Put(j); } - if (priorities[j] == 1) { - while (!symb.isEmpty() && priorities[symb.CheckLast()] > 0) { - Postfix[cnt++] = operations[symb.Get()]; + if (ops[j].priority == 1) { + while (!symb.isEmpty() && ops[symb.CheckLast()].priority > 0) { + postfix.Frml[cnt++] = ops[symb.Get()].operation; } symb.Get(); } - if (priorities[j] > 1) { - while (!symb.isEmpty() && priorities[symb.CheckLast()] >= priorities[j]) { - Postfix[cnt++] = operations[symb.Get()]; + if (ops[j].priority > 1) { + while (!symb.isEmpty() && ops[symb.CheckLast()].priority >= ops[j].priority ) { + postfix.Frml[cnt++] = ops[symb.Get()].operation; } symb.Put(j); } @@ -159,52 +159,52 @@ break; } } - if (flag && ((Infix[i] >= 48 && Infix[i] <= 57) || Infix[i] == 46 || Infix[i] == 44)) { - Postfix[cnt++] = Infix[i]; - if (i == infSize - 1) - Postfix[cnt++] = ' '; + if (flag && ((infix.Frml[i] >= 48 && infix.Frml[i] <= 57) || infix.Frml[i] == 46 || infix.Frml[i] == 44)) { + postfix.Frml[cnt++] = infix.Frml[i]; + if (i == infix.size - 1) + postfix.Frml[cnt++] = ' '; else { bool tr = false; for (int j = 0; j < OPER; ++j) { - if (Infix[i + 1] == operations[j] || Infix[i + 1] == ' ') + if (infix.Frml[i + 1] == ops[j].operation || infix.Frml[i + 1] == ' ') tr = true; } if (tr) - Postfix[cnt++] = ' '; + postfix.Frml[cnt++] = ' '; } } else - if (flag && Infix[i] != ' ') + if (flag && infix.Frml[i] != ' ') throw std::logic_error("В записи выражения используются недопустивые символы"); } while (!symb.isEmpty()) { - Postfix[cnt++] = operations[symb.Get()]; + postfix.Frml[cnt++] = ops[symb.Get()].operation; } - Postfix[cnt] = '\0'; - postSize = cnt; + postfix.Frml[cnt] = '\0'; + postfix.size = cnt; } double TFormula::Calculate() { // произведение вычислений - if (postSize == 0) + if (postfix.size == 0) FormulaConverter(); - if (postSize == 0) - return 0; + if (postfix.size == 0) + throw std::logic_error("Нет выражения, результат которого можно было бы вычислить"); TStack st; double tmp = 0; int cnt = 0; int flp = 0; - for (int i = 0; i < postSize; ++i) { + for (int i = 0; i < postfix.size; ++i) { bool flag = true; for (int j = 2; j < OPER; ++j) { - if (Postfix[i] == operations[j]) { + if (postfix.Frml[i] == ops[j].operation) { flag = false; if (st.isEmpty()) throw std::logic_error("нет операндов для применения знака операции"); tmp = st.Get(); if (st.isEmpty()) throw std::logic_error("нет второго операнда для применения знака операции"); - switch (operations[j]) + switch (ops[j].operation) { case '+': { @@ -235,14 +235,14 @@ st.Put(tmp); } } - if (Postfix[i] == '.' || Postfix[i] == ',') { - if(Postfix[i+1] != ' ') + if (postfix.Frml[i] == '.' || postfix.Frml[i] == ',') { + if(postfix.Frml[i + 1] != ' ') flp++; } - if (flag && Postfix[i] != ' ' && Postfix[i] != '.' && Postfix[i] != ',') { + if (flag && postfix.Frml[i] != ' ' && postfix.Frml[i] != '.' && postfix.Frml[i] != ',') { if (flp == 0) { - if (Postfix[i + 1] == ' ' || Postfix[i + 1] == '.' || Postfix[i + 1] == ',') { - tmp = Postfix[i] - 48; + if (postfix.Frml[i + 1] == ' ' || postfix.Frml[i + 1] == '.' || postfix.Frml[i + 1] == ',') { + tmp = postfix.Frml[i] - 48; int mn = 10; while (cnt > 0) { tmp += st.Get() * mn; @@ -252,15 +252,15 @@ st.Put(tmp); } else { - st.Put(Postfix[i] - 48); + st.Put(postfix.Frml[i] - 48); cnt++; } } else { tmp = st.Get(); - tmp += pow(10, flp * -1) * (Postfix[i] - 48); + tmp += pow(10, flp * -1) * (postfix.Frml[i] - 48); st.Put(tmp); - if (Postfix[i + 1] == ' ') + if (postfix.Frml[i + 1] == ' ') flp = 0; else flp++; @@ -271,9 +271,9 @@ } char const* TFormula::GetInfixFormula() const { // возвращает инфиксную форму записи - return Infix; + return infix.Frml; } char const* TFormula::GetPostfixFormula() const { // возвращает постфиксную форму записи - return Postfix; + return postfix.Frml; } \ No newline at end of file From c97c7e2968759fac94acc9f2be20ed21140653ee Mon Sep 17 00:00:00 2001 From: SandalovKY Date: Mon, 23 Dec 2019 22:32:35 +0300 Subject: [PATCH 3/3] Final --- include/TFormula.h | 7 +- include/TStack.h | 4 +- samples/TMain.cpp | 2 +- src/TFormula.cpp | 31 ++++---- test/FormulaTest.cpp | 165 ++++++++++++++++++++++++++++++++++++++++++- test/StackTest.cpp | 103 +++++++++++++++++++++++++++ test/testMain.cpp | 3 +- 7 files changed, 288 insertions(+), 27 deletions(-) diff --git a/include/TFormula.h b/include/TFormula.h index 3ae80a2..9fab948 100644 --- a/include/TFormula.h +++ b/include/TFormula.h @@ -20,8 +20,6 @@ class TFormula { Operations ops[OPER]; // операции, которые можно применять в формуле void SetOpTable(); // метод, задающий выше указанный список - void FormulaConverter(); // конвертация формулы в постфиксную форму - int FormulaChecker(int* Brackets, char const* form, int& size) const; // проверка правильность записанной исходной формулы public: TFormula(); // конструктор по умолчанию @@ -30,9 +28,12 @@ class TFormula { void SetInfixForm(char* form); // функция, позволяющая поменять исходную инфиксную формулу void SetInfixForm(std::string const& form); // функция, позволяющая поменять исходную инфиксную формулу - + void FormulaConverter(); // конвертация формулы в постфиксную форму + int FormulaChecker(int* Brackets, int& size) const; // проверка правильность записанной исходной формулы char const* GetInfixFormula() const; // возвращает инфиксную форму записи char const* GetPostfixFormula() const; // возвращает постфиксную форму записи + int const GetInfixSize() const { return infix.size; } + int const GetPostfixSize() const { return postfix.size; } double Calculate(); // вычисление значение выражения }; diff --git a/include/TStack.h b/include/TStack.h index 400647f..16b76e9 100644 --- a/include/TStack.h +++ b/include/TStack.h @@ -26,8 +26,8 @@ template TStack::TStack(int size) { // конструктор с параметрами(по умолчанию) if (size < 0 || size > maxMemSize) throw std::out_of_range("Было введено некорректное значение длины создаваемого стека"); - if (size == 0) - size = maxMemSize; + /*if (size == 0) + size = maxMemSize;*/ MemSize = size; DataCount = 0; pMem = new T[MemSize]; diff --git a/samples/TMain.cpp b/samples/TMain.cpp index f3d2de4..d47a5c5 100644 --- a/samples/TMain.cpp +++ b/samples/TMain.cpp @@ -12,7 +12,7 @@ int main(int argc, char** argv) { std::string a; std::getline(std::cin, a); fml.SetInfixForm(a); - TFormula b = a; + TFormula b = fml; std::cout << "Формула, записанная в инфиксной форме: " << b.GetInfixFormula() << std::endl; std::cout << "В постфиксной: " << b.GetPostfixFormula() << std::endl; std::cout << "Результат: " << fml.Calculate() << '\n'; diff --git a/src/TFormula.cpp b/src/TFormula.cpp index 4f36068..36298bc 100644 --- a/src/TFormula.cpp +++ b/src/TFormula.cpp @@ -63,12 +63,6 @@ postfix.size = 0; int br[MaxLength]; int brckts; - int erCnt = FormulaChecker(br, infix.Frml, brckts); - if (erCnt) { - PrintErrTable(br, brckts, erCnt); - throw std::logic_error("Неверная запись исходной формулы"); - } - FormulaConverter(); } void TFormula::SetInfixForm(std::string const& form) { // позволяет поменять исходную инфиксную форму @@ -81,27 +75,19 @@ infix.Frml[counter] = '\0'; infix.size = counter; postfix.size = 0; - int br[MaxLength]; - int brckts; - int erCnt = FormulaChecker(br, infix.Frml, brckts); - if (erCnt) { - PrintErrTable(br, brckts, erCnt); - throw std::logic_error("Неверная запись исходной формулы"); - } - FormulaConverter(); } -int TFormula::FormulaChecker(int* Brackets, char const* form, int& size) const { // проверяет исходную формулу на корректность +int TFormula::FormulaChecker(int* Brackets, int& size) const { // проверяет исходную формулу на корректность TStack a; int cnt = 1; size = 0; int ercnt = 0; - for (int i = 0; form[i] != '\0'; ++i) { - if (form[i] == '(') { + for (int i = 0; infix.Frml[i] != '\0'; ++i) { + if (infix.Frml[i] == '(') { a.Put(cnt); cnt++; } - if (form[i] == ')') { + if (infix.Frml[i] == ')') { if (a.isEmpty()) { Brackets[size++] = 0; Brackets[size++] = cnt; @@ -124,6 +110,13 @@ } void TFormula::FormulaConverter() { // преобразование инфиксной записи в постфиксную + int br[MaxLength]; + int brckts; + int erCnt = FormulaChecker(br, brckts); + if (erCnt) { + PrintErrTable(br, brckts, erCnt); + throw std::logic_error("Неверная запись исходной формулы"); + } int cnt = 0; TStack symb; for (int i = 0; i < infix.size; ++i) { @@ -135,7 +128,7 @@ symb.Put(j); } else { - if (ops[symb.CheckLast()].priority < ops[j].priority && ops[j].priority > 1) { + if (ops[symb.CheckLast()].priority <= ops[j].priority && ops[j].priority > 1) { symb.Put(j); } else { diff --git a/test/FormulaTest.cpp b/test/FormulaTest.cpp index 1df570c..885e06e 100644 --- a/test/FormulaTest.cpp +++ b/test/FormulaTest.cpp @@ -1,2 +1,165 @@ #include "TFormula.h" -#include \ No newline at end of file +#include +TEST(TFormula, can_create_formula_with_size_less_than_255) +{ + EXPECT_NO_THROW(TFormula f("2-7+(5*2)")); +} + +TEST(TFormula, cant_create_formula_with_size_greater_than_255) +{ + EXPECT_ANY_THROW(TFormula f("2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)*2-7+(5*2)")); +} + +TEST(TFormula, can_check_formula) +{ + TFormula f("2-7+(5*2)"); + int arr[MaxLength]; + int cnt = 0; + EXPECT_NO_THROW(f.FormulaChecker(arr, cnt)); +} + +TEST(TFormula, brackets_is_correct) +{ + TFormula f("(())()()(()(()))"); + int arr[MaxLength]; + int cnt = 0; + EXPECT_EQ(f.FormulaChecker(arr, cnt), 0); +} + +TEST(TFormula, brackets_in_formula_is_correct) +{ + TFormula f("((8-3)-5/((7+8)*9)-8)+25*7"); + int arr[MaxLength]; + int cnt = 0; + EXPECT_EQ(f.FormulaChecker(arr, cnt), 0); +} + +TEST(TFormula, brackets_is_uncorrect) +{ + TFormula f("(())()()(((()(()))"); + int arr[MaxLength]; + int cnt = 0; + EXPECT_NE(f.FormulaChecker(arr, cnt), 0); +} + +TEST(TFormula, brackets_in_formula_is_uncorrect) +{ + TFormula f("(((8-3)-5/((7+8)*9)-8)+25*7"); + int arr[MaxLength]; + int cnt = 0; + EXPECT_NE(f.FormulaChecker(arr, cnt), 0); +} + +TEST(TFormula, number_of_errors_is_correct_1) +{ + TFormula f("(())()()(((()(()))"); + int arr[MaxLength]; + int cnt = 0; + EXPECT_EQ(f.FormulaChecker(arr, cnt), 2); +} + +TEST(TFormula, number_of_errors_is_correct_2) +{ + TFormula f("(((8-3)-5/((7+8)*9)-8)+25*7"); + int arr[MaxLength]; + int cnt = 0; + EXPECT_EQ(f.FormulaChecker(arr, cnt), 1); +} + +TEST(TFormula, can_convert_correct_formula) +{ + TFormula f("((8-3)-5/((7+8)*9)-8)+25*7"); + EXPECT_NO_THROW(f.FormulaConverter()); +} + +TEST(TFormula, cant_convert_uncorrect_formula) +{ + TFormula f("(((8-3)-5/((7+8)*9)-8)+25*7"); + EXPECT_ANY_THROW(f.FormulaConverter()); +} + +TEST(TFormula, can_calculate_correct_formula) +{ + TFormula f("((8-3)-5/((7+8)*9)-8)+25*7"); + EXPECT_NO_THROW(f.Calculate()); +} + +TEST(TFormula, cant_calculate_uncorrect_formula) +{ + TFormula f("(((8-3)-5/((7+8)*9)-8)+25*7"); + EXPECT_ANY_THROW(f.Calculate()); +} + +TEST(TFormula, calculator_works_right) +{ + TFormula f("((8-3)-5/((7+8)*9)-8)+25*7"); + EXPECT_EQ((int)f.Calculate(), 171); +} + +TEST(tformula, can_create_correct_formula_1) { + ASSERT_NO_THROW(TFormula a("1+2")); +} + +TEST(tformula, can_transform_to_correct_postfix_form_1) { + TFormula a("1+2"); + char test[] = "1 2 +"; + for (int i = 0; i < a.GetPostfixSize(); ++i) { + EXPECT_EQ(test[i], a.GetPostfixFormula()[i]); + } +} + +TEST(tformula, can_calculate_correct_1) { + TFormula a("1+2"); + EXPECT_EQ(3, a.Calculate()); +} + +TEST(tformula, can_create_correct_formula_2) { + ASSERT_NO_THROW(TFormula a("1+2*(3-2)-4")); +} + +TEST(tformula, can_transform_to_correct_postfix_form_2) { + TFormula a("1+2*(3-2)-4"); + char test[] = "1 2 3 2 -*+4 -"; + for (int i = 0; i < a.GetPostfixSize(); ++i) { + EXPECT_EQ(test[i], a.GetPostfixFormula()[i]); + } +} + +TEST(tformula, can_calculate_correct_2) { + TFormula a("1+2*(3-2)-4"); + EXPECT_EQ(-1, a.Calculate()); +} + +TEST(tformula, can_create_correct_formula_3) { + ASSERT_NO_THROW(TFormula a("1+2/(3-3)")); +} + +TEST(tformula, can_transform_to_correct_postfix_form_3) { + TFormula a("1+2/(3-3)"); + char test[] = "1 2 3 3 -/+"; + for (int i = 0; i < a.GetPostfixSize(); ++i) { + EXPECT_EQ(test[i], a.GetPostfixFormula()[i]); + } +} + +TEST(tformula, can_not_calculate_correct_3) { + TFormula a("1+2/(3-3)"); + EXPECT_ANY_THROW(a.Calculate()); +} + +TEST(tformula, can_create_correct_formula_4) { + ASSERT_NO_THROW(TFormula a("1++1")); +} + +TEST(tformula, can_transform_to_correct_postfix_form_4) { + TFormula a("1++1"); + char test[] = "1 1 ++"; + for (int i = 0; i < a.GetPostfixSize(); ++i) { + EXPECT_EQ(test[i], a.GetPostfixFormula()[i]); + } +} + +TEST(tformula, can_not_calculate_correct_4) { + TFormula a("1++1"); + EXPECT_ANY_THROW(a.Calculate()); +} \ No newline at end of file diff --git a/test/StackTest.cpp b/test/StackTest.cpp index 42fbe84..47473f8 100644 --- a/test/StackTest.cpp +++ b/test/StackTest.cpp @@ -1,3 +1,106 @@ #include "TStack.h" #include +TEST(TStack, can_create_stack_with_positive_size) +{ + EXPECT_NO_THROW(TStack s(5)); +} + +TEST(TStack, can_create_stack_with_zero_size) +{ + EXPECT_NO_THROW(TStack s(0)); +} + +TEST(TStack, cant_create_stack_with_negative_size) +{ + EXPECT_ANY_THROW(TStack s(-5)); +} + +TEST(TStack, can_create_stack_without_size) +{ + EXPECT_NO_THROW(TStack s()); +} + +TEST(TStack, can_put_value_to_stack) +{ + TStack s(5); + EXPECT_NO_THROW(s.Put(5)); +} + +TEST(TStack, cant_put_value_if_stack_is_full) +{ + TStack s(2); + s.Put(1); + s.Put(2); + EXPECT_ANY_THROW(s.Put(3)); +} + +TEST(TStack, can_get_value_from_stack) +{ + TStack s(5); + s.Put(1); + s.Put(2); + s.Put(3); + EXPECT_NO_THROW(s.Get()); +} + +TEST(TStack, get_value_from_stack_right) +{ + TStack s(5); + s.Put(1); + s.Put(2); + s.Put(3); + EXPECT_EQ(s.Get(), 3); +} + +TEST(TStack, cant_get_value_from_stack_with_zero_size) +{ + TStack s(0); + EXPECT_ANY_THROW(s.Get()); +} + +TEST(TStack, cant_get_value_from_empty_stack) +{ + TStack s(5); + EXPECT_ANY_THROW(s.Get()); +} + +TEST(TStack, can_know_top_element) +{ + TStack s(5); + s.Put(1); + s.Put(2); + s.Put(3); + EXPECT_NO_THROW(s.CheckLast()); +} + +TEST(TStack, cant_know_top_element_from_empty_stack) +{ + TStack s(5); + EXPECT_ANY_THROW(s.CheckLast()); +} + +TEST(TStack, cant_know_top_element_from_stack_with_zero_size) +{ + TStack s(0); + EXPECT_ANY_THROW(s.CheckLast()); +} + +TEST(TStack, top_element_give_right_value) +{ + TStack s(5); + s.Put(1); + s.Put(2); + s.Put(3); + EXPECT_EQ(s.CheckLast(), 3); +} + +TEST(TStack, top_element_not_delete_value_from_stack) +{ + TStack s(5); + s.Put(1); + s.Put(2); + s.Put(3); + s.CheckLast(); + EXPECT_EQ(s.Get(), 3); +} \ No newline at end of file diff --git a/test/testMain.cpp b/test/testMain.cpp index 3968c27..909541c 100644 --- a/test/testMain.cpp +++ b/test/testMain.cpp @@ -1,6 +1,7 @@ #include - +#include int main(int argc, char **argv) { + setlocale(LC_CTYPE, "RUSSIAN"); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }