Skip to content

Commit 28b3c0b

Browse files
committed
initial calculator
1 parent 1640617 commit 28b3c0b

File tree

6 files changed

+101
-1
lines changed

6 files changed

+101
-1
lines changed

week-15/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
set(DIRS task-12-14 task-12-15)
1+
set(DIRS task-12-14 task-12-15 task-12-20)
22
foreach(DIR ${DIRS})
33
add_subdirectory(${DIR})
44
endforeach()

week-15/task-12-20/CMakeLists.txt

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
include_directories(include)
2+
3+
add_subdirectory(test)
4+
5+
add_executable(ae main.cpp)
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#pragma once
2+
3+
#include <stack>
4+
#include <sstream>
5+
6+
bool is_operator(char c) {
7+
return c == '+' || c == '-' || c == '*' || c == '/';
8+
}
9+
10+
int calculate(const std::string& str) {
11+
std::stack<int> stack;
12+
for (auto it = std::cbegin(str); it != std::cend(str);) {
13+
if (static_cast<bool>(std::isspace(*it))) {
14+
while (it != std::cend(str) && static_cast<bool>(std::isspace(*it))) { ++it; }
15+
} else if (static_cast<bool>(std::isdigit(*it))) {
16+
std::istringstream iss(std::string(it, std::cend(str)));
17+
int val;
18+
iss >> val;
19+
stack.push(val);
20+
std::advance(it, iss.tellg());
21+
} else if (is_operator(*it)) {
22+
const int b = stack.top(); stack.pop();
23+
const int a = stack.top(); stack.pop();
24+
switch (*it) {
25+
case '+':
26+
stack.push(a + b);
27+
break;
28+
case '-':
29+
stack.push(a - b);
30+
break;
31+
case '*':
32+
stack.push(a * b);
33+
break;
34+
case '/':
35+
stack.push(a / b);
36+
break;
37+
default:
38+
throw std::runtime_error("unexpected operator");
39+
}
40+
++it;
41+
} else {
42+
throw std::runtime_error("unexpected symbol");
43+
}
44+
}
45+
return stack.top();
46+
}

week-15/task-12-20/main.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include "calculator.hpp"
2+
3+
int main() {
4+
calculate("3 4 +");
5+
}
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cpp_test(test-12-20.cpp)
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include "gtest/gtest.h"
2+
#include "calculator.hpp"
3+
4+
TEST(RPNCalculatorTest, BasicOperations) {
5+
EXPECT_EQ(calculate("3 4 +"), 7); // 3 + 4
6+
EXPECT_EQ(calculate("5 2 -"), 3); // 5 - 2
7+
EXPECT_EQ(calculate("2 3 *"), 6); // 2 * 3
8+
EXPECT_EQ(calculate("6 2 /"), 3); // 6 / 2
9+
}
10+
11+
TEST(RPNCalculatorTest, ComplexExpressions) {
12+
EXPECT_EQ(calculate("3 4 2 * +"), 11); // 3 + (4 * 2)
13+
EXPECT_EQ(calculate("5 1 2 + 4 * + 3 -"), 14); // 5 + ((1+2)*4) - 3
14+
EXPECT_EQ(calculate("4 2 5 * + 1 3 - /"), -7); // (4 + 2*5) / (1-3)
15+
}
16+
17+
TEST(RPNCalculatorTest, EdgeCases) {
18+
EXPECT_EQ(calculate("0 5 +"), 5); // 0 + 5
19+
EXPECT_EQ(calculate("1 1 -"), 0); // 1 - 1
20+
EXPECT_EQ(calculate("999 1 +"), 1000); // large number
21+
EXPECT_EQ(calculate("-5 3 +"), -2); // negative number
22+
}
23+
24+
TEST(RPNCalculatorTest, InvalidInput) {
25+
EXPECT_THROW(calculate(""), std::invalid_argument); // empty
26+
EXPECT_THROW(calculate("3 +"), std::invalid_argument); // missing operand
27+
EXPECT_THROW(calculate("3 4 + -"), std::invalid_argument); // extra operator
28+
EXPECT_THROW(calculate("a b +"), std::invalid_argument); // non-numbers
29+
EXPECT_THROW(calculate("3 0 /"), std::runtime_error); // division by zero
30+
}
31+
32+
TEST(RPNCalculatorTest, WhitespaceHandling) {
33+
EXPECT_EQ(calculate(" 3 4 + "), 7); // extra spaces
34+
EXPECT_EQ(calculate("3\n4\t+"), 7); // different whitespace
35+
EXPECT_EQ(calculate("3 4 + "), 7); // trailing space
36+
}
37+
38+
TEST(RPNCalculatorTest, MultiDigitNumbers) {
39+
EXPECT_EQ(calculate("10 20 +"), 30); // 10 + 20
40+
EXPECT_EQ(calculate("100 50 -"), 50); // 100 - 50
41+
EXPECT_EQ(calculate("12 34 *"), 408); // 12 * 34
42+
EXPECT_EQ(calculate("100 5 /"), 20); // 100 / 5
43+
}

0 commit comments

Comments
 (0)