Evaluate Infix expression without converting it into postfix [duplicate] - c++

This question already has answers here:
How to evaluate an infix expression in just one scan using stacks?
(4 answers)
Closed 3 years ago.
I'm trying to evaluate an infix expression in 1 pass without converting it into postfix but it's not giving correct output for some expressions. For eg: 3-5*10/5+10 , (45+5)-5*(100/10)+5
Can someone provide a proper solution to this problem in cpp.
Link to the previous question asked: How to evaluate an infix expression in just one scan using stacks?
Please don't mark it as duplicate as I have tried the algorithm answered in the above given thread but to no avail.
#include<bits/stdc++.h>
int isoperand(char x)
{
if(x == '+' || x=='-'|| x=='*' || x=='/' || x==')' || x=='(')
return 0;
return 1;
}
int Pre(char x)
{
if(x == '+' || x == '-')
return 1;
if(x == '*' || x == '/')
return 3;
return 0;
}
int infixevaluation(std::string exp)
{
std::stack<int> s1; //Operand Stack
std::stack<char> s2; //Operator Stack
int i,x,y,z,key;
i=0;
while(exp[i]!='\0')
{
if(isoperand(exp[i]))
{
key = exp[i]-'0';
s1.push(key);
i++;
}
else if(!isoperand(exp[i]) && s2.empty())
s2.push(exp[i++]);
else if(!isoperand(exp[i]) && !s2.empty())
{
if(Pre(exp[i])>Pre(s2.top()) && exp[i]!=')')
s2.push(exp[i++]);
else if(exp[i]==')' && s2.top() == '(')
{
s2.pop();
i++;
}
else if(exp[i]=='(')
s2.push(exp[i++]);
else
{
x = s1.top();
s1.pop();
y = s2.top();
s2.pop();
z = s1.top();
s1.pop();
if(y == '+')
s1.push(z+x);
else if(y == '-')
s1.push(z-x);
else if(y == '*')
s1.push(x*z);
else if(y == '/')
s1.push(z/x);
}
}
}
while(!s2.empty())
{
x = s1.top();
s1.pop();
y = s2.top();
s2.pop();
z = s1.top();
s1.pop();
if(y == '+')
s1.push(x+z);
else if(y == '-')
s1.push(z-x);
else if(y == '*')
s1.push(x*z);
else if(y == '/')
s1.push(z/x);
}
return s1.top();
}
int main(int argc, char const *argv[])
{
std::string s;
getline(std::cin,s);
std::cout<<infixevaluation(s)<<std::endl;
return 0;
}

Your code can only deal with single-digit operands -- and it has no checks for malformed input, so when you have a multi-digit operand, it runs off the rails.
The easiest fix for the former is just to scan digits when you see a digit -- change the if (isoperand(exp[i]) clause to:
if (isdigit(exp[i])) {
int value = 0;
while (isdigit(exp[i]))
value = value * 10 + exp[i++] - '0';
s1.push(value);
} else ...
For error checking, you should do things like
check for spaces and other invalid characters and reject or skip them
keep track of whether the last token matched was an operand or an operator, and give errors for two consecutive operands, or two consecutive operators other than ( and )

Related

Why is this c++ code producing weird characters?

I wanted to simplify algebraic expressions in c++. I started with something simple: removing brackets from a algebraic expression containing + and - operators. For example, a-(b-c) should be simplified to a-b+c. This link gives the answer to this question. Here is the source code:
#include <iostream>
#include <string.h>
#include <stack>
using namespace std;
// Function to simplify the string
char* simplify(string str)
{
int len = str.length();
// resultant string of max length equal
// to length of input string
char* res = new char(len);
int index = 0, i = 0;
// create empty stack
stack<int> s;
s.push(0);
while (i < len) {
if (str[i] == '+') {
// If top is 1, flip the operator
if (s.top() == 1)
res[index++] = '-';
// If top is 0, append the same operator
if (s.top() == 0)
res[index++] = '+';
} else if (str[i] == '-') {
if (s.top() == 1)
res[index++] = '+';
else if (s.top() == 0)
res[index++] = '-';
} else if (str[i] == '(' && i > 0) {
if (str[i - 1] == '-') {
// x is opposite to the top of stack
int x = (s.top() == 1) ? 0 : 1;
s.push(x);
}
// push value equal to top of the stack
else if (str[i - 1] == '+')
s.push(s.top());
}
// If closing parentheses pop the stack once
else if (str[i] == ')')
s.pop();
// copy the character to the result
else
res[index++] = str[i];
i++;
}
return res;
}
I tested the function on a-(b-c-(d+e))-f and it gave the result a-b+c+d+e-fÿï┌. Why is it producing weird characters?

My 2D maze solver recurses infinitely and I get a stack overflow - why?

The Problem :-
I am trying to solve a 2d maze navigation problem in C++ using 2-dimensional array. To give a concise idea about the problem itself, I intend to navigate from node 'S' in the array to node 'G' by walking through free spaces denoted by '.' The nodes '#' are obstacles. One is not allowed to move on spaces denoted as obstacles. Care must also be taken to make all moves as legal moves (within configuration space). I denote the valid move with a '+' after replacement of the '.' If you like to know more about this problem (not necessary) then please refer this link.
What is the issue ?
I coded a recursive algorithm for this problem where we receive an array and a start node position, and then try to navigate to the goal node using recursion. However, I am getting a stack overflow error. It seems like my recursion never stops. I strongly believe there is some problem in my play() function or my check() function. I am not sure what actually is the problem.
What did I try ?
I am reproducing my code below :
void spawn(std::string (&board)[6]) {
for (int i = 0; i <= 6; i++) {
std::cout << board[i] << std::endl;
}
}
bool check(size_t a, size_t b, const std::string (&board)[6]) {
if (a < board[1].size() && a >= 0 && b < board[1].size() && b >= 0) {
if (board[a][b] == '#' || board[a][b] == '+')
return false;
else if (board[a][b] == '.')
return true;
}
return false;
}
void play(std::string (&board)[6], size_t a, size_t b) {
auto status = check(a, b, board);
if (board[a][b] == 'G' || board[a][b] == 'g') {
spawn(board);
return;
}
if (status) {
board[a][b] = '+';
play(board, ++a, b);
play(board, --a, b);
play(board, a, ++b);
play(board, a, --b);
}
}
int main() {
std::string grid[6] = {{"S#####"},
{".....#"},
{"#.####"},
{"#.####"},
{"...#.G"},
{"##...#"}};
play(grid, 0, 0);
return 0;
}
The check function prevents recursion because it sees the 'S' in the grid at the starting location. Changing:
else if (board[a][b] == '.')
to
else if (board[a][b] == '.' || board[a][b] == 'S')
got it to work for me.
Thanks for the insights Perette and Retired Ninja. I refactored the play() and check() functions in light of your suggestions and also some more ideas by myself.
I figured out that the main issue with the segmentation fault error was not providing accommodation for the '\0' character at the end of array of strings grid. I overlooked it because I considered array of strings to function in a different way than array of chars (since they are not the same species). Now I realize that the '\0' is necessary even for an array of strings !
I am reproducing the refactored functions for the purpose of completeness of this post :
void spawn(std::string board[6]) {
for (int i = 0; i <= 6; i++) {
std::cout << board[i] << std::endl;
}
}
bool check(int a, int b, const std::string board[6]) {
if (a < board[1].size() && a >= 0 && b <
board[1].size() && b >= 0) {
if (board[a][b] == '#' || board[a][b] == '+') {
return false;
} else if (board[a][b] == '.' ||
board[a][b] == 'S' ||
board[a][b] == 'G') {
return true;
}
}
return false;
}
void play(std::string board[6], int a, int b) {
if (board[a][b] == 'G' || board[a][b] == 'g') {
board[0][0] = 'S';
spawn(board);
return;
}
if (board[a][b] == '.' || board[a][b] == 'S')
board[a][b] = '+';
if (check(a + 1, b, board)) play(board, a + 1, b);
if (check(a - 1, b, board)) play(board, a - 1, b);
if (check(a, b + 1, board)) play(board, a, b + 1);
if (check(a, b - 1, board)) play(board, a, b - 1);
if (board[a][b] == '+') board[a][b] = '.';
}
int main() {
std::string grid[7] = {{"S#####"},
{".....#"},
{"#.####"},
{"#.####"},
{"...#.G"},
{"##...#"}};
play(grid, 0, 0);
return 0;
}

prefix notation c++, segmentation fault (stack and queue)

I am trying to figure out why I get segmentation fault, and my guess is that it is in my recursive function, which simplifies a prefix notation operation.
For example:
"m + 4 4" Returns: "+ m 8"
During testing I get a segmentation fault signal:
Exited with signal 11 (SIGSEGV)
I believe though that the problem lies in my recusive function "Operate"
string Operate(stack<string> &S, queue<string> &Q)
{
S.push(Q.front());
Q.pop();
std::string::size_type sz;
string result = "";
if (IsOperator(S.top()) == true)
{
S.push(Operate(S, Q));
}
if (Q.empty() == false)
{
S.push(Q.front());
Q.pop();
if (IsOperator(S.top()) == true)
{
S.push(Operate(S, Q));
}
if (S.size() < 3)
return "wrong input";
string arg1 = S.top();
S.pop();
string arg2 = S.top();
S.pop();
string oper = S.top();
S.pop();
if (StringIsDigit(arg1) && StringIsDigit(arg2))
{
int a = stoi(arg1, &sz);
int b = stoi(arg2, &sz);
char o = oper.at(0);
int c = 0;
if (o == '+')
c = b + a;
else if (o == '-')
c = b - a;
else if (o == '*')
c = b * a;
else
return "e";
result = to_string(c);
}
else
result = oper + " " + arg2 + " " + arg1;
}
else
{
result = S.top();
S.pop();
}
return result;
}
or in the function StringIsDigit:
bool StringIsDigit(string arg)
{
bool result = true;
for (int i = 0; i < arg.size() && result == true; i++)
{
if ((arg.size() != 1) && (arg.at(0) == '-') && (arg.at(i + 1) != ' '))
i++;
else
result = isdigit(arg.at(i));
}
return result;
}
Link to the whole program code:
https://pastebin.com/04pfE55N
The answer was quite simple, my error: SEGFAULT was as many pointed out for me error in reading from memory, segmentation fault, wiki.
When did the segfault occur?
It was when my function StringIsDigit() tried to figure out if negative values over 2 characters was an integer. In the "if statement, when checking if the string was indeed an integer, say -100", I continued to read the string until I reached the end of the arg string, but with arg.at(i + 1). Leading to the code trying to access memory outside the string array.Thanks Struthersneil for finding this flaw!
Please look at my old StringIsDigit() to find out the of by one value error I made:
bool StringIsDigit(string arg)
{
bool result = true;
for (int i = 0; i < arg.size() && result == true; i++)
{
if ((arg.size() != 1) && (arg.at(0) == '-') && (arg.at(i + 1) != ' '))
i++;
else
result = isdigit(arg.at(i));
}
return result;
}
The solution
The solution I want to make sure that the string was an integer since my algorithm supports expressions, such as x+3. This means that I need to iterate through the string is call isdigit() on every character in the string array. Though '-' is not an integer, '-' is needed obviously to express a negative integer, so I made a flawed check as you can see in my old StringIsDigit(). Instead of using that conditional if statement, I checked if the first character '-' and the second is not a whitespace ' ', and then I just let the isdigit() function do the rest of the work.
bool StringIsDigit(string arg)
{
bool result = true;
//I only need to check if the first is a '-' char and
//the next char is not ' '.
for (int i = 0; i < arg.size() && result == true; i++)
{
if ((arg.size() != 1) && (arg.at(0) == '-') && (arg.at(1) != ' '))
i++;
else
result = isdigit(arg.at(i));
}
return result;
}

convert any base to base 10 in C++

I have this code:
#include <stdio.h>
#include <ctype.h>
int validnumber(int b, char* p);
unsigned long base2dec(int b,char *p);
void dec2base (int b,unsigned long x);
char *number;
main() {
int base,temp=0,count;
unsigned long Decimal_number;
do {
printf ("Give the base of the number you want to tranform:");
scanf ("%d", &base);
if (base<2 || base>16)
printf("Not acceptable base number, numbers should be in range from 2 to 16\n\n");
} while (base<2 || base>16);
printf ("Give the number you want to tranform:");
scanf("%s", number);
for (count=0;count<32;count++) {
number [count]= toupper(number[count]);
}
temp=validnumber(base, number);
if (temp==0)
printf ("O arithmpos pou eisagatai periexei MH egkira symbola\n");
else
if (temp==1)
printf ("O arithmpos pou eisagatai periexei egkira symbola\n");
if (temp==1) {
Decimal_number = base2dec( base , number);
}
int validnumber(int b, char *p){
int count, a[32];
for (count=0;count<32;count++)
a[count]=p[count];
if (b>=2 && b<=10) {
for (count=0;count<32;count++) {
if (a[count]<48 || a[count]>48+b)
return 0;
break;
}
}
if (b>=11 && b<=16) {
for (count=0;count<32;count++) {
if ((a[count]>=48 && a[count]<=57) || (a[count]>=65 && a[count]<=70)) {
return 1;
}
}
}
}
From this point the main program must call the function:
unsigned long base2dec (int b, char * p)
which accepts as arguments the base b and a pointer p in character table that
corresponds to the imported string s and returns the number representing the s expressed in the decimal system.
Also, it should call the function:
void dec2base (int b, unsigned long x)
which accepts as arguments the base b and the value of the number x in the decimal system and displays the base value and the representation of the number x in this base. The main program calls this function for all of the base values from 2 to 16.
Are there any ideas on how to begin? Any guidance will be appreciated.
In your base2dec, you will simply call this method and pass in 'b' as it is and x which should be the converted string.
Here is an implementation of dec2base. It is implemented recursively.
void dec2base(int b, unsigned long x){
if (x == 0)
return;
int y = x % b;
x /= b;
if (y < 0)
x += 1;
dec2base(b, x);
//converted digits to hex after realizing this solution doesn't work
//for bases greater than 10. Credits to Trevor pointing this out.
cout<< hex << y < 0 ? y + (b * -1) : y;
return;
}
First of all please have a look at your formatting because the way your code is written makes it harder than it needs to be to follow.
Here is what I would do:
#include <stdexcept>
#include <iostream>
void dec2base(int b, long x)
{
// Quick check for zero
if (x == 0)
{
std::cout << '0';
return;
}
// Print the negative sign if present, also negate
if (x < 0)
{
std::cout << '-';
x = -x;
}
char buf[12];
int i = 0;
// Convert to a backwards BCD
do {
buf[i++] = static_cast<char>(x % b);
} while (x /= b);
// Print it starting from the last digit (really the first)
do {
if (buf[--i] <= 9) std::cout << static_cast<char>(buf[i] + '0');
else std::cout << static_cast<char>(buf[i] + ('a' - 10));
} while (i);
}
long base2dec(int b, char * p)
{
long digit; // Current digit
long mul = 1; // Current multiplier
char *pos = p; // Current position
bool neg = false; // Sign
long ret = 0; // The return value
// Find the last digit
while (*pos) pos++;
// Continue until the start of the string is reached
while (pos-- != p)
{
if (*pos < '0')
{
if (*pos == '-')
{
// Sign reached, save it an break out
neg = true;
break;
}
else // Shouldn't happen
{
throw std::invalid_argument("Not a number");
}
}
if (*pos > 'f')
throw std::invalid_argument("Not a number");
// Get a digit
if (*pos <= '9') digit = *pos - '0';
else if (*pos >= 'a') digit = *pos - ('a' - 10);
else if (*pos >= 'A' && *pos <= 'F')
digit = *pos - ('A' - 10);
else
throw std::invalid_argument("Not a number");
// Make sure it is not larger than or equal to the base
if (digit >= b)
throw std::invalid_argument("Not a number");
// Add the digit
ret += digit * mul;
// Increase the multiplier
mul *= b;
}
return neg ? -ret : ret;
}
int main()
{
long val = base2dec(16, "123f");
dec2base(16, val);
return 0;
}
I realize you didn't ask for a signed version but as it is very easy to implement I have done it. If you really don't need to deal with signed values it is simple to drop the relevant parts from the functions.
This is a very quick and dirty go at this and this could no doubt be improved both for readability and performance but is, I think, a good starting point.
Here is a slightly improved version of base2dec():
long base2dec(int b, char * p)
{
long digit; // Current digit
bool neg = false; // Sign
long ret = 0; // The return value
// Check for negative number
if (*p == '-')
{
neg = true;
p++;
}
// Continue until the end of the string is reached
for (; *p != 0; p++)
{
// Rough range check
if (*p < '0' || *p > 'f')
throw std::invalid_argument("Not a number");
// Get a digit
if (*p <= '9') digit = *p - '0';
else if (*p >= 'a') digit = *p - ('a' - 10);
else if (*p >= 'A' && *p <= 'F')
digit = *p - ('A' - 10);
else
throw std::invalid_argument("Not a number");
// Make sure it is not larger than or equal to the base
if (digit >= b)
throw std::invalid_argument("Not a number");
// Add the digit
ret = ret * b + digit;
}
return neg ? -ret : ret;
}
Regarding the validnumber() function. This check is best performed during the conversion both to avoid having to read the entire string twice and because base2dec() really ought to check for valid input anyway. If you still need a separate check then you need to fix validnumber(). There is no need to copy the string to an array and it is also better to use the same code for all bases. Here is a suggestion:
bool validnumber(int b, char *p)
{
// Check for valid base
if (b < 2 || b > 16) return false;
// Extract numeric and alpha parts of the base
int b_numeric = b <= 10 ? b : 10;
int b_alpha = b - 11;
// Ignore any sign
if (*p == '-') p++;
// Continue until the end of the string
for (; *p != 0; p++)
{
// Digits < 0 are always bad
if (*p < '0') return false;
// Check for valid numeric digits
if (*p > ('0' + b_numeric))
{
// Check for valid alpha digits
if (b <= 10) return false;
if (*p < 'A' || *p > ('a' + b_alpha)) return false;
if (*p > ('A' + b_alpha) && *p < 'a') return false;
}
}
return true;
}

Having trouble casting a stack object number to int (Java)

I'm writing a program that converts an expression from infix to postfix. I have the conversion part down but when it comes to evaluating the postfix expression, I run into problems with converting from char to int using the stack.
I keep getting the error: "Exception in thread "main" java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Integer"
It might be in this part of the code below where the problem is but I'm not sure:
Integer x1 = (Integer)stack2.pop();
Integer x2 = (Integer)stack2.pop();
Thank you!
public class Calc {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
System.out.println("Please enter your infix expression: ");
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
String postfix = "";
Stack<Character> stack = new Stack<Character>();
for(int i = 0; i < input.length(); i++){
char subject = input.charAt(i);
if (subject == '*'||subject == '+'||subject == '-'||subject == '/'){
while ((stack.empty() == false) && (order(stack.peek()) >= order(subject)))
postfix += stack.pop() + " ";
stack.push(subject);
}
else if(subject == '(')
{
stack.push(subject);
}
else if(subject == ')')
{
while(stack.peek().equals('(') == false){
postfix += stack.pop() + " ";
}
stack.pop();
}
else{
if((Character.isDigit(subject) == true) && ((i + 1) < input.length()) && (Character.isDigit(input.charAt(i+1)) == true))
{
postfix += subject;
}
else if(Character.isDigit(subject))
{
postfix += subject + " ";
}
else
{
postfix += subject;
}
}
}
postfix += stack.pop();
System.out.println("Your post-fix expression is: " + postfix);
char subject2;
int yeah;
Stack stack2 = new Stack();
for (int j = 0; j < postfix.length(); j++){
subject2 = postfix.charAt(j);
if(Character.isDigit(subject2) == true){
stack2.push(subject2);
}
if(subject2 == ' '){
continue;
}
else{
Integer x1 = (Integer)stack2.pop();
Integer x2 = (Integer)stack2.pop();
if (subject2 == '+'){
yeah = x1 + x2;
}
if (subject2 == '-'){
yeah = x1 - x2;
}
if (subject2 == '*'){
yeah = x1 * x2;
}
if (subject2 == '/'){
yeah = x1 / x2;
}
else {
yeah = 0;
}
}
}
yeah = (int) stack2.pop();
System.out.println("The result is:" + yeah);
}
static int order(char operator)
{
if(operator == '+' || operator =='-')
return 1;
else if(operator == '*' || operator == '/')
return 2;
else
return 0;
}
}
You can solve this by casting to int. Note that int and Integer are not the same:
Integer x1 = (int) stack2.pop();
Integer x2 = (int) stack2.pop();
no casting is necessary by using type-information
Stack<Integer> stack2 = new Stack<Integer>();
…
if(Character.isDigit(subject2) == true){
stack2.push( Character.getNumericValue( subject2 ) );
}
…
to prevent an empty stack exception I'd prefer poll over pop
so it is easier to check an error condition
eg. if( x1 == null ) System.err.println( "Your error message" );
Deque<Integer> stack2 = new ArrayDeque<Integer>();
…
Integer x1 = stack2.poll();
Integer x2 = stack2.poll();
…
btw: the program is syntactically wrong, because it puts only one value on the stack