Converting infix to postfix notation - c++

I am doing infix to postfix notation. My program compiles, although, for some reason it will not take in any infix expressions, only postfix expressions. Which is the opposite I wanted to do. Here is my program:
#include <iostream>
#include <string>
#include <sstream>
#include "stack"
using namespace std;
string infixexpr (istream& in)
{
//Holds value in computation
stack<string> postfixstack;
//used to to read in characters from the expression
char ch;
// used to read in numbers from expression
int num;
// Used to remove infix expressions from stack
string lexpr, rexpr;
ch = in.peek();
while ( ch != EOF)
{
//If we have a whitespace character skip it and continue with
// the end of the loop.
if(isspace(ch))
{
ch = in.get();
ch =in.peek();
continue;
}
//nonspace character is next to input stream
// if the next character is a number read it and convert it
// to string then put the string onto the postfix stack
if (isdigit (ch))
{
in >> num;
// use to convert string
ostringstream numberstr;
// convert to number using sstream
numberstr << num;
// Push the representing string onto stack0
postfixstack.push(numberstr.str());
ch = in.peek();
continue;
}
// if operator pop the two postfix expressions
// stored on the stack, put the operator after
postfixstack.pop();
lexpr = postfixstack.top();
postfixstack.pop();
if (ch == '+' || ch == '-' || + ch == '*' || ch == '/' || ch == '%')
postfixstack.push(rexpr + " " + lexpr + " " + ch);
else
{
cout << "Error in input expression" << endl;
exit(1);
}
ch = in.get();
ch = in.peek();
}
return postfixstack.top();
}
int main()
{
string input;
cout << "Enter a infix expression to convert to postfix,"
<< " \nor a blank line to quit the program:";
getline(cin,input);
while (input.size() != 0 )
{
//convert string to a string stream
istringstream inputExpr(input);
cout << "the infix equavilent is: "
<< infixexpr(inputExpr) << endl;
cout << "Enter a infix Expression to evaluate: ";
getline(cin,input);
}
return 0;
}
For example the program runs like this:
if I enter 56 2 + (add spaces after each number or operator)
I'll get back 56 2 +, which is what I want. But if I enter
56 + 2, the program will crash.
If you like to see my stack class and header, if that is the problem please let me know. I can post it under reply.

Oh my, where to begin. You should probably take this to the Code Review Stack Exchange instead, but let's get into it:
You don't describe the "crash", so we don't know what failure you're observing.
Your "if the next character is a number read it and convert it to string then put the string onto the postfix stack" code pushes the operand on the stack. But in Dijkstra's shunting-yard algorithm, which you appear to be trying to implement, only operators go on the stack.
Your "if operator pop the two postfix expressions stored on the stack, put the operator after" code doesn't guard against popping items off an empty stack.
That same code also pops two items off the stack, but you only pushed one on - the "56" in "56 + 2". Since you're forcing me to guess, I'm guessing this is where the program crashes.
That same code also pushes the result onto the stack, another example of how not to implement the shunting-yard algorithm.

Related

Code keeps printing "1" when everything is correct

The code runs and all but it doesn't print out the vowels, but instead prints a "1".
#include <iostream>
#include <string>
using namespace std;
int countVowels(string sentence,int numVowels)
{
for(int i =0; i<sentence.length(); i++)
{
if((sentence[i]==('a'))||(sentence[i]==('e'))||(sentence[i]==('i'))||(sentence[i]==('o'))||(sentence[i]==('u'))||(sentence[i]==('A'))||(sentence[i]==('E'))||(sentence[i]==('I'))||(sentence[i]==('O'))||(sentence[i]==('U')))
numVowels=numVowels+1;
}
}
int main()
{
string sentence;
int numVowels = 0;
do{
cout << "Enter a sentence or q to quit: ";
cin >> ws;
getline(cin,sentence);
}
if(sentence == 'q'|| sentence == 'Q');
cout << "There are " << countVowels << " vowels in your sentence." << endl;
return 0;
}
The output should be like this:
Enter a sentence or a to quit: I like apples!
There are 4 vowels in your sentence, and 11 letters.
Enter a sentence or q to quit: q
Bye!
My problem:
Can someone explain to me why it keeps printing a "1", and my "if" statement where I am supposed to assign the hotkey "q" to exit the program isn't working. When I run the program I get an error at the if statement saying "no match for operators=="
I usually don't like just providing a full solution, but since your question shows you have made a good effort, here's how I would write it (well, not quite, I simplified a little to be more beginner friendly):
#include <algorithm>
#include <iostream>
#include <string>
bool isVowel(char c)
{
// A simple function that returns true if the character passed in matches
// any of the list of vowels, and returns false on any other input.
if ( 'a' == c ||
'e' == c ||
'i' == c ||
'o' == c ||
'u' == c ||
'A' == c ||
'E' == c ||
'I' == c ||
'O' == c ||
'U' == c) {
return true; // return true if it's a vowel
}
return false; // remember to return false if it isn't
}
std::size_t countVowels(std::string const& sentence)
{
// Use the standard count_if algorithm to loop over the string and count
// all characters that the predicate returns true for.
// Note that we return the resulting total.
return std::count_if(std::begin(sentence),
std::end (sentence),
isVowel);
}
int main() {
std::string sentence;
std::cout << "Please enter a sentence, or q to quit: ";
std::getline(std::cin, sentence);
if ( "q" == sentence ||
"Q" == sentence) {
// Quit if the user entered a string containing just a single letter q.
// Note we compare against a string literal, not a single character.
return 0;
}
// Call the counting function and print the result.
std::cout << "There are "
<< countVowels(sentence) // Call the function on the input.
<< " vowels in your sentence\n";
return 0;
}
Hopefully the comments make it all clear.
Now you might have been told that you can't use the standard algorithms (std::count_if), since part of the exercise seems to be to write that. Well I'll leave that to you. Your current version is close to correct, but remember to return the result. And you don't really need to pass in the numVowels count, just create that within the function, and remember to return it.

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.

Converting from Infix to Postfix using stacks (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,

C++ I can't compare char variable to values [duplicate]

This question already has answers here:
Single quotes vs. double quotes in C or C++
(15 answers)
Closed 4 years ago.
Have to do this for the first cs course I'm taking. It's a basic calculator that takes an operator and a value and calculates the total (total beginning at 0).
#include <iostream>
using namespace std;
int main()
{
char oprtr;
float value, total = 0.0;
cin >> oprtr >> value;
while (oprtr != "q")
{
if (oprtr == "+")
total += value;
else if (oprtr == "-")
total -= value;
}
}
It's not finished but already having issues with it. It gives errors saying something along the lines of "prohibits comparing char values to int values"
Double quotes ("q") are for strings. Single quotes ('q') are for characters.
So:
while (oprtr != 'q')
{
if (oprtr == '+')
total += value;
else if (oprtr == '-')
total -= value;
}
Char means Character and you must use single quotes '' for these, double quotes "" are for strings.
The reason you are getting this error is because you're attempting to compare a character to a string literal (a const char), the exact error you're getting will be:
Operand types are incompatible ("char" and "const char").
The below code will fix this error:
#include <iostream>
using namespace std;
int main()
{
char oprtr;
float value, total = 0.0;
cin >> oprtr >> value;
while (oprtr != 'q')
{
if (oprtr == '+')
total += value;
else if (oprtr == '-')
total -= value;
}
}
And also, since you are reading the statement or the expression once, there is no need for you to loop while the character is not equal to 'q'. You should basically perform one operation. Also, switch is a very useful construct for comparing literals instead of several if's. So I would simplify that as.
#include <iostream>
using namespace std;
int main(){
char op;
float value, total = 0.0;
cin >> op >> value;
//it is important at this stage to check for errors, as they are most likely
//to occur.
if(!cin){
cerr << "Error: format unknown! \n"; //basic error handled here, the prog outputs the error
}
//now perform the calculation
switch(op){
case '+': total += value;
break;
case '-' : total -= value;
break;
case 'q' : break; //i presume q is your quit character
default: /*unknown character*/ cerr << "Unknown operation! \n";
}
cout << "Total: "<<total << endl;
return 0;
}
this basically reads in one expression and add it to the total. You can modify it to read as long as you want.
Comparing string length is a common function in C programming, as it allows you to see which string contains more characters. This is very useful for sorting data. Comparing strings requires a special function; do not use != or ==.
http://www.techonthenet.com/c_language/standard_library_functions/string_h/strcmp.php

How to properly use cin.peek()

This function is supposed to read a fraction and place it in an array. If the user enters '0' the function is supposed to exit. I am trying to do this using the cin.peek() function but execution always goes into the if statement and doesn't allow the user to exit.
How should I properly code this (I am open to not using peek(), I thought it was the simplest way of doing it.)
Thanks!
void enterFrac(Fraction* fracs[], int& index)
{
int n, d;
char c, slash;
cout << "Enter fractions (end by entering a 0): ";
c = cin.peek();
if ( c != '0')
{
cin >> n >> slash >> d;
Fraction* f = new Fraction();
f->num = n;
f->den = d;
fracs[index] = f;
index++;
}
}
This test of peek() works however:
#include <iostream>
using namespace std;
int main () {
char c;
int n;
char str[256];
cout << "Enter a number or a word: ";
c=cin.peek();
if ( (c >= '0') && (c <= '9') )
{
cin >> n;
cout << "You have entered number " << n << endl;
}
else
{
cin >> str;
cout << " You have entered word " << str << endl;
}
return 0;
}
There are two issues with your use of std::istream::peek():
This function access the next character and does not skip leading whitespace. You probably want to skip leading whitespace before determining what the next character is, e.g., using the manipulator std::ws: (std::cin >> std::ws).peek().
The result from std::istream::peek() is not a char. Instead, it is an std::char_traits<char>::int_type (which is a fancy spelling of int). The result may, e.g., be std::char_traits<char>::eof() and if the value of '0' happens to be negative (I'm not aware of any platform where it is; however, e.g., the funny character from my name 'ΓΌ' is a negative value on platforms where char is signed) you wouldn't get the correct result, either. That is, you normally compare the result of std::istream::peek() against the result of std::char_traits<char>::to_int_type(), i.e., you'd use something like this: std::cin.peek() == std::char_traits<char>::to_int_type('0')
That said, your program doesn't check whether it could successfully read the nominator and the denominator, separated by a slash. You always want to verify that reading was successful, e.g., using something like
if ((std::cin >> nominator >> slash >> denominator) && slash == '/') {
...
}
Just for entertainment, you can create a manipulator for testing that a character is a slash, indeed:
std::istream& slash(std::istream& in) {
if ((in >> std::ws).peek() != std::char_traits<char>::to_int_type('/')) {
in.setstate(std::ios_base::failbit);
}
return in;
}
This way, you'd encapsulate the test for slash. If you need to use this in multiple places this is quite handy.