Modifying Shunting Yard Algorithm to Handle Fractions and Variables - c++

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();
}

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;
}

Problem C++ Reverse Polish Notation calculator

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';
}

Creating a Reverse Polish calculator in C++

Assignment: For this assignment, you are to write a program, which will calculate the results of Reverse Polish expressions that are provided by the user.
You must handle the following situations (errors):
Too many operators (+ - / *)
Too many operands (doubles)
Division by zero
The program will take in a Polish expression that separates the operators and operands by a single space, and terminates the expression with an equals sign.
The program will continue to take and evaluate expressions until the user enters a zero (0) on a line by itself followed by a new line.
Problem 1: I am having a problem with telling the user that there are too many operators and operands. I tried to code it but I have no
idea where to begin with this.
Problem 2: I want the program to end when the user inputs 0, but it is not doing anything when I do it in my program.
#include<iostream>
#include<iomanip>
#include<string>
#include<sstream>
using namespace std;
class Node
{
double data;
Node *top;
Node *ptr;
public:
Node()
{
top = NULL;
ptr = NULL;
}
bool isEmpty()
{
return top == 0;
}
void pushValue(double val)
{
Node *next = new Node;
next->data = val;
next->ptr = top;
top = next;
}
double popVal()
{
if (isEmpty())
{
cout << "Error: Too many operators" << endl;
}
else
{
Node *next = top->ptr;
double ret = top->data;
delete top;
top = next;
return ret;
}
}
//Displays the answer of the equation
void print()
{
cout << "= " << top->data << endl;
}
};
bool isOperator(const string& input)
{
string ops[] = { "+", "-", "*", "/" };
for (int i = 0; i < 4; i++)
{
if (input == ops[i])
{
return true;
}
}
return false;
}
//This function tells the operators what to do with the values.
void performOp(const string& input, Node& stack)
{
double Val1, Val2;
int errorCheck = 0;
Val1 = stack.popVal();
Val2 = stack.popVal();
if (input == "+")
{
stack.pushValue(Val1 + Val2);
}
else if (input == "-")
{
stack.pushValue(Val1 - Val2);
}
else if (input == "*")
{
stack.pushValue(Val1 * Val2);
}
else if (input == "/" && Val2 != 0)
{
stack.pushValue(Val1 / Val2);
}
if (input == "/" && Val2 == 0)
{
cout << "Error: Division by zero" << endl;
errorCheck = 1;
}
if (errorCheck == 0)
{
stack.print();
}
}
int main()
{
cout << "Reverse Polish Notation Calculator!" << endl;
cout << "-------------------------------------------------------------------" << endl;
cout << "Enter your values followed by your operators(Enter 0 to exit)" << endl;
string input;
Node stack;
//Checks the user's input to see which function to use.
while (true)
{
cin >> input;
double num;
if (stringstream(input) >> num)
{
stack.pushValue(num);
}
else if (isOperator(input))
{
performOp(input, stack);
}
else if (input == "0")
{
return 0;
}
}
}

Unable to compile c++ project in terminal

My assignment is to make a binary expression tree to convert postfix expressions to infix expressions in C++. I originally coded all my work in my Xcode IDE and would periodically ssh to linprog4 in terminal to make sure it works there because it has to before I turn it in. I don't understand the errors that are popping up when I compile it using g++ -o proj4.x -std=c++11 proj4_driver.cpp BET.cpp
This assignment was due 2 weeks ago and unfortunately when I was turning in the tar file with all my files, I forgot to include the .tar extension. I don't think that would affect my files but now they aren't compiling and I don't understand the errors I am getting. Could someone skim through my code and see if I am missing anything? I've looked over my code and it doesn't look like I accidentally typed something randomly somewhere.
Here is a screenshot of the errors I am getting
BET.h
#ifndef BET_H
#define BET_H
using namespace std;
class BET {
private:
struct BinaryNode {
string data;
BinaryNode * parent;
BinaryNode * childLeft;
BinaryNode * childRight;
bool visited; // to tell if node has been visited to or not
// Construct a blank copy version BinaryNode when an
// object of BET is created
BinaryNode( const char & d = char{}, BinaryNode * p = NULL,
BinaryNode * l = NULL,
BinaryNode * r = NULL, bool v = false )
: data { d },
parent { p },
childLeft { l },
childRight { r },
visited { v } {}
// Construct a blank move version of BinaryNode when an
// an object of BET is created
BinaryNode( char && d, BinaryNode * p = NULL, BinaryNode * l = NULL,
BinaryNode * r = NULL, bool v = false )
: data { std::move(d) },
parent { p },
childLeft { l },
childRight { r },
visited { v } {}
}; // end of BinaryNode struct
public:
// constructors and destructor
BET();
BET( const string postfix );
BET( const BET & rhs );
~BET();
// help copy constructor
bool buildFromPostfix( const string postfix );
// copy assignment operator
const BET & operator=( const BET & rhs );
void printInfixExpression();
void printPostfixExpression();
size_t size();
size_t leaf_nodes();
bool empty();
bool isOperand(BinaryNode * n);
private:
BinaryNode *root;
size_t leaves, nodes;
bool useP;
void printInfixExpression( BinaryNode * n );
void makeEmpty( BinaryNode* & t );
BinaryNode * clone( BinaryNode * t ) const;
void printPostfixExpression( BinaryNode * n );
size_t size( BinaryNode * t );
size_t leaf_nodes( BinaryNode * t );
}; // end of BET class
#endif
BET.cpp
#include <iostream>
#include <stack>
#include <sstream>
#include <string>
#include "BET.h"
//using namespace std;
// default zero-param constructor
BET::BET() {
root = new BinaryNode;
leaves = 0;
nodes = 0;
}
// one-param constructor, where parameter "postfix" is a
// string containing a postfix expression. The tree should
// be built based on the postfix expression. Tokens in the
// postfix expression are separated by space
BET::BET(const string postfix) {
root = new BinaryNode;
buildFromPostfix(postfix);
}
// copy constructor
BET::BET(const BET & rhs) {
leaves = rhs.leaves;
nodes = rhs.nodes;
root = rhs.root;
}
// destructor
BET::~BET() {
makeEmpty(root);
leaves = nodes = 0;
}
bool BET::buildFromPostfix(const string postfix) {
// Create stack to hold variables
stack<BinaryNode *> s;
stack<BinaryNode> bet;
char token;
string temp;
int index = 1;
bool doubleDigit = false;
int opCount = 0, digitCount = 0;
//stringstream hexToInt;
// iterator through postfix
for (int i = 0; i < postfix.size(); ++i) {
// grab token at iterations index
token = postfix[i];
if ( (token > '0' && token < '9') || (token > 62 && token < 80)) {
// check to see if token is an operand
// create a dynamic object of BinaryNode
BinaryNode *operand = new BinaryNode;
// check to see if next index of postfix is digit
// if its not, then we know its a double digit
// this while loop should only continue as long as the
// next index is between 0 and 9
temp = postfix[i];
while (postfix[i + index] >= '0' && postfix[i + index] <= '9') {
temp += postfix[i + index];
index++;
doubleDigit = true;
}
if (doubleDigit == true) {
i += index;
doubleDigit = false;
index = 1;
operand->data = temp;
} else {
operand->data = postfix[i];
}
s.push(operand);
digitCount++;
} else if (token == '+' || token == '-' || token == '*' || token == '/'){
// check to see if token is operator
BinaryNode *operand = new BinaryNode;
operand->data = postfix[i];
operand->childLeft = s.top();
s.top()->parent = operand;
s.pop();
operand->childRight = s.top();
s.top()->parent = operand;
s.pop();
s.push(operand);
opCount++;
} else {
// if neither, must be space or other character
if (token == ' ') {
} else
return false;
}
}
if (digitCount <= opCount) {
return false;
}
root = s.top();
nodes = size();
//leaves = leaf_nodes();
// THINGS TO DO:
// Make error cases with if statements to return false at some point
return true;
}
// assignment operator
const BET & BET::operator=(const BET & rhs) {
root = clone(rhs.root);
return *this;
}
// public version of printInfixExpression()
// calls the private version of the printInfixExpression fuction
// to print out the infix expression
void BET::printInfixExpression() {
printInfixExpression(root);
}
// public version of printPostfixExpression()
// calls the private version of the printPostfixExpression function
// to print out the postfix expression
void BET::printPostfixExpression() {
printPostfixExpression(root);
}
// public version of size()
// calls the private version of the size function to return
// the number of nodes in the tree
size_t BET::size() {
return size(root);
}
// public version of leaf_nodes()
// calls the private version of leaf_nodes function to return
// the number of leaf nodes in the tree
size_t BET::leaf_nodes() {
return leaf_nodes(root);
}
// public version of empty()
// return true if the tree is empty. return false otherwise
bool BET::empty() {
if (nodes == 0) {
return true;
} else
return false;
}
// checks whether node is operand or not
bool BET::isOperand(BinaryNode * n) {
if (n->data != "+" && n->data != "-" && n->data != "*" && n->data != "/") {
return true;
} else
return false;
}
// private version of printInfixExpression
// print to the standard output the corresponding infix expression
void BET::printInfixExpression(BinaryNode * n) {
//BinaryNode * temp = NULL;
if (n != NULL ) {
printInfixExpression(n->childRight);
cout << n->data << " ";
printInfixExpression(n->childLeft);
}
/*
if (n != NULL && useP == true) {
printInfixExpression(n->childRight);
if (isOperand(n->parent) && n->parent != NULL && !n->childLeft) {
cout << "(";
}
cout << n->data << " ";
if (isOperand(n->parent) && n->parent != NULL && !n->childRight) {
cout << ")";
}
printInfixExpression(n->childLeft);
}
*/
}
// private method makeEmpty()
// delete all nodes in the subtree pointed to by n.
// Called by functions such as the destructor
void BET::makeEmpty(BinaryNode * & n) {
if (n != NULL) {
makeEmpty(n->childLeft);
makeEmpty(n->childRight);
delete n;
}
}
// private method clone()
// clone all nodes in the subtree pointed by n. Called by
// functions such as the assignment operator=
BET::BinaryNode * BET::clone(BinaryNode * n) const {
if (n != NULL) {
root->childRight = clone(n->childRight);
root->childLeft = clone(n->childLeft);
root->data = n->data;
}
return root;
}
// private method printPostfixExpression()
// print to the standard output the corresponding postfix expression
void BET::printPostfixExpression(BinaryNode * n) {
if (n != NULL) {
printPostfixExpression(n->childRight);
printPostfixExpression(n->childLeft);
cout << n->data << " ";
}
}
// private version of size()
// return the number of nodes in the subtree pointed by n
size_t BET::size(BinaryNode * n) {
if (n != NULL) {
size(n->childLeft);
size(n->childRight);
nodes++;
}
return nodes;
}
// return the number of leaf nodes in the subtree pointed by n
size_t BET::leaf_nodes(BinaryNode * n) {
if (n != NULL) {
leaf_nodes(n->childLeft);
leaf_nodes(n->childRight);
if (n->childLeft == NULL && n->childRight == NULL) {
leaves += 1;
}
}
return leaves;
}
Driver.cpp
#include "BET.cpp"
//using namespace std;
int main() {
string postfix;
// get a postfix expression
cout << "Enter the first postfix expression: ";
getline(cin, postfix);
// create a binary expression tree
BET bet1(postfix);
if (!bet1.empty()) {
cout << "Infix expression: ";
bet1.printInfixExpression();
cout << "\n";
cout << "Postfix expression: ";
bet1.printPostfixExpression();
cout << "\nNumber of nodes: ";
cout << bet1.size() << endl;
cout << "Number of leaf nodes: ";
cout << bet1.leaf_nodes() << endl;
// test copy constructor
BET bet2(bet1);
cout << "Testing copy constructor: ";
//bet2.printInfixExpression();
// test assignment operator
BET bet3;
bet3 = bet1;
cout << "Testing assignment operator: ";
//bet3.printInfixExpression();
}
cout << "Enter a postfix expression (or \"quit\" to quit): ";
while (getline(cin, postfix)) {
if (postfix == "quit") {
break;
}
if (bet1.buildFromPostfix(postfix)) {
cout << "Infix expression: ";
bet1.printInfixExpression();
cout << "Postfix expression: ";
bet1.printPostfixExpression();
cout << "Number of nodes: ";
cout << bet1.size() << endl;
cout << "Number of leaf nodes: ";
cout << bet1.leaf_nodes() << endl;
}
cout << "Enter a postfix expression (or \"quit\" to quit): ";
}
return 0;
}
Driver.cpp #include "BET.cpp" should be #include "BET.h"
Or (and this is just for completeness, not recommended), leave the include of the .cpp, but then only try to compile the one .cpp (as in g++ Driver.cpp) - since driver will include BET and so all your code is there and will build.

Error: deque iterator not dereferenceable

I'm trying to create a program that converts an arithmetic expression from infix to postfix form. As long as I don't call the "infixToPostFix" function, the program runs fine.
But when I try to run the following code, I get a crash and error "deque iterator not dereferenceable". I can't find any dereferencing operators, so I'm not sure what's wrong:
// infixToPostfixTest.cpp
#include "Token.h"
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
// infix to postfix function prototype
void infixToPostfix(vector<Token> &infix, vector<Token> &postfix);
// priority function prototype
int priority(Token & t);
// printing a Token vector
void printTokenVector(vector<Token> & tvec);
int main() {
// Experiment
//--------------------------------------------------
vector<Token> infix;
// a + b * c - d / e % f
//
infix.push_back(Token(VALUE,5.0)); // a
infix.push_back(Token(OPERATOR,'+'));
infix.push_back(Token(VALUE,6.0)); // b
infix.push_back(Token(OPERATOR,'*'));
infix.push_back(Token(VALUE,7.0)); // c
cout << "Infix expression: ";
printTokenVector(infix);
vector<Token> postfix; // create empty postfix vector
infixToPostfix(infix, postfix); // call inToPost to fill up postfix vector from infix vector
cout << "Postfix expression: ";
printTokenVector(postfix);
cout << endl << endl;
return 0;
}
// printing a Token vector
void printTokenVector(vector<Token> & tvec)
{
int size = tvec.size();
for (int i = 0; i < size; i++) {
cout << tvec[i] << " ";
}
cout << endl;
}
int priority(Token & t) // assumes t.ttype is OPERATOR, OPEN, CLOSE, or END
{
char c = t.getChar();
char tt = t.getType();
if (c == '*' || c == '/')
return 2;
else if (c == '+' || c == '-')
return 1;
else if (tt == OPEN)
return 0;
else if (tt == END)
return -1;
else
return -2;
}
void infixToPostfix(vector<Token> &infix, vector<Token> &postfix)
{
stack<Token> stack;
postfix.push_back(END);
int looper = 0;
int size = infix.size();
while(looper < size) {
Token token = infix[looper];
if (token.getType() == OPEN)
{
stack.push(token);
}
else if (token.getType() == CLOSE)
{
token = stack.top();
stack.pop();
while (token.getType() != OPEN)
{
postfix.push_back(token);
token = stack.top();
stack.pop();
}
}
else if (token.getType() == OPERATOR)
{
Token topToken = stack.top();
while ((!stack.empty()) && (priority(token) <= priority(topToken)))
{
Token tokenOut = stack.top();
stack.pop();
postfix.push_back(tokenOut);
topToken = stack.top();
}
stack.push(token);
}
else if (token.getType() == VALUE)
{
postfix.push_back(token);
}
else
{
cout << "Error! Invalid token type.";
}
looper = looper + 1;
}
while (!stack.empty())
{
Token token = stack.top();
stack.pop();
postfix.push_back(token);
}
}
//Token.h
#ifndef TOKEN_H
#define TOKEN_H
#include <iostream>
using namespace std;
enum TokenType { OPEN, CLOSE, OPERATOR, VARIABLE, VALUE, END };
class Token {
public:
Token (TokenType t, char c) : ttype(t), ch(c) { }
Token (TokenType t, double d) : ttype(t), number(d) { }
Token (TokenType t) : ttype(t) { }
Token () : ttype (END), ch('?'), number(-99999999) { }
TokenType getType() {return ttype;}
char getChar() {return ch;}
double getNumber() {return number;}
private:
TokenType ttype;
char ch;
double number;
};
ostream & operator << (ostream & os, Token & t) {
switch (t.getType()) {
case OPEN:
os << "("; break;
case CLOSE:
os << ")"; break;
case OPERATOR:
os << t.getChar(); break;
case VARIABLE:
os << t.getChar(); break;
case VALUE:
os << t.getNumber(); break;
case END:
os << "END" ; break;
default: os << "UNKNOWN";
}
return os;
}
stack is implemented using container, since stack is container adaptor, by default deque is used. In probably one line of your code - you call pop/top on empty stack, that is not allowed.
trace show, that error is after Token +.
Problem is here:
else if (token.getType() == OPERATOR)
{
Token topToken = stack.top();
You try to top from empty stack, since stack in case, where is only NUMBER token before OPERATOR token, is empty.
You are calling top on empty stack, just follow the code for your test.
you start with an empty stack
you encounter a VALUE, you don't change stack
you encounter an OPERATOR and attempt to access stack.top()
I ran into this problem too. I think the problem is in this sort of code:
else if (token.getType() == CLOSE)
{
token = stack.top();
stack.pop();
while (token.getType() != OPEN)
{
postfix.push_back(token);
token = stack.top();
stack.pop();
}
}
The problem is that 'token' is a reference to the top, not a copy. So you can't pop the stack until you are done working with token. In my case, it often still worked because the information was still present, but then it would crash at weird times. You need to organize this code in a different way to pop only after you done working with 'token'.
Maybe something like:
else if (token.getType() == CLOSE)
{
token = stack.top();
Token saveToken = new Token(token); // Or something like this...
stack.pop();
while (saveToken.getType() != OPEN)
{
postfix.push_back(saveToken);
token = stack.top();
delete saveToken; // ugh
Token saveToken = new Token(token);
stack.pop();
}
delete saveToken; //ugh
}