my c++ postfix converter using stack library - c++

I'm second year in CS
I'm trying to create infix to postfix converter
with this steps:
1.if the char is digit print
2- if it is '(' then add it to the stack
3-if it is ')' then pop to the output until it reaches '('
4- if it is operator the pop from the stack until it can be pushed
into the stack depending on the priority of operators
5- show the
final postfix equation
the problem is I need a loop to scan all the equation characters but I didn't know how to do it
below is my C++ code
#include <iostream>
#include <stack>
#include <cstdio>
using namespace std;
void scan(char);
int priority(char);
void st(char);
void move(char);
char expr;
int main() {
cout << "enter an formula: ";
cin >> expr;
scan(expr);
return 0;
}
void scan(char exp) {
if (isdigit(exp)) {
expr = putchar(exp);
move(exp);
}
else {
st(exp);
move(exp);
}
}
void move(char exp) {
if (expr == exp)
expr = getchar();
}
int priority(char exp) {
if (exp == '(')
return 1;
else if (exp == ')')
return 2;
else if (exp == '%' || exp == '/' || exp == '*')
return 3;
else if (exp == '+' || exp == '-')
return 4;
return 0;
}
void st(char op) {
std::stack<char> stack1;
if (priority(op) == 1) {
stack1.push(op);
}
else if (priority(op) == 2) {
while (stack1.top() != '(') {
putchar(stack1.top());
}
stack1.top();
}
else if (priority(op) == 3) {
if (stack1.empty()) { stack1.push(op); }
if (stack1.top() == '%' || stack1.top() == '/' || stack1.top() == '*')
{
putchar(stack1.top());
}
if (stack1.top() == '+' || stack1.top() == '-') { stack1.push(op); }
}
else if (priority(op) == 4) {
if (stack1.empty()) { stack1.push(op); }
if (stack1.top() == '%' || stack1.top() == '/' || stack1.top() == '*')
{
putchar(stack1.top());
}
if (stack1.top() == '+' || stack1.top() == '-') { putchar(stack1.top()); }
}
}

So I think the mistake is here
char expr;
In C++ char is a type for a single character. It you want a string of characters use the type std::string (and also #include <string>)
string expr;
Then loop through the equation like this
for (char ch : expr)
scan(ch);

Related

Stack Infix to Prefix not working correctly

I have an assignment to make a program that converts Infix to Prefix in C++. I have written a code to do so but the problem is I am only getting the operands and not the operators in the final result. I have checked my code many time, dry run it, but I cant find the problem. Here is the code:
#include <iostream>
#include <stack>
#include <algorithm>
using namespace std;
int Prec(char c)
{
if(c == '^')
{
return 3;
}
else if(c == '*' || c == '/')
{
return 2;
}
else if(c == '+' || c == '-')
{
return 1;
}
else
{
return -1;
}
} // prec
string InfixToPrefix(string s)
{
reverse(s.begin(), s.end());
stack<char> st;
string res;
for(int i=0; i<s.length(); i++)
{
if((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z'))
{
res += s[i];
}
else if(s[i] == ')')
{
st.push(s[i]);
}
else if(s[i] == '(')
{
while(!st.empty() && st.top() != ')')
{
res += st.top();
st.pop();
}
if(!st.empty())
{
st.pop();
}
else
{
while(!st.empty() && Prec(st.top()) >= Prec(s[i]))
{
res += st.top();
st.pop();
}
st.push(s[i]);
}
}
} // for loop
while(!st.empty())
{
res+=st.top();
st.pop();
}
reverse(res.begin(), res.end());
return res;
} // InfixToPrefix()
int main()
{
cout<<InfixToPrefix("(a-b/c)*(a/k-l)")<<endl;
}
Can someone please help?
The correct output should be "*-a/bc-/akl" but I am only getting "abcakl". Please help. Thank you.
You need to put the operator logic in the mainloop.
#include <iostream>
#include <stack>
#include <algorithm>
using namespace std;
int Prec(char c)
{
if(c == '^')
{
return 3;
}
else if(c == '*' || c == '/')
{
return 2;
}
else if(c == '+' || c == '-')
{
return 1;
}
else
{
return -1;
}
} // prec
string InfixToPrefix(string s)
{
reverse(s.begin(), s.end());
stack<char> st;
string res;
for(int i=0; i<s.length(); i++)
{
if((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z'))
{
res += s[i];
}
else if(s[i] == ')')
{
st.push(s[i]);
}
else if(s[i] == '(')
{
while(!st.empty() && st.top() != ')')
{
res += st.top();
st.pop();
}
if(!st.empty())
{
st.pop();
}
else
{
while(!st.empty() && Prec(st.top()) >= Prec(s[i]))
{
res += st.top();
st.pop();
}
st.push(s[i]);
}
}
else { // added operator logic to the main portion of the parse loop
if (!st.empty() && Prec(st.top()) >= Prec(s[i])){
res += st.top();
st.pop();
}
st.push(s[i]);
}
} // for loop
while(!st.empty())
{
res+=st.top();
st.pop();
}
reverse(res.begin(), res.end());
return res;
} // InfixToPrefix()
int main()
{
cout<<InfixToPrefix("(a-b/c)*(a/k-l)")<<endl;
}

Unexpected answer for a simple stack problem in C++

class Solution {
public:
bool isValid(string s) {
map<char , char> m;
m[')'] = '(';
m['}'] = '{';
m[']'] = '[';
stack<char> st;
if(s[0] != '(' || s[0] != '{' || s[0] != '[')
return "false";
for(int i = 0; i<s.length(); i++)
{
if(s[i] == '(' || s[i]== '{' || s[i]== '[')
{
st.push(s[i]);
}
else if(st.top() == m[s[i]])
{
st.pop();
}
else if(st.top() != m[s[i]])
{
return "false";
}
}
if(st.empty())
return "true";
else
return "false";
}
};
The code fails for a basic example such as "(]". I don't understand how this is possible.
( first goes in the stack
( is not the map for ]
So it should return "false". But it returns true.
Regarding your expression:
(s[0] != '(' || s[0] != '{' || s[0] != '[')
For a start, unless s[0] is some weird quantum variable that can be three things at once, that expression will never be false. Think about some possibilities:
Character != '(' != '{' != '[' || all
--------- ------ ------ ------ ------
( false true true true
{ true false true true
[ true true false true
x true true true true
As you can see, every character will have that expression evaluating as true. You probably should be using && rather than ||.
In addition, you return a C-style string from your function which, being a non-zero pointer, will translate to true in a boolean context, as evidenced by:
#include <iostream>
bool returnT() { return "true"; }
bool returnF() { return "false"; }
int main() {
std::cout << returnT() << '\n';
std::cout << returnF() << '\n';
}
which outputs:
1
1
So I would be more inclined to start with something like this:
class Solution {
public:
bool isValid(string s) {
stack<char> st;
map<char, char> m;
m[')'] = '('; m['}'] = '{'; m[']'] = '[';
if (s[0] != '(' && s[0] != '{' && s[0] != '[') {
return false;
}
for (int i = 0; i < s.length(); ++i) {
if (s[i] == '(' || s[i]== '{' || s[i]== '[') {
st.push(s[i]);
} else if (st.top() == m[s[i]]) {
st.pop();
} else if (st.top() != m[s[i]]) {
return false;
}
}
return st.empty();
}
};
But do watch out for one thing. If your valid input characters are limited to the six brackets, you should be okay.
But if you want to allow for other characters that don't affect the stack, such as with:
[14^{6+(2x3)}]
then your code will not work because the first 1 character will be considered a mismatch. To handle that, you'll need to modify it to take them into account.
For example:
for (int i = 0; i < s.length(); ++i) {
if (s[i] == '(' || s[i]== '{' || s[i]== '[') {
// Handle open brackets: store.
st.push(s[i]);
} else if (s[i] == ')' || s[i]== '}' || s[i]== ']') {
// Handle close brackets: check.
if (st.top() == m[s[i]]) {
st.pop();
} else {
return false;
}
}
// Anything else is just a "noise" character, ignore.
}
Apparently, a ')' must be close to '(' in ascii code.
class Solution {
public:
bool isValid(string s) {
stack<char> st; st.push('\0');
for (auto c : s) {
if (isalpha(c)) continue;
else if (c - st.top() <= 3 && c - st.top() > 0)
st.pop();
else
st.push(c);
}
return st.size() == 1;
}
};
int main() {
Solution solu;
cout << solu.isValid("[](){}") << endl;
cout << solu.isValid(")(") << endl;
}

C++ Bug fixing: Hawaiian Pronunciation Program

I am writing a C++ program that will show you how to pronounce a Hawaiian word.
Rules:
p, k, h, l, m, n (Pronounced like the english versions.)
w -start of word (Either pronounced as a w or a v sound. We shall pronounce it as a w sound.)
w -after the letter ‘a’ (Either pronounced as a w or a v sound. We shall pronounce it as a w sound.)
w -after ‘i’ or ‘e’ (Pronounced as a v sound.)
w -after ‘u’ or o (Pronounced as a w sound.)
My progress: My program works, but there's a couple of bugs.
When I type "iwa", the pronunciation must be "ee-vah" but I'm
getting "ee-wah".
My code is not ignoring whitespaces. So when I type "e komo mai", I want "eh koh-moh meye" but instead, I get "e komo mai is pronounced eh-eh-koh-moh-oh-meye".
Here is my code:
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
string convertToHawaiian(string input);
bool vowelGroup(char first, char next, string& replacement);
bool consonantGroup(char prevchar, char currchar, string& replacement);
bool singleVowel(char current, string& replacement);
int main() {
// Declare my variables
string userInput;
string replacement;
//cout << "Enter a hawaiian word to pronounce ==>";
getline(cin,userInput);
// For loop that will call my Consonant function
// Call my Hawaiian function and put it
// into pronunciation
replacement = convertToHawaiian(userInput);
// if My initial input has a capital, the replacement
// will keep the capital letter at the beginning
if (isupper(userInput.at(0))) {
replacement.at(0) = toupper(replacement.at(0));
}
// Get rid of the '-' character at the end of the string
if (replacement.at(replacement.size() - 1) == '-') {
replacement.pop_back();
}
cout << userInput << " is pronounced " << replacement << endl;
return 0;
}
// My main function that will convert my input
// into the hawaiian pronunciation
string convertToHawaiian(string input) {
char nextChar;
string replacement = "";
string result = "";
// Iterate through my string to check for vowels,
// vowelgroups and consonants.
for (unsigned int i = 0; i < input.size(); i++) {
char character = input.at(i);
character = tolower(character);
if (i != input.size() - 1) {
nextChar = input.at(i + 1);
nextChar = tolower(nextChar);
}
if ((i != input.size() - 1) && (vowelGroup(character, nextChar, replacement))) {
i++;
result = result + replacement;
}
else if (singleVowel(character, replacement)) {
result = result + replacement;
}
else {
consonantGroup(character, nextChar, replacement);
result = result + replacement;
}
}
return result;
}
bool vowelGroup (char first, char nextChar, string& result) {
bool isVowel = true;
if (first == 'a') {
nextChar = tolower(nextChar);
if ((nextChar == 'i') || (nextChar == 'e')) {
result = "eye-";
}
else if ((nextChar == 'o') || (nextChar == 'u')) {
result = "ow-";
}
else {
return false;
}
}
else if (first == 'e') {
nextChar = tolower(nextChar);
if (nextChar == 'i') {
result = "ay-";
}
else if (nextChar == 'u') {
result = "eh-oo-";
}
else {
return false;
}
}
else if (first == 'i') {
nextChar = tolower(nextChar);
if (nextChar == 'u') {
result = "ew-";
}
else {
return false;
}
}
else if (first == 'o') {
nextChar = tolower(nextChar);
if (nextChar == 'i') {
result = "oy-";
}
else if (nextChar == 'u') {
result = "ow-";
}
else {
return false;
}
}
else if (first == 'u') {
nextChar = tolower(nextChar);
if (nextChar == 'i') {
result = "ooey-";
}
else {
return false;
}
}
else {
isVowel = false;
return isVowel;
}
return isVowel;
}
// Check to verify consonants
bool consonantGroup(char character, char nextChar, string& replacement) {
bool isConson = true;
if ((character == 'p') || (character == 'k') || (character == 'h') || (character == 'l') || (character == 'm') || (character == 'n')){
replacement = character;
return isConson;
}
if ((character == 'w') && (nextChar == 'a')) {
replacement = 'w';
return isConson;
}
else if (((character == 'u') || (character == 'o')) && (nextChar == 'w')) {
replacement = 'w';
cout << "Not replacing w" << endl;
return isConson;
}
else if (((character == 'i') || (character == 'e')) && (nextChar == 'w')) {
replacement = 'v';
return isConson;
}
else {
isConson = false;
return isConson;
}
}
bool singleVowel(char current, string& result) {
bool isVowel = true;
if (current == 'a') {
result = "ah-";
return isVowel;
}
else if (current == 'e') {
result = "eh-";
return isVowel;
}
else if (current == 'i') {
result = "ee-";
return isVowel;
}
else if (current == 'o') {
result = "oh-";
return isVowel;
}
else if (current == 'u') {
result = "oo-";
return isVowel;
}
else {
isVowel = false;
return isVowel;
}
}
One of the more common sources of bugs is shared mutable state.
In your case, it is state shared between loop iterations.
The whitespace case is handled here:
else {
consonantGroup(character, nextChar, replacement);
result = result + replacement;
}
and in that case, replacement will be string "spilled over" from the previous iteration.
The remedy is very simple: declare replacement inside the loop instead.
You can solve the "iwa" problem if you stare at these lines until you spot the bug:
if ((character == 'w') && (nextChar == 'a')) {
replacement = 'w';

How to fix runtime error in Shunting Yard algorithm

I have implemented Shunting yard algorithm using stack in c++.
Well it is working quite well on inputs from SPOJ example inputs but when I input:
1
(((a+b) * (c+r)^(t+b)-n)^(c-(d * e))-b)+(c+(e-(d^r)))
I get a runtime error.
Note: I only get a runtime error when I call infixToPostfix() and use the above input and not when I comment it out.
Submission to SPOJ and running on ideone(with input above) results in a runtime error.
I really can't understand this behaviour of my program, so any help is welcomed.
I have tried some random inputs and it seems to work fine on them.
Even though they had spaces around operators.
#include<iostream>
#include<vector>
#include<math.h>
#include<stack>
#include<strings.h>
using namespace std;
void infixToPostfix(string st);
int pr(char s);
int main() {
int t;
scanf("%d",&t);
cin.ignore();
string st; // input string
while(t--)
{
getline(cin,st);
cin.sync();
cout<<st<<endl;
infixToPostfix(st);
}
return 0;
}
int pr(char s) // to check precedence
{
if(s == '^')
{
return 4;
}
else if(s == '*')
{
return 3;
}
else if(s == '/')
{
return 3;
}
else if(s == '+')
{
return 2;
}
else if(s == '-')
{
return 2;
}
else {
return 0;
}
}
void infixToPostfix(string st)
{
stack<char>op; //stack to hold operators and bracket
st += 'n';
int l = st.size();
op.push('0');
string fst; //final string
for(int x = 0;x<l;x++)
{
if(st[x] == '(')
{
op.push(st[x]);
}
else if(st[x] == ')')
{
while(op.top() != '(' && !op.empty())
{
fst +=op.top();
op.pop();
}
op.pop();
}
else if(st[x] == '+' || st[x] == '-' || st[x] == '*' ||st[x] == '/' ||st[x] == '^')
{
if(pr(st[x]) <= pr(op.top()))
{
fst += op.top();
op.pop();
op.push(st[x]);
}
else{
op.push(st[x]);
}
}
else if(st[x] == 'n'){
while(op.size() != 0)
{
if(op.top() != '0')
{fst += op.top();}
op.pop();
}
}
else if((st[x] >= 'a' || st[x] <= 'z' )&& st[x] != ' ')
{
fst += st[x];
}
}
printf("%s\n",fst.c_str());
}

Conversion of infix to postfix: stack is not recognized error

I am a beginner using the stack so I been trying to do different exercises on it. I'm trying to convert infix->postfix. The xcode debugger says "Use of class template 'stack'requires template arguments'. Here is my code.
#include<iostream>
#include<stack>
#include<string>
using namespace std;
bool IsOperand(char ch)
{
if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
return true;
}
return false;
}
bool IsOperator(char C)
{
if (C == '+' || C == '-' || C == '*' || C == '/' || C == '^') {
return true;
}
return false;
}
bool IsLeftParenthesis(char ch)
{
if (ch == '(') {
return true;
}
return false;
}
bool IsRightParenthesis(char ch)
{
if (ch == ')') {
return true;
}
return false;
}
bool Flag(char ch)
{
if (!IsOperand(ch) || !IsOperator(ch) || !IsLeftParenthesis(ch) || !IsRightParenthesis(ch)) {
return false;
}
return true;
}
int IsRightAssociative(char op)
{
if (op == '^') {
return true;
}
return false;
}
int GetOperatorWeight(char op)
{
int weight = -1;
switch (op) {
case '+':
case '-':
weight = 1;
break;
case '*':
case '/':
weight = 2;
break;
case '^':
weight = 3;
break;
}
return weight;
}
bool HasHigherPrecedence(char op1, char op2)
{
int op1Weight = GetOperatorWeight(op1);
int op2Weight = GetOperatorWeight(op2);
// If operators have equal precedence, return true if they are left associative.
// BUT REMEMBER...return false, if right associative.
// if operator is left-associative, left one should be given priority.
if (op1Weight == op2Weight) {
if (IsRightAssociative(op1)) {
return false;
}
else {
return true;
}
}
return op1Weight > op2Weight ? true : false;
}
string InfixToPostfix(string expression)
{
stack S;
string postfix = "";
for (auto& elem : expression) {
if (Flag(elem)) {
continue;
}
// If character is operator, pop two elements from stack, perform operation and push the result back.
else if (IsOperator(elem)) {
while (!S.empty() && S.top() != '(' && HasHigherPrecedence(S.top(), elem)) {
postfix += S.top();
S.pop();
}
S.push(elem);
}
else if (IsOperand(elem)) {
postfix += elem;
}
else if (elem == '(') {
S.push(elem);
}
else if (elem == ')') {
while (!S.empty() && S.top() != '(') {
postfix += S.top();
S.pop();
}
S.pop();
}
}
while (!S.empty()) {
postfix += S.top();
S.pop();
}
return postfix;
}
int main()
{
// std::string expression = "54/(5^2)+(6^2^3)";
std::string expression = "A+(BC-(D/E^F)G)H";
std::string postfix = InfixToPostfix(expression);
std::cout << "Output = " << postfix << "\n";
}
Here specificially where the error is happening.
string InfixToPostfix(string expression)
{
stack S;
It says
Stack S -> Use of class template 'stack'requires template arguments'
Stack is a container, you need to specify the type of the container like:
stack <int> S;
or in you case it is stack of char:
stack <char> S;