Using Stacks In C++ for infix and postfix expressions - c++

I'm writing a program that takes user input and uses stacks to convert an infix expression into a postfix expression based on precedence, with operands always going before operators. For example, if a user inputs:
(a+b*c)
then the program should display:
abc*+
so far, I have this:
#include <iostream>
#include <stack>
#include <string>
using namespace std;
int main()
{
stack<char> s;
char input;
while (cin.get(input) && input != '\n')
{
if (isalnum(input))
cout << input << "\n";
else if (input == '(')
s.push(input);
else if (input == ')')
{
while (!s.empty() && s.top() != '(')
{
cout << s.top();
s.pop();
}
if(!s.empty())
s.pop();
else
cout << "ERROR: No Matching ( \n";
}
else if (s.empty() && input == '*'||'/'||'+'||'-' && s.top() < input) // Error Begins Here?
{
char a = '*';
char b = '/';
char c = '+';
char d = '-';
bool prec (char a, char b, char c, char d);
return ('*' > '/' > '+' > '-');
s.push(input);
}
else if (input == '*'||'/'||'+'||'-' && s.top() >= input)
while (!s.empty())
{
cout << s.top();
s.pop();
s.push(input);
}
}
while (!s.empty())
{
cout << s.top();
s.pop();
}
}
Which compiles and runs but is not functioning as it should. When an expression like "ab" is input, the program will display "ab" as it should but if I input "a+b+c", then only "a" will be displayed. This means the program is not placing the operators into the stack to be displayed later on. What I need help with is modifying the program so that when an operator is input, it should be added onto the stack and then displayed based on it's precedence (*>/>+>-) after the operands, when the input is done.
I'm quite new to C++ and programming in general, so any suggestions would be great.

else if (input == '*'||'/'||'+'||'-' && s.top() >= input)
This does not do what you think it does. You need to do
else if (input == '*'|| input == '/'|| input == '+'|| input == '-' && s.top() >= input)
And this looks like an error too
bool prec (char a, char b, char c, char d);
That's the syntax for a function prototype. Are you sure this compiles?

The problem is here:
bool prec (char a, char b, char c, char d);
return ('*' > '/' > '+' > '-');
I'm guessing this is intended to define a precedence function, but that's not what it's doing. The first line declares that such a function exists (and its arguments have nothing to do with the variables declared in the previous lines), and the second causes the whole program to terminate. If you want a function like this, you must define it outside main.
A slightly less dramatic bug is here:
if (s.empty() && input == '*'||'/'||'+'||'-' && s.top() < input)
First, this part
input == '*'||'/'||'+'||'-'
is interpreted as
(input == '*') || ('/') || ('+') || ('-')
The last three terms are true, the first is irrelevant. And I'm not even sure what s.top() does if s is empty.
This should be enough to go on. I suggest you start by building and testing routines that can, e.g., identify the operators and evaluate their precedence, before you try putting everything together in one program.

Falmarri is right just wanted to post that my self , and it compiles I tried it , but there is another thing : you said
else if (s.empty() && input == '*'||'/'||'+'||'-' && s.top() < input) // Error Begins Here?
Are you sure that even reached that point because when I runn it , it just stops on the :
while (cin.get(input) && input != '\n')
until I hit enter and even more you can enter more then one char from consol while in cin.get(input) but the input will contain only the first char you entered . To solve this I just put an
#include <conio.h>at the beginning an used
while ((input = getch()) && input != (char)13) in staid of you're code
short explanation
getch()
returns after you press only one character and
input != (char)13
is required in staid of
input != '\n'
because getch() return (char)13 for ENTER see ASCII table for more info.

Related

RE: Why am I getting the wrong value of vowels from this counter?... original code

Instructions:
using a value returning function
Write a program that prompts the user to input a sequence of characters and outputs the number of vowels.
This is the problem given by the instructor..
#include <iostream>
using namespace std;
bool isVowel(char ch);
int main() {
char ch;
cout << "Enter a character: ";
cin >> ch;
cout << ch << " is a vowel: " << isVowel(ch) << endl;
return 0;
}
bool isVowel(char ch){
if (ch=='A' || ch=='E' || ch=='I' || ch=='O' || ch=='U' ||
ch=='a' || ch=='e' || ch=='i' || ch=='o' || ch=='u'){
return true;
} else
return false;
}
char is a single character, not a sentence. For a sentence use a string.
string s;
cout << "Enter a sentence: ";
cin >> s;
Then use a loop to loop through each character of the sentence
for (char ch : s)
{
...
}
Then use isVowel to test a single character, and increment the count if found. The clue is in the name isVowel, not countVowels, so isVowel should test a single vowel and return true or false, not count the number of vowels.
int vowels = 0;
for (char ch : s)
{
if (isVowel(ch))
vowels++;
}
finally write isVowel to test a single character.
bool isVowel(char ch)
{
return ch=='A' || ch=='E' || ch=='I' || ch=='O' || ch=='U' ||
ch=='a' || ch=='e' || ch=='i' || ch=='o' || ch=='u';
}
There are several problems here.
Firstly, you don't initialize vowels. You presumably mean int vowels = 0; or int vowels {0};.
Secondly, you are reading a single character with cin >> ch;. I suspect you mean to loop over an input string.
Thirdly, your signature for isVowel is bool isVowel(int vowels, char ch);, which returns a bool. But you have written your function as thought it is manipulating an integer total of vowels. This inconsistency doesn't make sense.
Fourthly, you assign the result of isVowel to a character in ch = isVowel(vowels,ch);. Then you call isVowel again with this updated ch in cout << isVowel(vowels, ch) << .... I'm not sure what you're attempting to do here, but this also doesn't make any sense.
You need to revisit all of this code. You probably want isVowel to actually return a boolean. You probably want to iterate over an entire input string, and adjust the value of vowels appropriately (after initializing it).
Your program is running an undefined behavior; you are using vowels without being initialized.
You can make function that takes the counter of vowels as a reference to an integer for example.
void isVowel(int& counter, char ch) {
std::string vowels{ "AaEeIiOoUu" };
for (auto c : vowels)
if(ch == c)
counter++;
}
int main(){
char ch;
int counter{};
while (std::cin >> ch)
isVowel(counter, ch);
std::cout << counter << endl << " vowels in this sentence." << endl;
}
#include <iostream>
using namespace std;
bool isVowel(int vowels, char ch);
So isVowel returns a bool. That would make sense if its purpose was to tell us whether a single character was a vowel or not. For some reason, we pass an integer called vowels to it. That doesn't seem to make any sense. What would it do with an integer value?
int main() {
char ch;
So ch is a single character. Okay.
int vowels;
And vowels is an integer with no particular value.
cout << "Enter a sentence: ";
cin >> ch;
Uh oh. We ask the user to enter a sentence but then we read in a single character. Remember, ch was a char.
ch = isVowel(vowels,ch);
Uh oh. We didn't assign vowels any particular value, so we've passed no particular value to isVowel. Also, we took the boolean value returned and assigned to a variable of type char. Why would we do that?
cout << isVowel(vowels, ch) << " vowels in this sentence." << endl;
Then for some reason we call isVowel again. That doesn't make much sense. Also, isVowel returned a bool (a yes or no). Why are we outputting that as if it was the number of vowels?
return 0;
}
// build a string counter and make it callable
bool isVowel(int vowels, char ch){
Okay, so isVowel returns a boolean and takes as input an integer and a character.
for (int i = 0; i < ch; i++){
if (ch=='A' || ch=='E' || ch=='I' || ch=='O' || ch=='U' ||
ch=='a' || ch=='e' || ch=='i' || ch=='o' || ch=='u'){
vowels++;
}
We are looping from zero to the value of the single character? That doesn't make sense.
}
return vowels;
}
Lots of problems here. Because there are so many fundamental problems with this code, it seems you've attempted a problem that's way beyond your C++ knowledge and you should attempt something much simpler first, such as accepting a sentence as input and repeating it back to the user without using any additional functions.

how to only allow 3 values in a "if" and "while" statement to allow the loop to exit

I'm just stuck on some logic statements.
specifically the ones that are in the function char GetInteger() so how would I only allow 3 values to cause the loop to exit.
char GetInteger( /* out */ char& usrinput)
{
do
{
cin >> usrinput;
cin.ignore(200,'\n');
if (usrinput != 0 || usrinput != 1 || usrinput != 2)
{
cout << "Invalid Input." << userinput << " Try Again\n";
}
} while(usrinput != 0 || usrinput != 1 || usrinput != 2);
return userInput;
}
Two issues with this code:
First userinput has a type of char. So when you read from a stream you read a single character (after dropping white space). So when a user types 1<enter> you get the character '1' in the variable userinput. Note the character '1' is not the same as the number 1.
Thus your test should be:
userinput != '1';
Secondly your boolean logic is wrong. When first learning it is sometimes easier to state the problem as a list of values that you would like to be acceptable (not the unacceptable ones).
You want the conditions to be false if the userInput has one of your accepted values (any good value will fail the test and thus not invoke the bad code). The first step to this is to get a true if any of your values are valid.
// If any value is good then true.
userinput == '1' || userinput == '2' || userinput == '3'
To invert this just add a not to the expression.
if (! (userinput == '1' || userinput == '2' || userinput == '3') )
Note: in boolean logic
!(A || B) => (!A && !B)
So you could re-write the above as:
if (userinput != '1' && userinput != '2' && userinput != '3')
I think this was your main mistake you converted the == into != but did not convert the || into &&.
I would also suggest that you could simplify this (as you may get more valid result) byconverting this into a range based test.
if (userinput < '1' || userinput > '3')
{
// Test Failed.
}
Additionally. Since you have the test in two places. You should yank it outinto its own function. Then you can call the function to do the test.
bool isUserInputValid(char userInput)
{
return userInput >= '1' && userInput <= '3';
}
Now we can re-write your original function as:
char GetInteger( /* out */ char& usrinput)
{
do
{
cin >> usrinput;
cin.ignore(200,'\n');
if (!isUserInputValid(userinput))
{
cout << "Invalid Input." << userinput << " Try Again\n";
}
} while(!isUserInputValid(userinput));
return userInput;
}
First of all, you should use int instead of string as you are reading integer.
You can use while(1) instead of putting condition in while. Inside while loop, if your selection is 0 or 1 or 2, you can simply break the loop.

Delimiter matching simple program won't work

I have looked over this for hours it seems like. This program will compile, it just can't detect errors correctly. And for some reason it will work when I type in hey [) or hey {], etc. But it won't work for hey[) or hey{]. Obviously in all cases it should detect an error but for some reason the space after 'hey' makes a difference.
#include<iostream>
#include <stack>
using namespace std;
bool delimiterMatching(char *file){
stack<char> x;
int count = 0;
char ch, onTop, check;
while(ch != '\0'){
ch = file[count];
if (ch == '(' || ch == '[' || ch == '{')
x.push(ch);
else if (ch == ')' || ch == ']' || ch == '}') {
onTop == x.top();
x.pop();
if((ch==')' && onTop!='(') || (ch==']' && onTop!='[') || (ch=='}' &&
onTop!= '{'))
return false;
}
count++;
}
if (x.empty())
return true;
else
return false;
}
int main()
{
char *test = new char();
cout << "enter sentence: ";
cin >> test;
if (delimiterMatching(test))
cout << "success" << endl;
else
cout << "error" << endl;
return 1;
}
With cin >> test you don't get a whole sentence, but only a string until cin encounters whitespace. So if you type (hey ), thest would be (hey and the closing brace would only be read by the next >>, whereas (hey) would work as expected.
You have a second issue with your test allocation, which might be too short for reasonable input.
Change main() as follows:
char *test = new char[256]; // enough space. COnsider also string
cout << "enter sentence: ";
cin.getline(test, 256); // full line input.
...
You have also two nasty bugs in delimiterMatching().
First you use an uninitialized ch in your while condition. Either initialise ch to a non nul char, or use while (file[count]).
And did you notice onTop == x.top(); ? Shouldn't it be onTop = x.top();?

Char validator will not only accept lower and upper case M/F

Hey im trying to validate a char to limit it to accpeting an m or f for male or female. But it doesnt pass the while condition even when m or f is pressed and keeps looping the question.
Can anybody help me with this.
Thanks in advance.
Here is my code:
char Validator :: getChar(string q)
{
char input;
do
{
cout << q.c_str() << endl;
cin >> input;
}
while(!isalpha(input) && "M"||"F"||"m"||"f");
return input;
}
The "M"||"F"||"m"||"f" part of your code doesn't do what you think it does. What it does is check the ADDRESSES of those string constants. Since they are all non-NULL, this expression simply returns true, so your condition, essentially becomes: while(!isalpha(input) && true) which is the same as while(!isalpha(input)).
Try this instead:
char Validator::getChar(const string &q)
{
char input = 0;
do
{
cout << q << endl;
cin >> input;
}
while((input != 'M') && (input != 'F') && (input != 'm') && (input != 'f'));
return input;
}
The expression in the while doesn't mean what you think it does. First, the ! does not apply to the entire expression, and second, "equality" is not an implicit test. You need to write out everything you mean.
To test for equality, use the == or != operators. You have to use the operators on every value you want to test; the operator doesn't "distribute" over a list of values like it would in ordinary English. Write your condition like this:
while (input != 'M' && input != 'F' && input != 'm' && input != 'f');
You can see that the isalpha call isn't necessary; if input isn't equal to any of the listed values, then it doesn't really matter whether it's an alphabetical character.
Another way to write it is this:
while (!(input == 'M' || input == 'F' || input == 'm' || input == 'f'));
Notice that I've another set of parentheses around the internal terms so that the ! operator applies to the entire expression instead of just the first term.
Just for an alternative approach to the terminating condition:
char Validator::getChar(const string &q)
{
const std::set<char> valid_chars { 'M', 'm', 'F', 'f' };
char input = 0;
do
{
cout << q << endl;
cin >> input;
}
while (!valid_chars.count(q));
return input;
}

Need Help Using "Sort" Within My Program

I have a simple program that lists input in order of precedence, checking only for operators and ranking them like so, "*/+-":
#include <iostream>
#include <stack>
#include <string>
using namespace std;
int prec(char op)
{
if (op == '*' || op == '/') return 0;
return 1;
}
bool compareprec(char a, char b)
{
return prec(a) < prec(b);
}
int main()
{
char input[] = "+-/*";
cin >> input;
sort(input, input + 4, &compareprec);
cout << input;
}
I'm trying to implement it within a more complex program that uses stacks to check alpha numerical input and do an infix to postfix conversion, ranking something that looks like this: "9*9+9" into "9 9 9 * +". The more complex program is as follows:
#include <iostream>
#include <stack>
#include <string>
using namespace std;
int prec(char op)
{
if (op == '*' || op == '/' || op == '+' || op == '-') return 0;
return 1;
}
bool compareprec(char a, char b)
{
return prec(a) < prec(b);
}
int main()
{
stack<char> s;
char input;
while (cin.get(input) && input != '\n')
{
if (isalnum(input))
cout << input << " ";
else if (input == '(')
s.push(input);
else if (input == ')')
{
while (!s.empty() && s.top() != '(')
{
cout << s.top() << " ";
s.pop();
}
if(!s.empty())
s.pop();
else
cout << "ERROR: No Matching ( \n";
}
else if (s.empty() && input == '*'|| input == '/'|| input == '+'|| input == '-')
{
sort(input, input + 4, &compareprec); // Error Begins Here?
s.push(input);
}
else if (input == '*'||input == '/'||input == '+'|| input =='-')
while (!s.empty())
{
sort(input, input + 4, &compareprec); // More Errors Here?
cout << s.top() << "\n ";
s.pop();
s.push(input);
}
}
while (!s.empty())
{
cout << s.top() << " ";
s.pop();
}
}
But I keep getting an error that says:
error: no matching function for call to 'sort(char&, int, bool (*)(char, char))'
error: no matching function for call to 'sort(char&, int, bool (*)(char, char))'
And I'm not sure why. I know it's probably something painfully obvious/silly but I can't figure it out. Any help would be appreciated. Thanks in advance!
sort expects something that can be iterated over.
Your working example has
char input[]
(an array of char)
Your non working example removes the array syntax and makes it a plain char
char input
When you attempt to do:
sort(input, input + 4, &compareprec)
In the working case, because you are providing an array, you're telling it to iterate from the beginning of input to 4 past the location. In the non-working case you're telling it to go from say 'a' to 'd' (which is 'a' + 4).
Why do you have to sort anything in the second example? You have maximally two operators you have to compare, one on the top of the stack and one in the input. Just use your compareprec-function and act accordingly based on the result.
And by the way, to make your code a little prettier, create a function:
bool is_operator(char s);
Almost forgot to tell you, the version of int prec(char a) in the second example is wrong, use the first one.