# Polish Notation in C++

This is my homemade Polish Notation implementation in C++.

I need a review for it to improve it and improve my coding skill. I also will put this implementation on my GitHub account

//======================================================
// Author      : Omar_Hafez
// Created     : 28 July 2022 (Thursday)  6:10:44 AM
//======================================================

#include <math.h>

#include <iostream>
#include <stack>
#include <vector>

class PolishNotation {
private:
std::string operations[5] = {"+", "-", "*", "/", "^"};
bool isDigit(char &ch) const { return ch >= '0' && ch <= '9'; }

bool isOperation(std::string str) const {
for (std::string x : operations) {
if (str == x) return 1;
}
return 0;
}

bool isNumber(std::string str) const {
bool floatingPoint = 0;
if (str.length() == 1) {
return isDigit(str[0]);
}
for (int i = (str[0] == '-'); i < str.length(); i++) {
if (!floatingPoint && str[i] == '.') {
floatingPoint = 1;
continue;
}
if (!isDigit(str[i])) return 0;
}
return 1;
}

bool isHigher(std::string a, std::string b) const {
int cnt1 = 0, cnt2 = 0;
cnt1 = (a == "+" || a == "-" ? 1 : a == "*" || a == "/" ? 2 : 3);
cnt2 = (b == "+" || b == "-" ? 1 : b == "*" || b == "/" ? 2 : 3);
return cnt1 > cnt2;
}

std::string calculate(std::string a, std::string b, std::string operation) const {
long double x = stold(a);
long double y = stold(b);
if (operation == "+") return std::to_string(x + y);
if (operation == "-") return std::to_string(x - y);
if (operation == "*") return std::to_string(x * y);
if (operation == "/") return std::to_string(x / y);
if (operation == "^") return std::to_string(pow(x, y));
return a;
}

std::vector<std::string> cutter(std::string str) const {
std::vector<std::string> ope;
std::string tmp = "";
int ind = 0;

while (ind < str.length()) {
while (ind < str.length() &&
(isDigit(str[ind]) || str[ind] == '.')) {
tmp += str[ind++];
}

if (tmp != "") {
ope.push_back(tmp);
tmp = "";
}

while (ind < str.length() && !isDigit(str[ind])) {
tmp += str[ind++];
}

if (tmp.length() > 1 && tmp.back() == '-') {
tmp.pop_back();
ope.back() = "-" + ope.back();
}

if (tmp != "") {
ope.push_back(tmp);
tmp = "";
}
}
return ope;
}

std::vector<std::string> convertToPolishNotation(std::vector<std::string> ope) const {
if (ope.size() == 1) return {ope[0]};
std::vector<std::string> a;
a.push_back(ope[0]);
std::stack<std::string> st;
for (int i = 1; i < ope.size(); i += 2) {
if (st.empty()) {
st.push(ope[i]);
} else {
while (!st.empty() && !isHigher(ope[i], st.top())) {
a.push_back(st.top());
st.pop();
}
st.push(ope[i]);
}
a.push_back(ope[i + 1]);
}
while (!st.empty()) {
a.push_back(st.top());
st.pop();
}
return a;
}

public:
std::vector<std::string> convertToPolishNotation(std::string str) const {
return convertToPolishNotation(cutter(str));
}

long double calculateThePolishNotation(std::vector<std::string> a) const {
int ind = 0;
std::stack<std::string> st;
while (ind < a.size()) {
while (st.empty() || isNumber(st.top())) {
st.push(a[ind++]);
}
std::string operation = st.top();
st.pop();
std::string x = st.top();
st.pop();
std::string y = st.top();
st.pop();
st.push(calculate(y, x, operation));
}
return stold(st.top());
}
};

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

PolishNotation p = PolishNotation();
std::cout << std::fixed << p.calculateThePolishNotation(p.convertToPolishNotation(str));
}


# Include All Necessary Include Files

The code does not contain the necessary include for std::string, it does not compile on my computer (Windows 10, Visual Studio 2019 Professional) without this.

# Don't Reinvent the Wheel

The C programming language has ctype.h which includes the function isdigit() there is no need to write your own, you can include cctype to get access this function. You might also want to try the first answer in this stack overflow question.

# Alternate Implementation of the calculate() Function

One problem with the current implementation of the calculate() function is that there is no error checking, what happens if someone inputs an operator that you don't check for such as %, ^ or \$.

A second problem with this function is that it is difficult to add a new operator/operation.

An alternate implementation that could solve both these problems would be to use std::map or std::unordered_map that uses a character or string as a Key and has a pointer to a function as the mapped return type.