Skip to content
Snippets Groups Projects
main.cpp 2 KiB
Newer Older
Florian Steinkamp's avatar
Florian Steinkamp committed
#include <iostream>
#include <optional>
#include <stack>
#include <stdexcept>
#include <climits>
#include <unordered_map>
#include <iterator>

Steffen's avatar
Steffen committed
int add(const int a, const int b) {
  return a + b;
Steffen's avatar
Steffen committed
int subtract(const int a, const int b) {
  return b - a;
Steffen's avatar
Steffen committed
int multiply(const int a, const int b) {
  return a * b;
 * Divides integer b from integer a, throwing an exception when b is zero.
 * Throws an std::invalid_argument exceptions if invalid parameters are provided.
Steffen's avatar
Steffen committed
int divide(const int a, const int b) {
Roman Siebert's avatar
Roman Siebert committed
  if (b == 0) {
    throw std::invalid_argument("Tried to divide by 0.");
  }
  return a / b;
using binary_operator = decltype(&add);

Florian Steinkamp's avatar
Florian Steinkamp committed
int evaluate(const std::string &s) {
Steffen's avatar
Steffen committed
  std::stack<int> stack;
  std::unordered_map<char, binary_operator> map {
    {'+', add},
	{'-', subtract},
	{'*', multiply},
	{'/', divide}
  };

  decltype(map)::iterator iter;
Roman Siebert's avatar
Roman Siebert committed
  for (char c : s) {
    if (std::isdigit(c)) {
      stack.push(c - '0');
    } else if (stack.size() >= 2 ) {
Roman Siebert's avatar
Roman Siebert committed
        iter = map.find(c);
        if (iter != map.end()) {
Steffen's avatar
Steffen committed
          auto a = stack.top();
Roman Siebert's avatar
Roman Siebert committed
          stack.pop();
Steffen's avatar
Steffen committed
          auto b = stack.top();
Roman Siebert's avatar
Roman Siebert committed
          stack.pop();
          stack.push(iter->second(b, a));
        } else {
          throw std::invalid_argument("Invalid character found.");
        }
    } else {
      throw std::invalid_argument("Invalid number of digits.");
Roman Siebert's avatar
Roman Siebert committed
    }
  }
  if (stack.size() > 1 || stack.size() == 0) {
    throw std::invalid_argument("Invalid input.");
  }
  return stack.top();
Florian Steinkamp's avatar
Florian Steinkamp committed
}

int main() {
  std::string user_input;
  std::cin >> user_input;

  if (user_input.empty()) {
    std::cout << "Empty input\n";
    return 1;
Florian Steinkamp's avatar
Florian Steinkamp committed

  std::cout << "User input is \"" << user_input << "\"\n";

Roman Siebert's avatar
Roman Siebert committed
  int result = INT_MAX;

  try {
    result = evaluate(user_input);
  } catch (const std::exception &e) {
    std::cout << e.what();
  }
Steffen's avatar
Steffen committed

Roman Siebert's avatar
Roman Siebert committed
  if (result != INT_MAX) {
Simon Ebbers's avatar
Simon Ebbers committed
    std::cout << "Result is: " << result << '\n';
Roman Siebert's avatar
Roman Siebert committed
  }
Florian Steinkamp's avatar
Florian Steinkamp committed
}