From 0765d2d624f5133d3530934e319f9bb0ba221791 Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 10 Dec 2019 14:07:50 +0200 Subject: [PATCH 1/9] new --- CMakeLists.txt | 2 +- fixed_queue.cc | 12 ++++++++ fixed_queue.h | 10 +++++++ iproject.h | 3 +- main.cc | 1 + project.cc | 67 ++++++++++++++++++++++++++++++++++++++++++-- project.h | 9 +++++- string_generator.cc | 61 ++++++++++++++++++++++++++++++++++++++++ string_generator.h | 23 +++++++++++++++ test/project_test.cc | 7 +++++ 10 files changed, 190 insertions(+), 5 deletions(-) create mode 100644 fixed_queue.cc create mode 100644 fixed_queue.h create mode 100644 string_generator.cc create mode 100644 string_generator.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e6318a3..d6d0345 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(dummy_cmake_project) set(CMAKE_CXX_STANDARD 14) list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) -set(SOURCES project.cc) +set(SOURCES project.cc fixed_queue.cc string_generator.cc) add_library(ProjectLib ${SOURCES}) add_executable(project main.cc) diff --git a/fixed_queue.cc b/fixed_queue.cc new file mode 100644 index 0000000..03403b9 --- /dev/null +++ b/fixed_queue.cc @@ -0,0 +1,12 @@ +#include "fixed_queue.h" +#include + +namespace dev { + void FixedSizeQueue::push(const float item){ + if (_size >= this->size()) { + this->pop(); + } + + std::queue::push(item); + } +} diff --git a/fixed_queue.h b/fixed_queue.h new file mode 100644 index 0000000..563c1a2 --- /dev/null +++ b/fixed_queue.h @@ -0,0 +1,10 @@ +#include "queue" + +namespace dev { +class FixedSizeQueue : public std::queue { +public: + void push(const float item); +private: + const int _size = 2; +}; +} diff --git a/iproject.h b/iproject.h index ec4452f..cc56ba3 100644 --- a/iproject.h +++ b/iproject.h @@ -1,9 +1,10 @@ #pragma once +#include "string" namespace dev{ class IProject { - virtual int run() = 0; + virtual float run(std::string expression) = 0; }; } diff --git a/main.cc b/main.cc index 5b2357f..92b5f58 100644 --- a/main.cc +++ b/main.cc @@ -1,4 +1,5 @@ #include "project.h" +#include int main() { return 0; diff --git a/project.cc b/project.cc index fdc1225..2fc735f 100644 --- a/project.cc +++ b/project.cc @@ -1,8 +1,71 @@ #include "project.h" +#include +#include namespace dev { -int Project::run() { - return 0; +float Project::run(std::string expression) { + auto sGenerator = StringGenerator(expression); + if (sGenerator.empty()){ + return 0; + } + + float result = 0; + + auto stuff = [this](std::string operation) { + std::cout << _queue.size() << "kek"; + if (2 != _queue.size()) { + std::cout << "UNDEFINED!!!" << std::endl; + throw; + } + + float operand1 = _queue.front(); + _queue.pop(); + float operand2 = _queue.front(); + _queue.pop(); + + if (StringGenerator::cPlus == operation.front()) { + return operand1 + operand2; + } else if (StringGenerator::cMinus == operation.front()) { + return operand1 - operand2; + } else if (StringGenerator::cMult == operation.front()) { + return operand1 * operand2; + } else if (StringGenerator::cDiv == operation.front()) { + return operand1 / operand2; + } else { + std::cout << "UNREACHABLE!!!" << std::endl; + throw; + } + }; + + while(true) { + auto item = sGenerator.next(); + + if (StringGenerator::isOperand(item)) { + std::istringstream iss(item); + float fItem; + iss >> std::noskipws >> fItem; + _queue.push(fItem); + + continue; + } + + if (StringGenerator::isOperation(item)) { + stuff(item); + continue; + } + + if (0 == item.length()) { + break; + } + + std::cout << item << "UNREACHABLE KEK!!!" << std::endl; + throw; + } + + if (!_queue.empty()) { + result = _queue.front(); + } + return result; } } // namespace dev diff --git a/project.h b/project.h index b5cc813..ff4faed 100644 --- a/project.h +++ b/project.h @@ -1,11 +1,18 @@ #pragma once #include "iproject.h" +#include "fixed_queue.h" +#include "string_generator.h" +#include "vector" +#include "string" namespace dev { class Project : public IProject { // IProject interface public: - int run(); + float run(std::string expression = ""); + + private: + FixedSizeQueue _queue; }; } // namespace dev diff --git a/string_generator.cc b/string_generator.cc new file mode 100644 index 0000000..44355a3 --- /dev/null +++ b/string_generator.cc @@ -0,0 +1,61 @@ +#include "string_generator.h" +#include + +namespace dev { + StringGenerator::StringGenerator(std::string basic) + : _basic(basic) {} + + const std::vector StringGenerator::_operations = std::vector{ + StringGenerator::cPlus, + StringGenerator::cMinus, + StringGenerator::cMult, + StringGenerator::cDiv + }; + + bool StringGenerator::empty() { + return 0 == _basic.length(); + } + + std::string StringGenerator::next() { + std::string result = ""; + + while(true) { + if (_basic.empty()) { + break; + } + auto item = _basic.front(); + _basic.erase(0,1); + if (' ' == item) { + break; + } + result+=item; + } + return result; + } + + bool StringGenerator::isOperation(std::string item) { + if (item.length() > 1) { + return false; + } + + const auto& front = item.front(); + for (const auto& op: _operations) { + if (op == front) { + return true; + } + } + return false; + } + + bool StringGenerator::isOperand(std::string item) { + if (1 > item.length()) { + return false; + } + + std::istringstream iss(item); + float f; + iss >> std::noskipws >> f; // noskipws considers leading whitespace invalid + // Check the entire string was consumed and if either failbit or badbit is set + return iss.eof() && !iss.fail(); + } +} diff --git a/string_generator.h b/string_generator.h new file mode 100644 index 0000000..d92a650 --- /dev/null +++ b/string_generator.h @@ -0,0 +1,23 @@ +#include "string" +#include "vector" + +namespace dev { + +class StringGenerator { +public: + StringGenerator(std::string basic); + std::string next(); + bool empty(); + + static bool isOperation(std::string item); + static bool isOperand(std::string item); + + static const char cPlus = '+'; + static const char cMinus = '-'; + static const char cMult = '*'; + static const char cDiv = '/'; +private: + std::string _basic; + static const std::vector _operations; +}; +} diff --git a/test/project_test.cc b/test/project_test.cc index 5dbeb2f..100f90e 100644 --- a/test/project_test.cc +++ b/test/project_test.cc @@ -15,5 +15,12 @@ TEST_F(ProjectTest, Run) { ASSERT_EQ(0, project_.run()); } +TEST_F(ProjectTest, Simple_Operations) { + EXPECT_EQ(15, project_.run("10 5 +")); + EXPECT_EQ(5, project_.run("10 5 -")); + EXPECT_EQ(50, project_.run("10 5 *")); + EXPECT_EQ(2, project_.run("10 5 /")); +} + } // namespace testing } // namespace dev From aadf2e15bbc6366eed925e56b50d2a6308ede25b Mon Sep 17 00:00:00 2001 From: Mykola Korniichuk Date: Tue, 10 Dec 2019 15:41:16 +0200 Subject: [PATCH 2/9] fix --- fixed_queue.cc | 4 +--- project.cc | 18 ++++++++---------- project.h | 6 ++++-- string_generator.cc | 1 - string_generator.h | 1 + test/project_test.cc | 31 ++++++++++++++++++++++++++----- 6 files changed, 40 insertions(+), 21 deletions(-) diff --git a/fixed_queue.cc b/fixed_queue.cc index 03403b9..802f434 100644 --- a/fixed_queue.cc +++ b/fixed_queue.cc @@ -1,12 +1,10 @@ #include "fixed_queue.h" -#include namespace dev { void FixedSizeQueue::push(const float item){ - if (_size >= this->size()) { + while (_size <= this->size()){ this->pop(); } - std::queue::push(item); } } diff --git a/project.cc b/project.cc index 2fc735f..c86d067 100644 --- a/project.cc +++ b/project.cc @@ -1,6 +1,4 @@ #include "project.h" -#include -#include namespace dev { @@ -13,10 +11,9 @@ float Project::run(std::string expression) { float result = 0; auto stuff = [this](std::string operation) { - std::cout << _queue.size() << "kek"; if (2 != _queue.size()) { - std::cout << "UNDEFINED!!!" << std::endl; - throw; + // UNDEFINED!!! + throw std::exception(); } float operand1 = _queue.front(); @@ -33,8 +30,8 @@ float Project::run(std::string expression) { } else if (StringGenerator::cDiv == operation.front()) { return operand1 / operand2; } else { - std::cout << "UNREACHABLE!!!" << std::endl; - throw; + // UNREACHABLE!!! + throw std::exception(); } }; @@ -51,7 +48,8 @@ float Project::run(std::string expression) { } if (StringGenerator::isOperation(item)) { - stuff(item); + float result = stuff(item); + _queue.push(result); continue; } @@ -59,8 +57,8 @@ float Project::run(std::string expression) { break; } - std::cout << item << "UNREACHABLE KEK!!!" << std::endl; - throw; + // UNREACHABLE!!!" + throw std::exception(); } if (!_queue.empty()) { diff --git a/project.h b/project.h index ff4faed..f339fa0 100644 --- a/project.h +++ b/project.h @@ -2,8 +2,10 @@ #include "iproject.h" #include "fixed_queue.h" #include "string_generator.h" -#include "vector" -#include "string" + +#include +#include +#include namespace dev { diff --git a/string_generator.cc b/string_generator.cc index 44355a3..8f8c298 100644 --- a/string_generator.cc +++ b/string_generator.cc @@ -1,5 +1,4 @@ #include "string_generator.h" -#include namespace dev { StringGenerator::StringGenerator(std::string basic) diff --git a/string_generator.h b/string_generator.h index d92a650..ba39df7 100644 --- a/string_generator.h +++ b/string_generator.h @@ -1,5 +1,6 @@ #include "string" #include "vector" +#include namespace dev { diff --git a/test/project_test.cc b/test/project_test.cc index 100f90e..f7554fb 100644 --- a/test/project_test.cc +++ b/test/project_test.cc @@ -11,15 +11,36 @@ class ProjectTest : public ::testing::Test { dev::Project project_; }; -TEST_F(ProjectTest, Run) { +TEST_F(ProjectTest, Run_Basic) { ASSERT_EQ(0, project_.run()); + ASSERT_EQ(10, project_.run("10")); + ASSERT_EQ(10, project_.run("10 4")); } TEST_F(ProjectTest, Simple_Operations) { - EXPECT_EQ(15, project_.run("10 5 +")); - EXPECT_EQ(5, project_.run("10 5 -")); - EXPECT_EQ(50, project_.run("10 5 *")); - EXPECT_EQ(2, project_.run("10 5 /")); + ASSERT_EQ(15, project_.run("10 5 +")); + ASSERT_EQ(5, project_.run("10 5 -")); + ASSERT_EQ(50, project_.run("10 5 *")); + ASSERT_EQ(2, project_.run("10 5 /")); +} + +TEST_F(ProjectTest, Simple_Operations_Float) { + ASSERT_EQ(15.2, project_.run("10.1 5.1 +")); + ASSERT_EQ(5, project_.run("10.1 5.1 -")); + ASSERT_EQ(51.51, project_.run("10.1 5.1 *")); + ASSERT_EQ(2.02, project_.run("10.1 5 /")); +} + +TEST_F(ProjectTest, Simple_Operations_Exceptions) { + ASSERT_THROW(project_.run("a"), std::exception); + ASSERT_THROW(project_.run("a a"), std::exception); + ASSERT_THROW(project_.run("+"), std::exception); + ASSERT_THROW(project_.run("10 +"), std::exception); +} + +TEST_F(ProjectTest, Simple_Operations_Complex) { + EXPECT_EQ(17, project_.run("10 5 + 2 +")); + EXPECT_EQ(7, project_.run("10 5 2 +")); } } // namespace testing From 3d43694dd6a7d068ec5ed68fe5519e12c5d58897 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 11 Dec 2019 13:54:33 +0200 Subject: [PATCH 3/9] kek --- main.cc | 18 ++++++++++++++++-- project.cc | 17 +++++++++++++++++ string_generator.cc | 9 +++++++++ string_generator.h | 2 ++ test/project_test.cc | 11 +++++++---- 5 files changed, 51 insertions(+), 6 deletions(-) diff --git a/main.cc b/main.cc index 92b5f58..c7d9b95 100644 --- a/main.cc +++ b/main.cc @@ -1,6 +1,20 @@ #include "project.h" #include -int main() { - return 0; +int main(int argc, char *argv[]) { + //TODO: + // There should be easier way to convert CL args to a single string + std::string args= ""; + for (int i = 1; i < argc; ++i) { + args += argv[i]; + if (i != argc-1) { + args += ' '; + } + } + + dev::Project project; + float result = project.run(args); + std::cout << "Result: " << result << std::endl; + + return 0; } diff --git a/project.cc b/project.cc index c86d067..b26d5e2 100644 --- a/project.cc +++ b/project.cc @@ -2,8 +2,16 @@ namespace dev { +//TODO: +// Think of alternative to exceptions + +//TODO: +// Use const string float Project::run(std::string expression) { auto sGenerator = StringGenerator(expression); + + //TODO: + // Redundant check if (sGenerator.empty()){ return 0; } @@ -11,16 +19,23 @@ float Project::run(std::string expression) { float result = 0; auto stuff = [this](std::string operation) { + //TODO: + // Get rid of hardcode if (2 != _queue.size()) { // UNDEFINED!!! throw std::exception(); } + //TODO: + // Looks like front() should be redefined in FixedQueue + // to perform front() and pop() within a single call float operand1 = _queue.front(); _queue.pop(); float operand2 = _queue.front(); _queue.pop(); + //TODO: + // Use switch if (StringGenerator::cPlus == operation.front()) { return operand1 + operand2; } else if (StringGenerator::cMinus == operation.front()) { @@ -39,6 +54,8 @@ float Project::run(std::string expression) { auto item = sGenerator.next(); if (StringGenerator::isOperand(item)) { + //TODO: + // Get rid of duplicated code (see string_generator.cc) std::istringstream iss(item); float fItem; iss >> std::noskipws >> fItem; diff --git a/string_generator.cc b/string_generator.cc index 8f8c298..036b772 100644 --- a/string_generator.cc +++ b/string_generator.cc @@ -4,6 +4,10 @@ namespace dev { StringGenerator::StringGenerator(std::string basic) : _basic(basic) {} + //TODO: + // Use enum instead (will simplify usage outside): + // 1) public method for convertion of char to enum value + // 2) Move these constants to private const std::vector StringGenerator::_operations = std::vector{ StringGenerator::cPlus, StringGenerator::cMinus, @@ -38,6 +42,9 @@ namespace dev { } const auto& front = item.front(); + + // TODO: + // _operations is redundant since there are const chars with operations within the same class for (const auto& op: _operations) { if (op == front) { return true; @@ -51,6 +58,8 @@ namespace dev { return false; } + // TODO: + // I bet this part could be simplified... std::istringstream iss(item); float f; iss >> std::noskipws >> f; // noskipws considers leading whitespace invalid diff --git a/string_generator.h b/string_generator.h index ba39df7..8cfc8d5 100644 --- a/string_generator.h +++ b/string_generator.h @@ -13,6 +13,8 @@ class StringGenerator { static bool isOperation(std::string item); static bool isOperand(std::string item); + //TODO: + // static const char cPlus = '+'; static const char cMinus = '-'; static const char cMult = '*'; diff --git a/test/project_test.cc b/test/project_test.cc index f7554fb..7485ed4 100644 --- a/test/project_test.cc +++ b/test/project_test.cc @@ -25,10 +25,10 @@ TEST_F(ProjectTest, Simple_Operations) { } TEST_F(ProjectTest, Simple_Operations_Float) { - ASSERT_EQ(15.2, project_.run("10.1 5.1 +")); - ASSERT_EQ(5, project_.run("10.1 5.1 -")); - ASSERT_EQ(51.51, project_.run("10.1 5.1 *")); - ASSERT_EQ(2.02, project_.run("10.1 5 /")); + ASSERT_NEAR(15.2, project_.run("10.1 5.1 +"), 0.01); + ASSERT_NEAR(5, project_.run("10.1 5.1 -"), 0.01); + ASSERT_NEAR(51.51, project_.run("10.1 5.1 *"), 0.01); + ASSERT_NEAR(2.02, project_.run("10.1 5 /"), 0.01); } TEST_F(ProjectTest, Simple_Operations_Exceptions) { @@ -43,5 +43,8 @@ TEST_F(ProjectTest, Simple_Operations_Complex) { EXPECT_EQ(7, project_.run("10 5 2 +")); } +//TODO: +// Increase coverage + } // namespace testing } // namespace dev From 5db1d398d0c6d8264a92d244c38ebe295c7b534c Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 12 Dec 2019 13:30:48 +0200 Subject: [PATCH 4/9] refactor --- fixed_queue.cc | 11 +++++- fixed_queue.h | 5 ++- iproject.h | 2 +- project.cc | 90 +++++++++++++++++---------------------------- project.h | 2 +- string_generator.cc | 53 ++++++++++++-------------- string_generator.h | 21 +++++------ 7 files changed, 81 insertions(+), 103 deletions(-) diff --git a/fixed_queue.cc b/fixed_queue.cc index 802f434..85ddff1 100644 --- a/fixed_queue.cc +++ b/fixed_queue.cc @@ -1,10 +1,19 @@ #include "fixed_queue.h" namespace dev { - void FixedSizeQueue::push(const float item){ + void FixedSizeQueue::push(const float& item){ while (_size <= this->size()){ this->pop(); } std::queue::push(item); } + + bool FixedSizeQueue::getFirst(float& item) { + if (this->empty()){ + return false; + } + item = this->front(); + this->pop(); + return true; + } } diff --git a/fixed_queue.h b/fixed_queue.h index 563c1a2..5559d1c 100644 --- a/fixed_queue.h +++ b/fixed_queue.h @@ -3,8 +3,9 @@ namespace dev { class FixedSizeQueue : public std::queue { public: - void push(const float item); + void push(const float& item); + bool getFirst(float& item); private: - const int _size = 2; + static constexpr int _size = 2; }; } diff --git a/iproject.h b/iproject.h index cc56ba3..794a16c 100644 --- a/iproject.h +++ b/iproject.h @@ -4,7 +4,7 @@ namespace dev{ class IProject { - virtual float run(std::string expression) = 0; + virtual float run(const std::string& expression) = 0; }; } diff --git a/project.cc b/project.cc index b26d5e2..8e533de 100644 --- a/project.cc +++ b/project.cc @@ -5,82 +5,60 @@ namespace dev { //TODO: // Think of alternative to exceptions -//TODO: -// Use const string -float Project::run(std::string expression) { +float Project::run(const std::string& expression) { auto sGenerator = StringGenerator(expression); - //TODO: - // Redundant check - if (sGenerator.empty()){ - return 0; - } + auto stuff = [this](std::string operation, float& result) { + float operand1; + float operand2; - float result = 0; - - auto stuff = [this](std::string operation) { - //TODO: - // Get rid of hardcode - if (2 != _queue.size()) { + if (!_queue.getFirst(operand1) || + ! _queue.getFirst(operand2)) { // UNDEFINED!!! - throw std::exception(); + return false; } - //TODO: - // Looks like front() should be redefined in FixedQueue - // to perform front() and pop() within a single call - float operand1 = _queue.front(); - _queue.pop(); - float operand2 = _queue.front(); - _queue.pop(); - - //TODO: - // Use switch - if (StringGenerator::cPlus == operation.front()) { - return operand1 + operand2; - } else if (StringGenerator::cMinus == operation.front()) { - return operand1 - operand2; - } else if (StringGenerator::cMult == operation.front()) { - return operand1 * operand2; - } else if (StringGenerator::cDiv == operation.front()) { - return operand1 / operand2; - } else { + const char& cOperation = operation.front(); + switch (cOperation) { + case StringGenerator::cPlus: + result = operand1 + operand2; + break; + case StringGenerator::cMinus: + result = operand1 - operand2; + break; + case StringGenerator::cMult: + result = operand1 * operand2; + break; + case StringGenerator::cDiv: + result = operand1 / operand2; + break; + default: // UNREACHABLE!!! - throw std::exception(); + return false; } + return true; }; + std::string item; while(true) { - auto item = sGenerator.next(); - - if (StringGenerator::isOperand(item)) { - //TODO: - // Get rid of duplicated code (see string_generator.cc) - std::istringstream iss(item); - float fItem; - iss >> std::noskipws >> fItem; - _queue.push(fItem); - - continue; + if (!sGenerator.next(item)) { + break; } - if (StringGenerator::isOperation(item)) { - float result = stuff(item); - _queue.push(result); + float operation_result = 0; + if (StringGenerator::getOperand(item, operation_result) || + (StringGenerator::isOperation(item) && stuff(item, operation_result))) { + _queue.push(operation_result); continue; } - if (0 == item.length()) { - break; - } - // UNREACHABLE!!!" throw std::exception(); } - if (!_queue.empty()) { - result = _queue.front(); - } + float result = 0; + _queue.getFirst(result); + return result; } } // namespace dev diff --git a/project.h b/project.h index f339fa0..1261388 100644 --- a/project.h +++ b/project.h @@ -12,7 +12,7 @@ namespace dev { class Project : public IProject { // IProject interface public: - float run(std::string expression = ""); + float run(const std::string& expression = ""); private: FixedSizeQueue _queue; diff --git a/string_generator.cc b/string_generator.cc index 036b772..dc7babf 100644 --- a/string_generator.cc +++ b/string_generator.cc @@ -1,27 +1,15 @@ #include "string_generator.h" namespace dev { - StringGenerator::StringGenerator(std::string basic) + StringGenerator::StringGenerator(const std::string& basic) : _basic(basic) {} - //TODO: - // Use enum instead (will simplify usage outside): - // 1) public method for convertion of char to enum value - // 2) Move these constants to private - const std::vector StringGenerator::_operations = std::vector{ - StringGenerator::cPlus, - StringGenerator::cMinus, - StringGenerator::cMult, - StringGenerator::cDiv - }; - bool StringGenerator::empty() { - return 0 == _basic.length(); + return _basic.empty(); } - std::string StringGenerator::next() { - std::string result = ""; - + bool StringGenerator::next(std::string& result) { + result = ""; while(true) { if (_basic.empty()) { break; @@ -31,38 +19,43 @@ namespace dev { if (' ' == item) { break; } - result+=item; + result += item; } - return result; + return !result.empty(); } - bool StringGenerator::isOperation(std::string item) { + bool StringGenerator::isOperation(const std::string& item) { if (item.length() > 1) { return false; } const auto& front = item.front(); - // TODO: - // _operations is redundant since there are const chars with operations within the same class - for (const auto& op: _operations) { - if (op == front) { - return true; - } + switch (front) { + case StringGenerator::cPlus: + case StringGenerator::cMinus: + case StringGenerator::cDiv: + case StringGenerator::cMult: + return true; + default: + return false; } - return false; } - bool StringGenerator::isOperand(std::string item) { - if (1 > item.length()) { + bool StringGenerator::isOperand(const std::string& item) { + float result; + return getOperand(item, result); + } + + bool StringGenerator::getOperand(const std::string& item, float& result) { + if (item.empty()) { return false; } // TODO: // I bet this part could be simplified... std::istringstream iss(item); - float f; - iss >> std::noskipws >> f; // noskipws considers leading whitespace invalid + iss >> std::noskipws >> result; // noskipws considers leading whitespace invalid // Check the entire string was consumed and if either failbit or badbit is set return iss.eof() && !iss.fail(); } diff --git a/string_generator.h b/string_generator.h index 8cfc8d5..4740aa3 100644 --- a/string_generator.h +++ b/string_generator.h @@ -3,24 +3,21 @@ #include namespace dev { - class StringGenerator { public: - StringGenerator(std::string basic); - std::string next(); + StringGenerator(const std::string& basic); + bool next(std::string& result); bool empty(); - static bool isOperation(std::string item); - static bool isOperand(std::string item); + static bool isOperation(const std::string& item); + static bool isOperand(const std::string& item); + static bool getOperand(const std::string& item, float& result); - //TODO: - // - static const char cPlus = '+'; - static const char cMinus = '-'; - static const char cMult = '*'; - static const char cDiv = '/'; + static constexpr char cPlus = '+'; + static constexpr char cMinus = '-'; + static constexpr char cMult = '*'; + static constexpr char cDiv = '/'; private: std::string _basic; - static const std::vector _operations; }; } From c10f84779cebe6a4d79d6f0c3320ea7765a6e50d Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 12 Dec 2019 13:38:05 +0200 Subject: [PATCH 5/9] fixup! refactor --- fixed_queue.cc | 5 +++-- project.cc | 20 +++++++------------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/fixed_queue.cc b/fixed_queue.cc index 85ddff1..86595a5 100644 --- a/fixed_queue.cc +++ b/fixed_queue.cc @@ -8,11 +8,12 @@ namespace dev { std::queue::push(item); } - bool FixedSizeQueue::getFirst(float& item) { + bool FixedSizeQueue::getFirst(float& result) { + result = 0; if (this->empty()){ return false; } - item = this->front(); + result = this->front(); this->pop(); return true; } diff --git a/project.cc b/project.cc index 8e533de..76567b8 100644 --- a/project.cc +++ b/project.cc @@ -6,8 +6,6 @@ namespace dev { // Think of alternative to exceptions float Project::run(const std::string& expression) { - auto sGenerator = StringGenerator(expression); - auto stuff = [this](std::string operation, float& result) { float operand1; float operand2; @@ -39,16 +37,13 @@ float Project::run(const std::string& expression) { return true; }; + auto sGenerator = StringGenerator(expression); + float result = 0; std::string item; - while(true) { - if (!sGenerator.next(item)) { - break; - } - - float operation_result = 0; - if (StringGenerator::getOperand(item, operation_result) || - (StringGenerator::isOperation(item) && stuff(item, operation_result))) { - _queue.push(operation_result); + while(sGenerator.next(item)) { + if (StringGenerator::getOperand(item, result) || + (StringGenerator::isOperation(item) && stuff(item, result))) { + _queue.push(result); continue; } @@ -56,9 +51,8 @@ float Project::run(const std::string& expression) { throw std::exception(); } - float result = 0; - _queue.getFirst(result); + _queue.getFirst(result); return result; } } // namespace dev From bb68e660dd47023910ec85357d26b76db03b03c8 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 12 Dec 2019 13:55:40 +0200 Subject: [PATCH 6/9] fixup! refactor --- project.cc | 2 +- string_generator.cc | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/project.cc b/project.cc index 76567b8..e5072e8 100644 --- a/project.cc +++ b/project.cc @@ -6,7 +6,7 @@ namespace dev { // Think of alternative to exceptions float Project::run(const std::string& expression) { - auto stuff = [this](std::string operation, float& result) { + auto stuff = [this](const std::string& operation, float& result) { float operand1; float operand2; diff --git a/string_generator.cc b/string_generator.cc index dc7babf..8db5d8b 100644 --- a/string_generator.cc +++ b/string_generator.cc @@ -10,10 +10,7 @@ namespace dev { bool StringGenerator::next(std::string& result) { result = ""; - while(true) { - if (_basic.empty()) { - break; - } + while(!empty()) { auto item = _basic.front(); _basic.erase(0,1); if (' ' == item) { From adacac5385410b2e0b0e11b6d77a7fdc3d0417d3 Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 17 Dec 2019 13:57:24 +0200 Subject: [PATCH 7/9] msg --- CMakeLists.txt | 5 ++- fixed_queue.h => include/fixed_queue.h | 0 iproject.h => include/iproject.h | 0 include/istring_generator.h | 15 +++++++++ project.h => include/project.h | 1 - .../string_generator.h | 10 +++--- fixed_queue.cc => src/fixed_queue.cc | 0 project.cc => src/project.cc | 1 + .../string_generator.cc | 2 ++ test/CMakeLists.txt | 4 +++ test/fixed_size_queue_test.cc | 33 +++++++++++++++++++ 11 files changed, 63 insertions(+), 8 deletions(-) rename fixed_queue.h => include/fixed_queue.h (100%) rename iproject.h => include/iproject.h (100%) create mode 100644 include/istring_generator.h rename project.h => include/project.h (91%) rename string_generator.h => include/string_generator.h (74%) rename fixed_queue.cc => src/fixed_queue.cc (100%) rename project.cc => src/project.cc (97%) rename string_generator.cc => src/string_generator.cc (97%) create mode 100644 test/fixed_size_queue_test.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index d6d0345..dbe2613 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,10 @@ project(dummy_cmake_project) set(CMAKE_CXX_STANDARD 14) list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) -set(SOURCES project.cc fixed_queue.cc string_generator.cc) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + +file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cc) + add_library(ProjectLib ${SOURCES}) add_executable(project main.cc) diff --git a/fixed_queue.h b/include/fixed_queue.h similarity index 100% rename from fixed_queue.h rename to include/fixed_queue.h diff --git a/iproject.h b/include/iproject.h similarity index 100% rename from iproject.h rename to include/iproject.h diff --git a/include/istring_generator.h b/include/istring_generator.h new file mode 100644 index 0000000..a339448 --- /dev/null +++ b/include/istring_generator.h @@ -0,0 +1,15 @@ +#include "string" + +#ifndef ISTRINGGENERATOR_H +#define ISTRINGGENERATOR_H + +namespace dev { +class IStringGenerator { +public: + virtual bool next(std::string& result) = 0; + virtual bool empty() = 0; +}; +} + +#endif // ISTRINGGENERATOR_H + diff --git a/project.h b/include/project.h similarity index 91% rename from project.h rename to include/project.h index 1261388..502e3c4 100644 --- a/project.h +++ b/include/project.h @@ -1,7 +1,6 @@ #pragma once #include "iproject.h" #include "fixed_queue.h" -#include "string_generator.h" #include #include diff --git a/string_generator.h b/include/string_generator.h similarity index 74% rename from string_generator.h rename to include/string_generator.h index 4740aa3..fa7f2e5 100644 --- a/string_generator.h +++ b/include/string_generator.h @@ -1,13 +1,11 @@ -#include "string" -#include "vector" -#include +#include "istring_generator.h" namespace dev { -class StringGenerator { +class StringGenerator : public IStringGenerator{ public: StringGenerator(const std::string& basic); - bool next(std::string& result); - bool empty(); + bool next(std::string& result) override; + bool empty() override; static bool isOperation(const std::string& item); static bool isOperand(const std::string& item); diff --git a/fixed_queue.cc b/src/fixed_queue.cc similarity index 100% rename from fixed_queue.cc rename to src/fixed_queue.cc diff --git a/project.cc b/src/project.cc similarity index 97% rename from project.cc rename to src/project.cc index e5072e8..0356c0d 100644 --- a/project.cc +++ b/src/project.cc @@ -1,4 +1,5 @@ #include "project.h" +#include "string_generator.h" namespace dev { diff --git a/string_generator.cc b/src/string_generator.cc similarity index 97% rename from string_generator.cc rename to src/string_generator.cc index 8db5d8b..f5c9190 100644 --- a/string_generator.cc +++ b/src/string_generator.cc @@ -1,3 +1,5 @@ +#include +#include #include "string_generator.h" namespace dev { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8d6190d..cb2c9eb 100755 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -3,5 +3,9 @@ include_directories (${CMAKE_SOURCE_DIR}) include(AddGoogleTest) add_executable (ProjectTest project_test.cc) +add_executable (FixedQueueTest fixed_size_queue_test.cc) + add_gtest(ProjectTest) +add_gtest(FixedQueueTest) + target_link_libraries(ProjectTest PUBLIC ProjectLib) diff --git a/test/fixed_size_queue_test.cc b/test/fixed_size_queue_test.cc new file mode 100644 index 0000000..9e61dcc --- /dev/null +++ b/test/fixed_size_queue_test.cc @@ -0,0 +1,33 @@ + +#include "fixed_queue.h" +#include +#include +namespace dev { +namespace testing { + +class FixedSizeQueueTest : public ::testing::Test { + public: + void SetUp() override { + FixedSizeQueue tmp_queue; + std::swap(queue_, tmp_queue); + } + void TearDown() override {} + dev::FixedSizeQueue queue_; +}; + +TEST_F(FixedSizeQueueTest, Push) { + float item = 5.1; + EXPECT_NO_THROW(queue.push(item)); +} + +TEST_F(FixedSizeQueueTest, GetFirst) { + float item = 5.1; + queue_.push(item); + EXPECT_TRUE(queue_.getFirst()); +} + +//TODO: +// Increase coverage + +} // namespace testing +} // namespace dev From 9b4297476f2b9be79527d5dc4550a21facfa93d8 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 18 Dec 2019 14:06:44 +0200 Subject: [PATCH 8/9] new kek --- include/fixed_queue.h | 2 +- include/istring_generator.h | 15 --------------- include/string_generator.h | 8 +++----- src/project.cc | 18 ++++++++++-------- test/CMakeLists.txt | 1 + test/fixed_size_queue_test.cc | 33 ++++++++++++++++++++++++++------- test/project_test.cc | 8 ++++---- 7 files changed, 45 insertions(+), 40 deletions(-) delete mode 100644 include/istring_generator.h diff --git a/include/fixed_queue.h b/include/fixed_queue.h index 5559d1c..e8b3344 100644 --- a/include/fixed_queue.h +++ b/include/fixed_queue.h @@ -1,4 +1,4 @@ -#include "queue" +#include namespace dev { class FixedSizeQueue : public std::queue { diff --git a/include/istring_generator.h b/include/istring_generator.h deleted file mode 100644 index a339448..0000000 --- a/include/istring_generator.h +++ /dev/null @@ -1,15 +0,0 @@ -#include "string" - -#ifndef ISTRINGGENERATOR_H -#define ISTRINGGENERATOR_H - -namespace dev { -class IStringGenerator { -public: - virtual bool next(std::string& result) = 0; - virtual bool empty() = 0; -}; -} - -#endif // ISTRINGGENERATOR_H - diff --git a/include/string_generator.h b/include/string_generator.h index fa7f2e5..9f349f0 100644 --- a/include/string_generator.h +++ b/include/string_generator.h @@ -1,11 +1,9 @@ -#include "istring_generator.h" - namespace dev { -class StringGenerator : public IStringGenerator{ +class StringGenerator{ public: StringGenerator(const std::string& basic); - bool next(std::string& result) override; - bool empty() override; + bool next(std::string& result); + bool empty(); static bool isOperation(const std::string& item); static bool isOperand(const std::string& item); diff --git a/src/project.cc b/src/project.cc index 0356c0d..61762d5 100644 --- a/src/project.cc +++ b/src/project.cc @@ -3,9 +3,6 @@ namespace dev { -//TODO: -// Think of alternative to exceptions - float Project::run(const std::string& expression) { auto stuff = [this](const std::string& operation, float& result) { float operand1; @@ -14,7 +11,7 @@ float Project::run(const std::string& expression) { if (!_queue.getFirst(operand1) || ! _queue.getFirst(operand2)) { // UNDEFINED!!! - return false; + throw std::runtime_error("Single operand! Undefined behaviour!"); } const char& cOperation = operation.front(); @@ -33,7 +30,7 @@ float Project::run(const std::string& expression) { break; default: // UNREACHABLE!!! - return false; + throw std::runtime_error("Undefined operation!"); } return true; }; @@ -42,14 +39,19 @@ float Project::run(const std::string& expression) { float result = 0; std::string item; while(sGenerator.next(item)) { - if (StringGenerator::getOperand(item, result) || - (StringGenerator::isOperation(item) && stuff(item, result))) { + if (StringGenerator::isOperation(item)) { + stuff(item, result); + _queue.push(result); + continue; + } + + if (StringGenerator::getOperand(item, result)) { _queue.push(result); continue; } // UNREACHABLE!!!" - throw std::exception(); + throw std::runtime_error("Unreachable!"); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cb2c9eb..1e38328 100755 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -9,3 +9,4 @@ add_gtest(ProjectTest) add_gtest(FixedQueueTest) target_link_libraries(ProjectTest PUBLIC ProjectLib) +target_link_libraries(FixedQueueTest PUBLIC ProjectLib) diff --git a/test/fixed_size_queue_test.cc b/test/fixed_size_queue_test.cc index 9e61dcc..a50b060 100644 --- a/test/fixed_size_queue_test.cc +++ b/test/fixed_size_queue_test.cc @@ -2,6 +2,7 @@ #include "fixed_queue.h" #include #include + namespace dev { namespace testing { @@ -12,22 +13,40 @@ class FixedSizeQueueTest : public ::testing::Test { std::swap(queue_, tmp_queue); } void TearDown() override {} - dev::FixedSizeQueue queue_; + + FixedSizeQueue queue_; }; TEST_F(FixedSizeQueueTest, Push) { float item = 5.1; - EXPECT_NO_THROW(queue.push(item)); + EXPECT_NO_THROW(queue_.push(item)); } TEST_F(FixedSizeQueueTest, GetFirst) { - float item = 5.1; - queue_.push(item); - EXPECT_TRUE(queue_.getFirst()); + float item_1 = 5.1; + float item_2 = 3.2; + queue_.push(item_1); + queue_.push(item_2); + + float result = 0; + ASSERT_TRUE(queue_.getFirst(result)); + + EXPECT_EQ(result, item_1); } -//TODO: -// Increase coverage +TEST_F(FixedSizeQueueTest, PushThreeItems) { + float item_1 = 5.1; + float item_2 = 3.2; + float item_3 = 1.1; + queue_.push(item_1); + queue_.push(item_2); + queue_.push(item_3); + + float result = 0; + ASSERT_TRUE(queue_.getFirst(result)); + + EXPECT_EQ(result, item_2); +} } // namespace testing } // namespace dev diff --git a/test/project_test.cc b/test/project_test.cc index 7485ed4..444daf9 100644 --- a/test/project_test.cc +++ b/test/project_test.cc @@ -32,10 +32,10 @@ TEST_F(ProjectTest, Simple_Operations_Float) { } TEST_F(ProjectTest, Simple_Operations_Exceptions) { - ASSERT_THROW(project_.run("a"), std::exception); - ASSERT_THROW(project_.run("a a"), std::exception); - ASSERT_THROW(project_.run("+"), std::exception); - ASSERT_THROW(project_.run("10 +"), std::exception); + ASSERT_THROW(project_.run("a"), std::runtime_error); + ASSERT_THROW(project_.run("a a"), std::runtime_error); + ASSERT_THROW(project_.run("+"), std::runtime_error); + ASSERT_THROW(project_.run("10 +"), std::runtime_error); } TEST_F(ProjectTest, Simple_Operations_Complex) { From 32fa3349acfb7c1f363c61ee7d3fada44bc5bcd1 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 19 Dec 2019 13:04:42 +0200 Subject: [PATCH 9/9] review --- src/fixed_queue.cc | 3 ++- src/project.cc | 7 +++++-- src/string_generator.cc | 5 +++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/fixed_queue.cc b/src/fixed_queue.cc index 86595a5..edf2481 100644 --- a/src/fixed_queue.cc +++ b/src/fixed_queue.cc @@ -8,8 +8,9 @@ namespace dev { std::queue::push(item); } + // Not obvious naming bool FixedSizeQueue::getFirst(float& result) { - result = 0; + result = 0; // result will be changed it bad case (if stack is empty) if (this->empty()){ return false; } diff --git a/src/project.cc b/src/project.cc index 61762d5..401ccec 100644 --- a/src/project.cc +++ b/src/project.cc @@ -8,7 +8,7 @@ float Project::run(const std::string& expression) { float operand1; float operand2; - if (!_queue.getFirst(operand1) || + if (!_queue.getFirst(operand1) || //getFirst change stack. but name of function does not say about it ! _queue.getFirst(operand2)) { // UNDEFINED!!! throw std::runtime_error("Single operand! Undefined behaviour!"); @@ -26,7 +26,7 @@ float Project::run(const std::string& expression) { result = operand1 * operand2; break; case StringGenerator::cDiv: - result = operand1 / operand2; + result = operand1 / operand2; // I can write 1 / 0 break; default: // UNREACHABLE!!! @@ -36,9 +36,12 @@ float Project::run(const std::string& expression) { }; auto sGenerator = StringGenerator(expression); + + // Think of case, when this result will be returned in case of wrong line float result = 0; std::string item; while(sGenerator.next(item)) { + // Not obvious loop if (StringGenerator::isOperation(item)) { stuff(item, result); _queue.push(result); diff --git a/src/string_generator.cc b/src/string_generator.cc index f5c9190..5bf6b08 100644 --- a/src/string_generator.cc +++ b/src/string_generator.cc @@ -12,9 +12,14 @@ namespace dev { bool StringGenerator::next(std::string& result) { result = ""; + //not obvious loop! while(!empty()) { + + // get front and pop!!! auto item = _basic.front(); _basic.erase(0,1); + + // how about const? if (' ' == item) { break; }