Problem C++ Reverse Polish Notation calculator - c++

I have a problem with RPN.
I want the program to finish entering characters after pressing ENTER but something doesn't work because it doesn't write to vec.
I tried to solve the task:
The value of the expression recorded in Reverse Polish Notation should be determined. The expression will contain the following operators: +, -, * and / (integer division) and natural numbers not greater than one million. The result is in the type int.
Entrance
In the first and only line the phrase written in Reverse Polish Notation. Operators are separated from numbers by a space character. Expression length is less than 1000 characters.
Exit
The end value of the ONP expression.
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
int RPN(vector<string> &notation) {
stack<int> s;
for (string str : notation) {
if (str == "+" or str == "-" or str == "/" or str == "*") {
int a = s.top();
s.pop();
int b = s.top();
s.pop();
if (str == "-") {
s.push(b - a);
continue;
}
if (str == "+") {
s.push(b + a);
continue;
}
if (str == "/") {
s.push(b / a);
continue;
}
if (str == "*") {
s.push(b * a);
continue;
}
} else
s.push(stoi(str));
}
return s.top();
}
int main() {
vector<string> notation;
while (true) {
string sign;
cin >> sign;
if (cin.get() != 'n') {
break;
} else {
notation.push_back(sign);
}
}
for (auto i : notation) // test, print vec
{
cout << i << endl;
;
}
cout << RPN(notation) << endl;
return 0;
}

Your code doesn't maintain precedence. It treats addition the same way it treats multiplication. If that's what you want, you can just perform each operation from left to right.
I suppose the goal of your program is to have some precedence and to perform for example multiplication before addition.
Here is a simple code that maintains precedence. The code assumes that the input is always correct and do not handle parentheses for simplicity.
#include <iostream>
#include <vector>
#include <stack>
int getPrecedence(std::string &o)
{
if (o == "+" || o == "-")
return 1;
return 2;
}
int calculate(int a, int b, const std::string &operation)
{
if (operation == "+")
return a + b;
if (operation == "-")
return a - b;
if (operation == "*")
return a * b;
if (operation == "/")
return a / b;
return -1;
}
void performOperation(std::stack<int> &numbers, std::stack<std::string> &operators) {
int n1 = numbers.top();
numbers.pop();
int n2 = numbers.top();
numbers.pop();
std::string op = operators.top();
operators.pop();
numbers.push(calculate(n2, n1, op));
}
int RPN(std::vector<std::string> &notation) {
std::stack<int> numbers;
std::stack<std::string> operators;
if (notation.empty())
return 0;
numbers.push(stoi(notation[0]));
for (int i = 1; i < notation.size(); i+=2)
{
while (!operators.empty() && getPrecedence(operators.top()) >= getPrecedence(notation[i]))
performOperation(numbers, operators);
numbers.push(std::stoi(notation[i+1]));
operators.push(notation[i]);
}
while (!operators.empty())
performOperation(numbers, operators);
return numbers.top();
}
std::vector<std::string> parse(const std::string& input)
{
std::vector<std::string> vec;
std::string current;
for (char c : input)
{
if (isdigit(c))
current += c;
else if (c)
{
if (!current.empty())
{
vec.emplace_back(std::move(current));
current = "";
}
if (c != ' ')
vec.emplace_back(1, c);
}
}
if (!current.empty())
vec.push_back(std::move(current));
return vec;
}
int main() {
// This program doesn't validate input.
// It assumes that the input is always correct.
std::string input;
std::getline(std::cin, input);
std::vector<std::string> notation = parse(input);
std::cout << RPN(notation) << '\n';
}
Input:
1 + 2 + 3 * 3 + 3 / 3 + 5 - 4
Output:
14
For simplicity, I take the number of strings that the program will read before taking the input.
Update:
The above code assumes that the input is an infix expression. If the input is already in the RPN, the code would be like this:
#include <iostream>
#include <vector>
#include <stack>
int calculate(int a, int b, const std::string &operation)
{
if (operation == "+")
return a + b;
if (operation == "-")
return a - b;
if (operation == "*")
return a * b;
if (operation == "/")
return a / b;
return -1;
}
bool isOperation(const std::string& op)
{
return op == "+" || op == "-" || op == "*" || op == "/";
}
int RPN(std::vector<std::string> &notation) {
std::stack<int> numbers;
for (const auto& str : notation)
{
if (isOperation(str))
{
int n2 = numbers.top(); numbers.pop();
int n1 = numbers.top(); numbers.pop();
numbers.push(calculate(n1, n2, str));
}
else
numbers.push(std::stoi(str));
}
return numbers.top();
}
std::vector<std::string> parse(const std::string& input)
{
std::vector<std::string> vec;
std::string current;
for (char c : input)
{
if (isdigit(c))
current += c;
else if (c)
{
if (!current.empty())
{
vec.emplace_back(std::move(current));
current = "";
}
if (c != ' ')
vec.emplace_back(1, c);
}
}
if (!current.empty())
vec.push_back(std::move(current));
return vec;
}
int main() {
// This program doesn't validate input.
// It assumes that the input is always correct.
std::string input;
std::getline(std::cin, input);
std::vector<std::string> notation = parse(input);
std::cout << RPN(notation) << '\n';
}

Related

Replace every occurrence with double in string

I'm trying to write a function whose first parameter is a string and the second parameter is vector of real numbers. The function should return as a result a new string in which each occurrence replaces the sequences "%d" or "%f" with one number each from the vector, in the order in which they appear. In doing so, if the sequence is "%d", any decimals in the number are truncated, while in the sequence "%f" they are retained.
For example, if the string reads “abc%dxx%fyy %d” and if the vector contains the numbers 12.25, 34.13, 25 and 47, the new string should read “abc12xx34.13yy 25” (data 47 which is “redundant” is simply ignored).
#include <iostream>
#include <string>
#include <vector>
std::string Replace(std::string s, std::vector < double > vek) {
std::string str;
int j = 0;
for (int i = 0; i < s.length(); i++) {
while (s[i] != '%' && i < s.length()) {
if (s[i] != 'f' && s[i] != 'd')
str += s[i];
i++;
}
if (s[i] == '%' && (s[i + 1] == 'd' || s[i + 1] == 'f')) {
if (s[i + 1] == 'd')
str += (std::to_string(int(vek[j])));
if (s[i + 1] == 'f') {
std::string temp = std::to_string(vek[j]);
int l = 0;
while (temp[l] != '0') {
str += temp[l];
l++;
}
}
j++;
if (j > vek.size())
throw std::range_error("Not enough elements");
if (i == s.length()) break;
}
}
return str;
}
int main() {
try {
std::cout<<Replace("abc%dxx%fyy %d",{12.25, 34.13, 25});
std::cout << "\n" << "abc12xx34.13yy 25";
} catch (std::range_error e) {
std::cout << e.what();
}
return 0;
}
OUTPUT:
abc12xx34.13yy 25
abc12xx34.13yy 25
Output is correct. How could I modify this to work with less lines of code? Is there any way to make this more elegant and efficient?
You could use:
regular expressions to search for the pattern (%d|%f), i.e., %d or %f, and
a string stream to create the string to return.
Going into some more detail:
The code is basically a while (std::regex_search).
std::regex_search will return whatever was in the input string before the matched pattern (what you want in the output string), the matched pattern (what you will need to check in order to decide if you want to write out an int or a double), and whatever is left to parse.
By using std::ostringstream, you can simply write out ints or doubles without converting them to strings yourself.
vek.at() will throw an std::out_of_range exception if you run out of data in the vector.
Notice as well that, whereas for this implementation it's good to pass the string s by value (since we are modifying it within the function), you should pass vek as a const reference to avoid a copy of the whole vector.
[Demo]
#include <iostream>
#include <regex>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
std::string Replace(std::string s, const std::vector<double>& vek) {
std::regex pattern{"(%d|%f)"};
std::smatch match{};
std::ostringstream oss{};
for (auto i{0}; std::regex_search(s, match, pattern); ++i) {
oss << match.prefix();
auto d{vek.at(i)};
oss << ((match[0] == "%d") ? static_cast<int>(d) : d);
s = match.suffix();
}
return oss.str();
}
int main() {
try {
std::cout << Replace("abc%dxx%fyy %d", {12.25, 34.13, 25});
std::cout << "\n"
<< "abc12xx34.13yy 25";
} catch (std::out_of_range& e) {
std::cout << e.what();
}
}
// Outputs:
//
// abc12xx34.13yy 25
// abc12xx34.13yy 25
[EDIT] A possible way to do it without std::regex_search would be to search for the (%d|%f) pattern manually, using std::string::find in a loop until the end of the string is reached.
The code below takes into account that:
the input string could not have that pattern, and that
it could have a % character followed by neither d nor f.
[Demo]
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
std::string Replace(std::string s, const std::vector<double>& vek) {
std::ostringstream oss{};
size_t previous_pos{0};
size_t pos{0};
auto i{0};
while (previous_pos != s.size()) {
if ((pos = s.find('%', previous_pos)) == std::string::npos) {
oss << s.substr(previous_pos);
break;
}
oss << s.substr(previous_pos, pos - previous_pos);
bool pattern_found{false};
if (s.size() > pos + 1) {
auto c{s[pos + 1]};
if (c == 'd') {
oss << static_cast<int>(vek.at(i));
pattern_found = true;
} else if (c == 'f') {
oss << vek.at(i);
pattern_found = true;
}
}
if (pattern_found) {
++i;
previous_pos = pos + 2;
} else {
oss << s[pos];
previous_pos = pos + 1;
}
}
return oss.str();
}
int main() {
try {
std::cout << Replace("abc%%dx%x%fyy %d", {12.25, 34.13, 25}) << "\n";
std::cout << "abc%12x%x34.13yy 25\n";
std::cout << Replace("abcdxxfyy d", {12.25, 34.13, 25}) << "\n";
std::cout << "abcdxxfyy d\n";
} catch (std::out_of_range& e) {
std::cout << e.what();
}
}
// Outputs:
//
// abc%12x%x34.13yy 25
// abc%12x%x34.13yy 25
// abcdxxfyy d
// abcdxxfyy d
#include <iostream>
#include <vector>
#include <string>
std::string replace(std::string str, std::vector<double> vec) {
std::string result = "";
int i = 0;
// loop through the string
while (i < str.size()) {
// if the current character is a %
if (str[i] == '%') {
// if the next character is a d
if (str[i+1] == 'd') {
// if the vector is not empty
if (vec.size() > 0) {
// add the first element of the vector to the result
result += std::to_string(vec[0]);
// remove the first element of the vector
vec.erase(vec.begin());
}
// move the index to the next character
i += 2;
}
// if the next character is a f
else if (str[i+1] == 'f') {
// if the vector is not empty
if (vec.size() > 0) {
// add the first element of the vector to the result
result += std::to_string(vec[0]);
// remove the first element of the vector
vec.erase(vec.begin());
}
// move the index to the next character
i += 2;
}
// if the next character is not a d or f
else {
// add the current character to the result
result += str[i];
// move the index to the next character
i += 1;
}
}
// if the current character is not a %
else {
// add the current character to the result
result += str[i];
// move the index to the next character
i += 1;
}
}
// return the result
return result;
}
int main() {
std::vector<double> vec = {12.25, 34.13, 25, 47};
std::string str = "abc%dxx%fyy %d";
std::cout << replace(str, vec);
return 0;
}

infix to postfix program not producing the correct output

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iomanip>
using namespace std;
class Stack {
public:
string stack[100][1];
int size;
Stack() { size = 0; }
~Stack() {};
void push(string data) {
stack[size][0] = data;
size += 1;
}
bool empty() {
if (size == 0)
{
return true;
}
else
{
return false;
}
}
string pop() {
size -= 1;
return stack[size][0];
}
string top() {
if (empty())
cout << "Stack is empty";
return stack[size - 1][0];
}
};
int pre(char op)
{
switch (op)
{
case '(': case ')': return 0;
case '+': case '-': return 1;
case '*': case '/': return 2;
}
return -1;
}
vector<string> infix_to_postfix(const vector<string>& expr) {
vector<string> postfix;
string op;
Stack st;
for (int i = 0; i < expr.size(); i++) {
if (expr[i][0] == '+' || expr[i][0] == '-' || expr[i][0] == '*' || expr[i][0] == '/') {
while (!st.empty()) {
op = (st.top()[0]);
if (pre(expr[i][0]) <= pre(op[0]))
postfix.push_back(st.pop());
else break;
}
postfix.push_back(expr[i]);
}
else if (expr[i][0] == '(') {
st.push(expr[i]);
}
else if (expr[i][0] == ')') {
while (!st.empty()) {
op = st.pop();
if (op[0] == '(') break;
else {
postfix.push_back(op);
}
}
}
else {
postfix.push_back(expr[i]);
}
}
return postfix;
}
int main() {
auto expr = infix_to_postfix({ "(", "2", "+", "3", ")", "*", "7" });
for (auto& elem : expr)
{
std::cout << elem << ", ";
}
std::cout << "\n";
return 0;
}
This program is supposed to convert from infix to postfix but it is not producing the correct output. I'm expecting the output to be:
2, 3, +, 7, *,
but the output is
2, +, 3, *, 7,
You have two issues.
When handling an operator, after popping the lower precedence operators you need to push the new operator onto the stack rather than adding it to the result:
if (expr[i][0] == '+' || expr[i][0] == '-' || expr[i][0] == '*' || expr[i][0] == '/') {
while (!st.empty()) {
op = (st.top()[0]);
if (pre(expr[i][0]) <= pre(op[0]))
postfix.push_back(st.pop());
else break;
}
st.push(expr[i]);
}
At the end of the function you need to pop any remaining operators off the stack:
while (!st.empty())
{
postfix.push_back(st.pop());
}
return postfix;

pattern matching (codejam round 1A previous year) solution not working

I am trying previous year's codejam question of round 1A
link to question
i have submitted this code(start reading from main method, for ease)-
#include <bits/stdc++.h>
using namespace std;
#define range(t) for (int i = 0; i < t; i++)
#define rangeG(i, t) for (i = 0; i < t; i++)
#define printVec(vec) \
for (auto c : vec) \
{ \
cout << c << endl; \
}
vector<string> separate(string s)
{
vector<string> result;
range(s.size())
{
if (s[i] == '*')
{
string temp = s.substr(0, i + 1);
if (temp.size() > 1)
{
result.push_back(temp);
}
s = s.substr(i, s.size());
i = 0;
}
else if (i == (s.size() - 1))
{
string temp = s.substr(0, i + 1);
result.push_back(temp);
s = s.substr(i, s.size());
}
}
return result;
}
void removeAsterisk(string &s)
{
s.erase(remove(s.begin(), s.end(), '*'), s.end());
}
bool setStart(string s, string &start)
{
bool possible = 1;
removeAsterisk(s);
range(min(s.size(), start.size()))
{
if (s[i] != start[i])
{
possible = 0;
}
}
if (possible)
{
if (s.size() >= start.size())
{
start = s;
}
}
return possible;
}
bool setEnd(string s, string &end)
{
bool possible = 1;
removeAsterisk(s);
range(min(s.size(), end.size()))
{
if (s[s.size() - 1 - i] != end[end.size() - 1 - i])
{
possible = 0;
}
}
if (possible)
{
if (s.size() >= end.size())
{
end = s;
}
}
return possible;
}
void solve()
{
int n;
cin >> n;
vector<string> allS;
bool possible = 1;
string start = "";
string end = "";
string middle = "";
string result = "";
while (n--)
{
string str;
cin >> str;
if (count(str.begin(), str.end(), '*') == 0)
{
result = str;
}
vector<string> temp = separate(str);
for (string s : temp)
{
if (s[0] != '*')
{
possible = setStart(s, start);
}
if (s[s.size() - 1] != '*')
{
possible = setEnd(s, end);
}
if (possible && count(s.begin(), s.end(), '*') == 0)
{
result = s;
break;
}
if (s[0] == '*' && s[s.size() - 1] == '*')
{
removeAsterisk(s);
middle += s;
}
}
}
if (possible)
{
if (result.size() == 0)
{
result = start + middle + end;
}
cout << result << "\n";
}
else
{
cout << "*\n";
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t = 0;
cin >> t;
range(t)
{
cout << "Case #" << i + 1 << ": ";
solve();
}
return 0;
}
it seems correct to me and i have tested many times for many examples, but it is losing in test set-1(exactly one * (asterisk) character and and always the first character of string). Can anyone tell what's wrong?
you can consider code of first ranked here (it has all solutions,check only for "pattern matching" task) for help. I know that the wrong answer is an edge case and if it passes test set 1 then it will pass others.

Infix/Postfix evaluator terminating issue

I've got a few different functions that on their own work fine. Now I am trying to put them together into one file. My debugger is throwing segmentation faults in the infixToPostfix function.
When I watch the ns variable, it does not show anything getting assigned to it, but it prints out the postfix expression when I actually run the code. When ns passes into PostfixEvaulation, it runs to the top member function of TemplateStack and crashes with:
terminate called after throwing an instance of "std::string"
This only happens when I pass a string with an operator. When I pass a string of just numbers, everything runs fine,
but it still does not seem to call PostfixEvaluation.
#include <iostream>
#include <sstream>
#include <string>
#include <typeinfo>
using namespace std;
//Class Template Stack declaration
template <class T>
class TemplateStack {
public:
typedef T type;
TemplateStack()
{
max_size_ = 50;
TopOfStack = 0;
data_ = new T[max_size_];
} //Default Constructor taking no parameters
void push(T element)
{
if (TopOfStack == max_size_)
throw string("Stack's underlying storage is overflow");
TopOfStack++;
data_[TopOfStack] = element;
}
void pop() {
if (TopOfStack == -1)
throw string("Stack is empty");
TopOfStack--;
}
T top() {
if (TopOfStack == -1)
throw string("Stack is empty");
return data_[TopOfStack];
}
private:
int TopOfStack; //Generic data type for the top element of stack
size_t max_size_;
T* data_;
};
//Function to Evauluate the Postfix notation expresion
int PostfixEvaulation(string input){
//string input;
int operand1, operand2, result,number;
TemplateStack<char>operation;
stringstream temp;
int i=0;
while (i < input.length())
{
if (isdigit(input[i]))
{
operation.push(input[i]);
}
else
{
operand2 = operation.top();
temp << operation.top();
operation.pop();
operand1 = operation.top();
temp << operation.top();
operation.pop();
switch(operand1,operand2)
{
case '+': result=operand1 + operand2;
break;
case '-': result=operand1 - operand2;
break;
case '*': result=operand1 * operand2;
break;
case '/': result=operand1 / operand2;
break;
}
operation.push(result);
}
i++;
}
cout << "The result is: "<<temp.str()<<endl;
//cin.ignore(numeric_limits<streamsize>::max(), '\n');
return 0;
}
//Function to return precedence of operators
int prec(char c)
{
if(c == '^')
return 3;
else if(c == '*' || c == '/')
return 2;
else if(c == '+' || c == '-')
return 1;
else
return -1;
}
//Function: Convert Infix to Postfix
void infixToPostfix(string s)
{
TemplateStack<char> st;
st.push('N');
int l = s.length();
string ns;
for (int i = 0; i < l; i++) {
// If the scanned character is an operand, add it to output string.
if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z')) {
ns += s[i];
}
// If the scanned character is an ‘(‘, push it to the stack.
else if (s[i] == '(') {
st.push('(');
}
// If the scanned character is an ‘)’, pop and to output string from the stack
// until an ‘(‘ is encountered.
else if (s[i] == ')') {
while (st.top() != 'N' && st.top() != '(') {
char c = st.top();
st.pop();
ns += c;
}
if (st.top() == '(') {
char c = st.top();
st.pop();
}
}
//If an operator is scanned
else {
while (st.top() != 'N' && prec(s[i]) <= prec(st.top())) {
char c = st.top();
st.pop();
ns += c;
}
st.push(s[i]);
}
}
//Pop all the remaining elements from the stack
while (st.top() != 'N') {
char c = st.top();
st.pop();
ns += c;
}
cout << "Here is the ns variable: "<< ns << endl;
PostfixEvaulation(ns);//Call the PostFixEvaluationFunction with the ns (postfix notation) variab
}
//Function: User inputs Expression
void GetInput(){
string input;
cout << "Enter Infix Expression: ";
getline(cin, input);
infixToPostfix(input);
}
int main()
{
GetInput();
}

Modifying Shunting Yard Algorithm to Handle Fractions and Variables

I am using a modified version of Jesse Brown's shunting yard algorithm implementation. I am trying to modify the variable system to basically perform symbolic math instead of assigning double values to the variables. For example, instead of simply stating pi = 3.14, I would like it to just include pi in the solution. So 1+2+pi would result in 3+pi.
The code is as follows. I have just started to mess with it and haven't done a lot. Does anyone have any ideas?
// Source: http://www.daniweb.com/software-development/cpp/code/427500/calculator-using-shunting-yard-algorithm#
// Author: Jesse Brown
// Modifications: Brandon Amos
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include "shunting_yard.h"
using namespace std;
#define isvariablechar(c) (isalpha(c) || c == '_')
TokenQueue_t calculator::toRPN(const char* expr,
map<string, string>* vars,
map<string, int> opPrecedence) {
TokenQueue_t rpnQueue; stack<string> operatorStack;
bool lastTokenWasOp = true;
// In one pass, ignore whitespace and parse the expression into RPN
// using Dijkstra's Shunting-yard algorithm.
while (*expr && isspace(*expr)) ++expr;
while (*expr) {
if (isdigit(*expr)) {
// If the token is a number, add it to the output queue.
char* nextChar = 0;
double digit = strtod(expr, &nextChar);
# ifdef DEBUG
cout << digit << endl;
# endif
rpnQueue.push(new Token<double>(digit));
expr = nextChar;
lastTokenWasOp = false;
}
else if (isvariablechar(*expr)) {
// If the function is a variable, resolve it and
// add the parsed number to the output queue.
if (!vars) {
//throw domain_error(
//"Detected variable, but the variable map is null.");
}
stringstream ss;
ss << *expr;
++expr;
while (isvariablechar(*expr)) {
ss << *expr;
++expr;
}
string key = ss.str();
map<string, string>::iterator it = vars->find(key);
if (it == vars->end()) {
//throw domain_error(
//"Unable to find the variable '" + key + "'.");
}
string val = vars->find(key)->second;
# ifdef DEBUG
cout << val << endl;
# endif
rpnQueue.push(new Token<string>(val));;
lastTokenWasOp = false;
}
else {
// Otherwise, the variable is an operator or paranthesis.
switch (*expr) {
case '(':
operatorStack.push("(");
++expr;
break;
case ')':
while (operatorStack.top().compare("(")) {
rpnQueue.push(new Token<string>(operatorStack.top()));
operatorStack.pop();
}
operatorStack.pop();
++expr;
break;
default:
{
// The token is an operator.
//
// Let p(o) denote the precedence of an operator o.
//
// If the token is an operator, o1, then
// While there is an operator token, o2, at the top
// and p(o1) <= p(o2), then
// pop o2 off the stack onto the output queue.
// Push o1 on the stack.
stringstream ss;
ss << *expr;
++expr;
while (*expr && !isspace(*expr) && !isdigit(*expr)
&& !isvariablechar(*expr) && *expr != '(' && *expr != ')') {
ss << *expr;
++expr;
}
ss.clear();
string str;
ss >> str;
# ifdef DEBUG
cout << str << endl;
# endif
if (lastTokenWasOp) {
// Convert unary operators to binary in the RPN.
if (!str.compare("-") || !str.compare("+")) {
rpnQueue.push(new Token<double>(0));
}
else {
//throw domain_error(
//"Unrecognized unary operator: '" + str + "'.");
}
}
while (!operatorStack.empty() &&
opPrecedence[str] <= opPrecedence[operatorStack.top()]) {
rpnQueue.push(new Token<string>(operatorStack.top()));
operatorStack.pop();
}
operatorStack.push(str);
lastTokenWasOp = true;
}
}
}
while (*expr && isspace(*expr)) ++expr;
}
while (!operatorStack.empty()) {
rpnQueue.push(new Token<string>(operatorStack.top()));
operatorStack.pop();
}
return rpnQueue;
}
double calculator::calculate(const char* expr,
map<string, string>* vars) {
// 1. Create the operator precedence map.
map<string, int> opPrecedence;
opPrecedence["("] = -1;
opPrecedence["<<"] = 1; opPrecedence[">>"] = 1;
opPrecedence["+"] = 2; opPrecedence["-"] = 2;
opPrecedence["*"] = 3; opPrecedence["/"] = 3;
// 2. Convert to RPN with Dijkstra's Shunting-yard algorithm.
TokenQueue_t rpn = toRPN(expr, vars, opPrecedence);
// 3. Evaluate the expression in RPN form.
stack<double> evaluation;
while (!rpn.empty()) {
TokenBase* base = rpn.front();
rpn.pop();
Token<string>* strTok = dynamic_cast<Token<string>*>(base);
Token<double>* doubleTok = dynamic_cast<Token<double>*>(base);
if (strTok) {
string str = strTok->val;
/*if (evaluation.size() < 2) {
throw domain_error("Invalid equation.");
}*/
if (str.compare("pi")){
cout << "its pi!" << endl;
}
double right = evaluation.top(); evaluation.pop();
double left = evaluation.top(); evaluation.pop();
if (!str.compare("+")) {
evaluation.push(left + right);
}
else if (!str.compare("*")) {
evaluation.push(left * right);
}
else if (!str.compare("-")) {
evaluation.push(left - right);
}
else if (!str.compare("/")) {
evaluation.push(left / right);
}
else if (!str.compare("<<")) {
evaluation.push((int)left << (int)right);
}
else if (!str.compare(">>")) {
evaluation.push((int)left >> (int)right);
}
else {
cout << "Unknown Operator" << endl;
//throw domain_error("Unknown operator: '" + str + "'.");
}
}
else if (doubleTok) {
evaluation.push(doubleTok->val);
}
else {
//throw domain_error("Invalid token.");
}
delete base;
}
return evaluation.top();
}