Converting from Infix to Postfix using stacks (c++) - c++

I'm currently working on a project to convert from postfix to infix using a stack in the form of a singly linked list. I've managed to convert expressions such as ab+ to (a+b) however when the expression gets longer such as ab+cd*-. It doesn't work. I'm considering pushing the previously converted expression back onto the stack however the stack is of type char and the expression is a string and it complains when I try to push it back. Should I make it a template and if so how would I do it or is there anyway else to solve this problem.
Here is my code:
#include "stack.h"
void convert(string expression){
stack c;
string post = " ";
string rightop = "";
string leftop = "";
string op = "";
for (int i = 0; i <= expression.length(); i++){
c.push(expression[i]);
c.print();
if (expression[i] == '*' ||
expression[i] == '+' ||
expression[i] == '-' ||
expression[i] == '/'){
cout << c.top() << endl;
leftop = c.top();
cout << leftop << endl;
c.pop();
rightop = c.top();
cout << rightop << endl;
c.pop();
op = c.top();
cout << op << endl;
//c.pop();
post = "(" + leftop + " " + op + " " + rightop + ")";
cout << post << endl;
}
//c.push(post);
}
}
int main(){
string expression;
cout << " Enter a Post Fix expression: ";
getline(cin, expression);
convert(expression);
return 0;
}

The original code is lacking following declarations to compile :
#include "stack"
#include "string"
#include "iostream"
using namespace std;
Next, the type of the stack should be a string to be able to store full expressions onto it.
You did not take the elements in proper order from the stack : it is first op, next rightop and finally leftop
The currently commented out last c.pop() is necessary to remove 3rd element from the stack, but it must be followed inside the loop with the (again commented out) c.push(post);
The loop on expression goes one step too far : it should be for (int i =0; i<expression.length();i++) (note the < instead of <=)
When this is done, it is enough to make the convert function to return the last post as a string for the program to give expected result.
As you asked in this other question, it would be much better to ignore spaces in the input string : you should add if (isspace(expression[i])) continue; immediately after the for.
With all those fixes, the code could be :
#include <stack>
#include <string>
#include <iostream>
#include <cctypes>
using namespace std;
string convert(string expression){
stack<string> c;
string post =" ";
string rightop="";
string leftop="";
string op ="";
for (int i =0; i<expression.length();i++){
if (isspace(expression[i])) continue;
c.push(string(expression.c_str() + i, 1));
//c.print();
if(expression[i] == '*' ||
expression[i] == '+' ||
expression[i] == '-' ||
expression[i] == '/'){
cout<<c.top()<<endl;
op=c.top();
cout<<leftop<<endl;
c.pop();
rightop=c.top();
cout<<rightop<<endl;
c.pop();
leftop=c.top();
cout<<op<<endl;
c.pop();
post="(" + leftop + " " + op + " " + rightop + ")";
cout<<post<<endl;
c.push(post);
}
}
return post;
}
int main(){
string expression;
cout<<" Enter a Post Fix expression: ";
getline(cin,expression);
string converted = convert(expression);
cout << "Converted expression : " << converted << endl;
return 0;
}
And when given ab+cd*- you get at the end ((a + b) - (c * d))
You just have to comment out all the traces form convert method ;-)

i get the impression your "stack" is not used properly. e.g. if ab+* is pushed on the stack your variables become leftop = +, rightop = b, op = a, in order to convert a postfix expression it is easiest to create a binary evaluation tree to get the operator precedence right
e.g.
for ab+c* you want
*
/ \
+ c
/ \
a b
and then evaluate the tree either recursively or not. everytime the operator is + or - use parenthesis around it,

Related

C++ Recursion function

Good afternoon everyone, I am new to recursion and am trying to create a program to take user input to build a math function. It works when doing simple things such as 3 + 4, but when trying something like (3 + 4) + 6 the main prints an empty string. The purpose of the program is to place nested numbers inside parenthesis to make them clear to read. I have tried following the code, but the recursion seems to be what i don't understand. Thanks for your time and help.
Code
#include <iostream>
#include <string>
using namespace std;
string buildEq(bool nested, string tab);
int main()
{
cout << "Welcome to the equation builder!" << endl << endl;
cout << "Each step can only have one operation between two numbers." << endl;
cout << "So the equation (3 + 4) + 6 would have one 'nested' operation." << endl << endl;
string equation = buildEq(false, "");
cout << endl << "The equation you have built is... " << equation << endl;
cout << endl << "Thanks for coming!" << endl;
return 0;
}
string buildEq(bool nested, string tab)
{
string equation;
string nesting;
cout << tab << "For this step, is there nesting? (y/n): ";
cin >> nesting;
if(nesting == "y")
{
nested = true;
tab += "\t";
buildEq(true, tab);
}
else
{
int number = 0;
int operation_count = 1;
while(number < 2)
{
if(nested == true)
{
equation += "(";
}
string num= "";
cout << tab << "What number would you like to enter: ";
cin >> num;
equation += num+= " ";
number++;
while(operation_count == 1)
{
string operation;
cout << tab << "What operation would you like to perform? (+, -, /, *): ";
cin >> operation;
equation += operation += " ";
operation_count++;
}
if(nested == true && number == 2)
{
equation += ")";
}
}
}
return equation;
}
Correct output
Welcome to the equation builder!
Each step can only have one operation between two numbers.
So the equation (3 + 4) + 6 would have one 'nested' operation.
For this step, is there nesting? (y/n): n
What number would you like to enter: 3
What operation would you like to perform? (+, -, /, *): +
What number would you like to enter: 4
The equation you have built is... 3 + 4
Thanks for coming!
Press <RETURN> to close this window...
Function results empty
Welcome to the equation builder!
Each step can only have one operation between two numbers.
So the equation (3 + 4) + 6 would have one 'nested' operation.
For this step, is there nesting? (y/n): y
For this step, is there nesting? (y/n): n
What number would you like to enter: 3
What operation would you like to perform? (+, -, /, *): +
What number would you like to enter: 4
The equation you have built is...
Thanks for coming!
Press <RETURN> to close this window...
(Probably an overkill, but I don't think that the question itself is an easy example for understanding recursions)
In order to understand the recursion part, we need to look at the general problem, and understand how we progress from one invocation to another (the recursive step), and what is our stopping point (the base case) . Your goal here is to create a valid equation, in order to do so, your input should follow certain guidelines. Specifically, in order to verify such a problem, you need to verify that each input is following a syntax which is called Context Free Grammar, denoted by the following rules (N stands for number or nested, O for operation, D for digit and $ for nothing):
N -> ( N ) O | D O
D -> 0-9
O -> + N | - N | * N | / N | $
There are two recursions here. In each stage we need to get a valid equation, and those rules make sure it stays like that.
The following code is creating a proper equation from the user.
Notice a few important notes -
I'm using std::stringstream, which is more efficient at creating strings and appending to the existing "string".
You should not over-use std::endl, since in addition to adding a line break, it also flushes to the stdout, which is expensive.
Using "Using namespace std;" isn't a good habit!
Look at how I pass the same stringstream, and each stage adds to this, in order to create the general string. If your code doesn't add to the "carried" value, it means that you are doing nothing in this recursive step.
The code:
#include <sstream>
#include <iostream>
#include <string>
#include <cctype>
#include <assert.h>
void get_num_or_nested(std::stringstream& eq);
void get_operation_or_stop(std::stringstream& eq);
bool is_number(const std::string& s)
{
int digit_count = 0;
for (const char& character : s)
{
if (std::isdigit(character))
{
++digit_count;
}
}
return !s.empty() && s.size() == digit_count;
}
bool is_operation(char c)
{
return (c == '+' || c == '-' || c == '*' || c == '/');
}
std::string get_input_from_user()
{
std::string input;
std::cin >> input;
return input;
}
void get_operation_or_stop(std::stringstream& eq)
{
std::cout << "Insert one of the following:\n";
std::cout << "An operation - [ + | - | * | / ]\n";
std::cout << "s for Stop" << std::endl;
std::string input = get_input_from_user();
if (input.size() == 1)
{
if (is_operation(input[0]))
{
eq << input;
get_num_or_nested(eq);
}
else if (input != "s")
{
assert(false);
}
// stops!
}
else
{
assert(false);
}
}
void get_num_or_nested(std::stringstream& eq)
{
std::cout << "Insert one of the following:\n";
std::cout << "A number\n";
std::cout << "n for Nested" << std::endl;
std::string input = get_input_from_user();
if (input == "n")
{
eq << "(";
get_num_or_nested(eq);
eq << ")";
get_operation_or_stop(eq);
}
else if (is_number(input))
{
eq << input;
get_operation_or_stop(eq);
}
else
{
assert(false);
}
}
int main()
{
std::cout << "Welcome to the equation builder!\n" << std::endl;
std::stringstream eq;
get_num_or_nested(eq);
std::cout << "The equation you have built is... " << eq.str() << std::endl;
std::cout << "Thanks for coming!" << std::endl;
}
The only thing that is wrong is when the user says yes to nesting. Instead of calling the function and discarding what it returned, you need to return what the function returned.
if(nesting == "y")
{
nested = true;
tab += "\t";
return buildEq(true, tab);
}

String Comparison in C++ with IF Statements?

I'm very new to C++, just started learning using an online course about 30 minutes ago. I'm a little confused as to why this string comparison isn't working in a basic math script:
#include <iostream>
#include <string>
using namespace std;
int main() {
int one, two, answer;
char *oper;
cout << "Add two numbers\n\nEnter your first number" << endl;
cin >> one;
cout << "Choose an operator: + - * / %%" << endl;
cin >> oper;
cout << "Enter your second number" << endl;
cin >> two;
if (oper == "+") {
answer = one + two;
}
else if (oper == "-") {
answer = one - two;
}
else if (oper == "*") {
answer = one * two;
}
else if (oper == "/") {
answer = one / two;
}
else if (oper == "%%") {
answer = one % two;
}
cout << one << " " << oper << " " << two << " = " << answer << endl;
return 0;
}
The values for one, oper, and two are 1, "+", and 1 respectively, but in the end, 1 + 1 = 4201435 is printed out. None of the if/else if statements are being executed. What's causing this?
You're comparing char * using operator==. Either let oper be a std::string instead
std::string oper
To use the string comparison listed here: http://en.cppreference.com/w/cpp/string/basic_string/operator_cmp
or if you need to use a char * for some restriction, use strcmp:
if (!strcmp(oper, "+")) {
// ...
You also need to have your operand variable point at some buffer too, for the stream to read into. This is a little bit more complicated and I just recommend changing the type of oper to std::string.
The problem with the code you have is that it's comparing pointers to char arrays. What you get from your input methods is going to be a new string from the input stream and will never have the same address as the readonly strings in your program.
So since none of the condition is true, ans hasn't been assigned. So output it accounts for an undefined behavior.

Reverse Polish Notation Calculator in C++

I'm trying to code the RPN algorithm in C++, using a string as parameter.
I'm using a stack and a string to be read.
I know how the algorithm works, but I don't get a correct result, I always get 0. This is my code:
#include <iostream>
#include <stack>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
float RPN(string s) {
stack<int> p;
int n1, n2;
string values[s.size()];
for (unsigned int i = 0; i < s.size(); i++)
values[i] = s.at(i);
for (unsigned int i = 0; i < s.size(); i++) {
if (s.at(i) != '+' || s.at(i) != '-' || s.at(i) != '*'
|| s.at(i) != '/') {
int n;
istringstream(values[i]) >> n;
p.push(n);
}
else {
n1 = p.top();
p.pop();
n2 = p.top();
p.pop();
switch (s.at(i)) {
case '+':
p.push(n1 + n2);
break;
case '-':
p.push(n2 - n1);
break;
case '*':
p.push(n1 * n2);
break;
case '/':
p.push(n2 / n1);
break;
}
}
}
if (p.size()) {
int resul = p.top();
while (p.size())
p.pop();
return resul;
}
return 0;
}
This is the calling method:
void callRPN() {
string s1 = "56-";
string s2 = "65-";
string s3 = "843+2*-";
string s4 = "62+83-*4/";
cout << s1 << " valor: " << RPN(s1) << endl;
cout << s2 << " valor: " << RPN(s2) << endl;
cout << s3 << " valor: " << RPN(s3) << endl;
cout << s4 << " valor: " << RPN(s4) << endl;
}
And the console result:
56- valor: 0
65- valor: 0
843+2*- valor: 0
62+83-*4/ valor: 0
What is the error in my code? If someone could help me I would appreciate it. Thank you.
At least one major problem is that the inputs are invalid (they're not proper Reverse Polish Notation) and you don't check for invalid inputs.
A few points about the algorithm:
int resul = p.top();
// At this point, p.size() should be 1 - it should only contain the answer.
// If it's anything other than 1, the expression you were passed is wrong
// and you should throw an exception.
while (p.size())
p.pop();
Also, you should check to make sure that there are enough items on the stack when you do this:
n1 = p.top();
p.pop();
n2 = p.top();
p.pop();
If there aren't enough, you should throw an exception because that means that the input is invalid.
At least some of your Reverse Polish Notation inputs are incorrect, depending on how they're interpreted. For example, should 56- be interpreted as 5 - 6 or as 56 -? If it's the latter, then the following is incorrect:
62+83-*4/
This should actually throw an exception for the same reason as above. Try tracing through this; when you do 62 +, for example, 62 plus what? The correct way to do 62 + 83 in Reverse Polish Notation is 62 83 +. At that point, the stack should contain 145 and only 145 (meaning that it's invalid to do - or * at this point). If you're trying to do (62 + 83) / 4, the correct encoding is:
62 83 + 4 /
It's unclear what the -* part is supposed to do for the same reasons I mentioned above.
So, really, this should validate the input.
Perhaps more importantly, the following is incorrect:
if (s.at(i) != '+' || s.at(i) != '-' || s.at(i) != '*'
|| s.at(i) != '/') {
int n;
istringstream(values[i]) >> n;
p.push(n);
}
You should replace || with && here; you want to push onto the stack if it isn't any of the operators. In this case, it'll only push onto the stack if it's not a + operator (meaning that it'll try to push onto the stack if it's, for example, a - operator).

How to take a line as an input and not include spaces

I'm working on a project to convert from postfix to infix expressions. I was stuck for a while but I had part of it working then I realized I needed to inlcude a space between each of the operands when I input it to the user.I'm not sure how to take in a string and not include spaces how would I go about doing that. getline doesn't work as it includes spaces. therefore instead of ab+ I need to accept it as: a b +. i'm not sure how to do this not include the strings. Here is my code so far.
#include "stack.h"
void convert(string expression){
stack c;
string post =" ";
string rightop="";
string leftop="";
string op ="";
for (int i =0; i<=expression.length()-1;i++){
c.push(expression[i]);
c.print();
if (expression[i] == '*' ||
expression[i] == '+' ||
expression[i] == '-' ||
expression[i] == '/'){
cout<<c.top()<<endl;
leftop=c.top();
cout<<leftop<<endl;
c.pop();
rightop=c.top();
cout<<rightop<<endl;
c.pop();
op=c.top();
cout<<op<<endl;
c.top()=expression[i+1];
//c.pop();
post="(" + leftop + " " + op + " " + rightop + ")";
cout<<post<<endl;
}
//c.push(post);
}
}
int main(){
string expression;
cout<<" Enter a Post Fix expression: ";
getline(cin,expression);
convert(expression);
return 0;
}
In C, strings are essentially a bunch of character pointers. You can refer to this SO post for a few examples of how to remove white space from your input string by moving pointers.
You can test explicitely each character against " \t\r", or you can use the isspace function declared in cctypes :
for (int i =0; i<=expression.length()-1;i++){
if (isspace(expression[i])) continue;
// remaining unchanged ...
I've update my answer to your other question with that.

C++: Extract Tokens from String using only STL

I want to extract tokens from a given fraction expression, which is passed as a string,
Fraction s("-5 * 7/27");
Where the extracted tokens hold either a single operator or a sequence of digits as an operand, using the stl container only.
May someone guide me to do so? I want to know how to extract the tokens and differentiate the operand from operator, thank you.
Assuming there are always spaces between the tokens, here's how put them all in a queue:
#include <string>
#include <queue>
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
stringstream formula("-5 * 7/27");
string a_token;
queue<string> tokens;
// Use getline to extract the tokens, and then push them onto the queue.
while (getline(formula, a_token, ' ')) {
tokens.push( a_token );
}
// Print and pop each token.
while (tokens.empty() == false) {
cout << tokens.front() << endl;
tokens.pop();
}
}
Running the program will output:
-5
*
7/27
Now to determine which are operators, numbers, or fractions, you can do something like this in the loop:
if (a_token == "+" || a_token == "-" || a_token == "*" || a_token == "/")
{
// It's an operator
cout << "Operator: " << a_token << endl;
}
else
{
// Else it's a number or a fraction.
// Now try find a slash '/'.
size_t slash_pos = a_token.find('/');
// If we found one, it's a fraction.
if (slash_pos != string::npos) {
// So break it into A / B parts.
// From the start to before the slash.
string A = a_token.substr(0, slash_pos);
// From after the slash to the end.
string B = a_token.substr(slash_pos + 1);
cout << "Fraction: " << A << " over " << B << endl;
}
else
{
// Else it's just a number, not a fraction.
cout << "Number: " << a_token << endl;
}
}
This website: http://www.cplusplus.com/reference/string/string/ will give you information on the string functions.
After modifying the code and running it again, you'll get output like this:
Number: -5
Operator: *
Fraction: 7 over 27