Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Polish calculator customs #6

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .vimrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
function! Build()
silent :!clear
silent :!mkdir -p build
silent :!cd build && cmake .. && make
:!echo "Done"
redraw!
endfunction
command! Build :call Build()

function! Clean()
silent :!clear
silent :!cd build && rm -frv *
:!echo "Done"
redraw!
endfunction
command! Clean :call Clean()

function! Run()
silent :!clear
silent :!cd build && ./project
:!echo "Done"
redraw!
endfunction
command! Run :call Run()

function! Test()
silent :!clear
silent :!cd build/test && ./ProjectTest;
silent :!cd build/test && ./CalculatorTest;
silent :!cd build/test && ./ParserTest;
:!echo "Done"
redraw!
endfunction
command! Test :call Test()
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
include_directories("Calculator")
include_directories("Parser")
include_directories("types")
set(SOURCES project.cc Calculator/Calculator.cc Parser/Parser.cc)
add_library(ProjectLib ${SOURCES})

add_executable(project main.cc)
Expand Down
46 changes: 46 additions & 0 deletions Calculator/Calculator.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "Calculator.h"
#include <iostream>

namespace dev {
Calculator::Calculator(types::NumbersStackPtr numbers,
types::OperatorsListPtr operators)
: numbers_(std::move(numbers))
, operators_(std::move(operators)) { }

float Calculator::calculate() {

if (operators_->size() != numbers_->size() - 1) {
return types::kError;
}

for(const auto& math_operator : *operators_) {
auto left = numbers_->pop();
auto right = numbers_->pop();
switch(*math_operator.begin()) {
case types::Operators::ADD: numbers_->push(add(left,right)); break;
case types::Operators::DEC: numbers_->push(dec(left,right)); break;
case types::Operators::DIV: numbers_->push(div(left,right)); break;
case types::Operators::MUL: numbers_->push(mul(left,right)); break;
default:break;
}
}
return numbers_->top();
}

float Calculator::add(float first, float second) {
return first + second;
}

float Calculator::div(float first, float second) {
return second ? (first / second) : types::kError;
}

float Calculator::dec(float first, float second) {
return first - second;
}

float Calculator::mul(float first, float second) {
return first * second;
}

}
31 changes: 31 additions & 0 deletions Calculator/Calculator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef CALCULATOR_CALCULATOR_H
#define CALCULATOR_CALCULATOR_H

#include "ICalculator.h"
#include "CustomStack.h"
#include "utils.h"

#include <vector>
#include <string>
#include <limits>
#include <memory>

namespace dev {

class Calculator : public ICalculator {
public:
Calculator(types::NumbersStackPtr numbers, types::OperatorsListPtr operators);
float calculate() override;

private:
float add(float first, float second);
float div(float first, float second);
float dec(float first, float second);
float mul(float first, float second);

types::NumbersStackPtr numbers_;
types::OperatorsListPtr operators_;
};
}

#endif
12 changes: 12 additions & 0 deletions Calculator/ICalculator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef CALCULATOR_ICALCULATOR_H
#define CALCULATOR_ICALCULATOR_H

namespace dev {

class ICalculator {
public:
virtual float calculate() = 0;
};

}
#endif
14 changes: 14 additions & 0 deletions Parser/IParser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef PARSER_IPARSER_H
#define PARSER_IPARSER_H

#include <string>

namespace dev {

class IParser {
public:
virtual bool parse(const std::string& data) = 0;
};

}
#endif
70 changes: 70 additions & 0 deletions Parser/Parser.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include "Parser.h"

namespace dev {
Parser::Parser()
: numbers_(new types::NumbersStack()),
operators_(new types::OperatorsList()) {
}

bool Parser::parse(const std::string& data) {
if (data.empty()) {
return false;
}

const auto& splitted_data = split(data);
for (const auto& user_data : splitted_data) {

// Append operators list
std::string math_operator = string_matches_operator(user_data);
if (!math_operator.empty()) {
operators_->push_back(math_operator);
continue;
}

// Append numbers list
try {
float number = std::stof(user_data);
numbers_->push(number);
} catch (const std::exception& exception) {
std::cerr << "cannot convert "<< user_data << " to number!" << std::endl;
}
}

if (operators_->size() != numbers_->size() - 1) {
return false;
}

return true;
}

std::string
Parser::string_matches_operator(const std::string& possible_operator) const {
if (possible_operator != "*" &&
possible_operator != "+" &&
possible_operator != "-" &&
possible_operator != "/") {
return "";
}

return possible_operator;
}

std::vector<std::string> Parser::split(const std::string& data) const {
std::istringstream data_stream(data);
std::string buffer;
std::vector<std::string> result;
while (std::getline(data_stream, buffer, ' ')) {
result.push_back(buffer);
}
return result;
}

types::NumbersStackPtr Parser::get_numbers() {
return std::move(numbers_);
}

types::OperatorsListPtr Parser::get_operators() {
return std::move(operators_);
}

}
38 changes: 38 additions & 0 deletions Parser/Parser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#ifndef PARSER_PARSER_H
#define PARSER_PARSER_H

#include "IParser.h"
#include "CustomStack.h"
#include "utils.h"

#include <vector>
#include <memory>
#include <string>
#include <limits>
#include <iostream>
#include <sstream>
#include <exception>

namespace dev {

using namespace types;

class Parser : public IParser {
public:
Parser();
bool parse(const std::string& data) override;

types::NumbersStackPtr get_numbers();
types::OperatorsListPtr get_operators();

private:
std::string
string_matches_operator(const std::string& possible_operator) const;
std::vector<std::string>
split(const std::string&) const;
types::NumbersStackPtr numbers_;
types::OperatorsListPtr operators_;
};
}

#endif
3 changes: 2 additions & 1 deletion iproject.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#pragma once
#include <string>

namespace dev{

class IProject {
virtual int run() = 0;
virtual float run(const std::string& user_input) = 0;
};

}
25 changes: 25 additions & 0 deletions main.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,30 @@
#include "project.h"
#include <memory>


namespace {
const int kUserInputLimit = 1000;
}

//TODO: Maybe add IO handler ??
std::string handle_input() {
char user_input[kUserInputLimit];
std::cout << "Input expression -> ";
std::cin.getline(user_input, sizeof(user_input));
return std::string(user_input);
}

void handle_output(float result) {
if (result == std::numeric_limits<float>::min()) {
std::cout << "Error occured while calculating!" << std::endl;
} else {
std::cout << (float)result << std::endl;
}
}

int main() {
std::unique_ptr<dev::Project> polish_calculator(new dev::Project);
float result = polish_calculator->run(handle_input());
handle_output(result);
return 0;
}
20 changes: 18 additions & 2 deletions project.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,23 @@

namespace dev {

int Project::run() {
return 0;
namespace {
const auto kError = std::numeric_limits<float>::min();
}

Project::Project() {
}

float Project::run(const std::string& user_input) {
parser_.reset(new Parser());
const bool parsing_successful = parser_->parse(user_input);
if (!parsing_successful) {
return kError;
}

calculator_.reset(new Calculator(parser_->get_numbers(),
parser_->get_operators()));
return calculator_->calculate();
}

} // namespace dev
18 changes: 16 additions & 2 deletions project.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
#pragma once
#include "iproject.h"
#include "Calculator/Calculator.h"
#include "Parser/Parser.h"
#include <iostream>
#include <sstream>
#include <vector>
#include <exception>
#include <limits>
#include <stack>
#include <memory>
#include "CustomStack.h"

namespace dev {

class Project : public IProject {
// IProject interface
public:
int run();
Project();
float run(const std::string& user_input);

private:
std::unique_ptr<Calculator> calculator_;
std::unique_ptr<Parser> parser_;
};
} // namespace dev
6 changes: 6 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,11 @@ include_directories (${CMAKE_SOURCE_DIR})
include(AddGoogleTest)

add_executable (ProjectTest project_test.cc)
add_executable (CalculatorTest calculator_test.cc)
add_executable (ParserTest parser_test.cc)
add_gtest(ProjectTest)
add_gtest(CalculatorTest)
add_gtest(ParserTest)
target_link_libraries(ProjectTest PUBLIC ProjectLib)
target_link_libraries(CalculatorTest PUBLIC ProjectLib)
target_link_libraries(ParserTest PUBLIC ProjectLib)
Loading