Evaluation of Postfix Expression using stl in c++ - c++

I don't what is wrong with this code it should answer -4
but the answer i'm getting is 2492
#include <bits/stdc++.h>
using namespace std;
int main() {
stack <int> st;
char s[]="231*+9-" ;
for(int i=0;i<7;i++){
if (isdigit(s[i])){
st.push((int)s[i]);
}
else{
float val1,val2;
val1=st.top();
st.pop();
val2=st.top();
st.pop();
switch (s[i])
{
case '+': st.push( val2 + val1); break;
case '-': st.push(val2 - val1); break;
case '*': st.push( val2 * val1); break;
case '/': st.push( val2/val1); break;
}
}
}int m=st.top();
cout<<m;
return 0;
}

You cannot cast a numeric char directly to int if you want its digit value, because that would just give its ASCII code. Instead, do st.push((int)(s[i]-'0')). This removes the offset of the 0-9 character group.

One easy way is to replace char s[]="231*+9- by a string string s ="231*+9-"
and then create an alias of size_t, so you can push the char as a substr like this:
std::string::size_type sz;
...
st.push(stoi(s.substr(i,1), &sz));

Related

whats wrong with this code it just give Enter an Alphabet= j ERROR! (Enter one Alphabet only not two Alphabet or a number)

#include <stdio.h>
int main(void)
{
char a;
printf("Enter an Alphabet=\n");
scanf("%c",&a);
if(a>=0)
{
printf("ERROR!\n(Enter one Alphabet only not two Alphabet or a number)");
}
else
{
switch (a)
{
case 'a' :
printf("It is vowel");
break;
case 'e' :
printf("It is vowel");
break;
case 'i' :
printf("It is vowel");
break;
case 'o' :
printf("It is vowel");
break;
case 'u' :
printf("It is vowel");
break;
default :
printf("it is a constant");
}
}
return 0;
}
this code just give this result
Enter an Alphabet=
r
ERROR!
(Enter one Alphabet only not two Alphabet or a number)
--------------------------------
Process exited after 2.259 seconds with return value 0
Press any key to continue . . .
To check if a character is an alphabetical character, you should use the isalpha function.
Putting together my other pointer (checking what scanf returns as well as using tolower, the code could be written something like this:
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char a;
printf("Enter an alphabetical character: ");
if (scanf(" %c", &a) != 1)
{
printf("Error reading input\n");
return 1;
}
if (!isalpha(a))
{
printf("Character is not an alphabetical character\n");
return 1;
}
switch (tolower(a))
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
printf("It's a vowel\n");
break;
default:
printf("It's a consonant\n");
break;
}
}
[Note that the above code is still written in plain C, not C++]

how can i convert infix to postfix expression of multi digit operands?

I am able to convert infix to postfix and calculates with one digit but i can't convert to postfix and calculate with N digits. PLz anyone help me! Thanks!!
here is my code with single digit
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
using namespace std;
class infix2postfix
{
public:
void push(int symbol);
int pop();
void infix_to_postfix();
int priority(char symbol);
int isEmpty();
int white_space(char);
int eval_post();
};
char infix[100], postfix[100];
int stack[100];
int top;
int main()
{
infix2postfix ip;
top=-1;
cout<<"Enter infix : ";
gets(infix);
ip.infix_to_postfix();
cout<<"Postfix : "<<postfix<<endl;
cout<<"Result is : "<<ip.eval_post()<<endl;
return 1;
}
void infix2postfix :: infix_to_postfix()
{
int i,p=0;
char next;
char symbol;
for(i=0; i<strlen(infix); i++)
{
symbol=infix[i];
if(!white_space(symbol))
{
switch(symbol)
{
case '(':
push(symbol);
break;
case ')':
while((next=pop())!='(')
postfix[p++] = next;
break;
case '+':
case '-':
case '*':
case '/':
case '%':
case '^':
while( !isEmpty( ) && priority(stack[top])>= priority(symbol) )
postfix[p++]=pop();
push(symbol);
break;
default: /*if an operand comes*/
postfix[p++]=symbol;
}
}
}
while(!isEmpty( ))
postfix[p++]=pop();
postfix[p]='\0'; /*End postfix with'\0' to make it a string*/
}
/*This function returns the priority of the operator*/
int infix2postfix :: priority(char symbol)
{
switch(symbol)
{
case '(':
return 0;
case '+':
case '-':
return 1;
case '*':
case '/':
case '%':
return 2;
case '^':
return 3;
default :
return 0;
}
}
void infix2postfix :: push(int symbol)
{
if(top>100)
{
cout<<"Stack overflow\n";
exit(1);
}
stack[++top]=symbol;
}
int infix2postfix :: pop()
{
if( isEmpty() )
{
cout<<"Stack underflow\n";
exit(1);
}
return (stack[top--]);
}
int infix2postfix :: isEmpty()
{
if(top==-1)
return 1;
else
return 0;
}
int infix2postfix :: white_space(char symbol)
{
if( symbol == ' ' || symbol == '\t' )
return 1;
else
return 0;
}
int infix2postfix :: eval_post()
{
int a,b,i,temp,result;
for(i=0; i<strlen(postfix); i++)
{
if(postfix[i]<='9' && postfix[i]>='0')
push(postfix[i]-'0');
else
{
a=pop();
b=pop();
switch(postfix[i])
{
case '+':
temp=b+a;
break;
case '-':
temp=b-a;
break;
case '*':
temp=b*a;
break;
case '/':
temp=b/a;
break;
case '%':
temp=b%a;
break;
case '^':
temp=pow(b,a);
}
push(temp);
}
}
result=pop();
return result;
}
My Question is: how to get the result for more than 1 digit operand?
I have tried for Single digit, but how could i get for multi-digit numbers?
You are currently pushing the digits on the stack individually, so a numeric value of 10 will be pushed on the stack two symbols: 1 and 0.
In your operator logic, you are popping one symbol from the stack per operand. Multi-digits operands will thus not work and produce completely wrong results.
There are many ways to solve this. For example, you could fuse multiple digits together into the same stack symbol while reading them in (i.e. combine the digit currently processed with the top of the stack if both are digits).
The place to do this would be inside push. Here's how to do this:
void infix2postfix :: push(int symbol)
{
if(top>100)
{
cout<<"Stack overflow\n";
exit(1);
}
if (! isEmpty() && stack[top] >= 0 && stack[top] <= 9) {
stack[top] *= 10;
stack[top] += symbol;
}
else {
stack[++top]=symbol;
}
}
This will work as long as a numeric operand fits inside the range of an int. Bigger numbers will simply overflow.
There will also be problems because numbers cannot be told apart from other stack symbols. With multi-digit numbers, you can now have symbols which have the same int value as an operator. A way to fix this is to assign negative int values to the operator symbols, and non-negative values for the numbers. This will work for your case as your grammar does not seem to have a unary minus.
This approach is also in line with what you do in eval_post, where you push the calculation result on the stack as a single integer value, regardless of how many digits might be contained.
The most powerful but complicated alternative would write a grammar and use a parser generator. I recommend GNU bison. This will completely take over generating the code for the parser, so all you have to do is to write the grammar for your expressions plus the actual infix-to-postfix transformation (which will be trivial with bison). It will also help you detect invalid input easily and provide appropriate error messages.
However, getting started with bison can be hard if you never used it before.

c++ The evaluation of expression. How to exit the while loop?

I use stack to evaluate an expression.
The most important function is below:
double Expression_Eval()
{
SeqStack<char,100> OPTR;
SeqStack<double,100> OPND;
OPTR.Push('#');
char ch;
ch=getchar();
while (ch!='#' || OPTR.GetTop()!='#')
{
if (!InOPTR(ch))
{
int n=ch-'0';
double num=(double)n;
OPND.Push(num);
ch=getchar();
}
else
{
char pre_op=OPTR.GetTop();
switch (Precede(pre_op, ch))
{
case '<': OPTR.Push(ch);
ch=getchar();
break;
case '=': OPTR.Pop();
ch=getchar();
break;
case '>': double b=OPND.Pop();
double a=OPND.Pop();
pre_op=OPTR.Pop();
OPND.Push(Operate(a, pre_op, b));
ch=getchar();
break;
}
}
}
return OPND.GetTop();
}
Then, when I input 8/(5-3)#, it will not print the result.
I think the loop termination condition ch!='#' || OPTR.GetTop()!='#' is wrong.
When I press Enter, getchar() get the last char is CR but not #.
But, I don't know how to revise it to make my program work.
The other part of my program is below:
#include<iostream>
using namespace std;
template<typename DataType,int StackSize>
class SeqStack
{
private:
DataType data[StackSize];
int top;
public:
SeqStack()
{ top=-1; }
~SeqStack() {}
void Push(DataType x)
{
if(top == StackSize-1)
throw "error";
data[++top]=x;
}
DataType Pop()
{
if(top == -1)
throw "error";
DataType x=data[top--];
return x;
}
DataType GetTop()
{
if(top != -1)
return data[top];
else
cout<<"error";
}
};
bool InOPTR(char ch)
{
if( (ch>='(' && ch<='+') || ch=='-' || ch=='/' )
{
return true;
}else{
return false;
}
}
char Precede(char op1, char op2)
{
char pri[7][7]={ {'>','>','<','<','<','>','>'}
, {'>','>','<','<','<','>','>'}
, {'>','>','>','>','<','>','>'}
, {'>','>','>','>','<','>','>'}
, {'<','<','<','<','<','=','#'}
, {'>','>','>','>','#','>','>'}
, {'<','<','<','<','<','#','='} };
int m,n;
switch(op1)
{
case '+': m=0;break;
case '-': m=1;break;
case '*': m=2;break;
case '/': m=3;break;
case '(': m=4;break;
case ')': m=5;break;
case '#': m=6;break;
}
switch(op2)
{
case '+': n=0;break;
case '-': n=1;break;
case '*': n=2;break;
case '/': n=3;break;
case '(': n=4;break;
case ')': n=5;break;
case '#': n=6;break;
}
return pri[m][n];
}
double Operate(double a, char op, double b)
{
double result;
switch(op)
{
case '+': result=a+b; break;
case '-': result=a-b; break;
case '*': result=a*b; break;
case '/': result=a/b; break;
}
return result;
}
int main()
{
double r=Expression_Eval();
cout<<r<<endl;
return 0;
}
Problem seem to be that '#' is considered a number, but it should be considered an operation:
Use:
bool InOPTR(char ch) {
if ((ch >= '(' && ch <= '+') || ch == '-' || ch == '/' || ch=='#'){
return true;
}
else {
return false;
}
}
Note that '#' is ASCII 64 which is not covered in the ranage '(' to '+' [40-43]
Hope this helps.
You need to consume carriage return or newline character after getchar(); which comes into play when you press enter button.
One trick is as below.
ch=getchar();
getchar(); //this getchar to consume CR.
since you have used ch = getchar() many times you have to use above solution at many places.
Better solution to this problem will be to enter string instead of entering single character using getchar()...
Hope you got what I am trying to say...

error in character comparison

after the switch statement the program compares the characters.in this phase ı have debugged and seen that the first character of string is 111 'o' instead of just 'o' and this causes my program to fail. how can I fix it or where is the problem?
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <cmath>
using namespace std;
int main(){
char sentence1[50];
char sentence2[50];
int m,n,k,l;
int i,j,substitution;
cout<<"Enter the first word:"<<endl;
cin>>sentence1;
cout<<"Enter the second word:"<<endl;
cin>>sentence2;
m = strlen(sentence1);
n = strlen(sentence2);
int cost[m+1][n+1];
bool a1,a2;
cost[0][0]=0;
for(i=1;i<m+1;i++){
cost[i][0]=cost[i-1][0]+2;
}
for(j=1;j<n+1;j++){
cost[0][j]=cost[0][j-1]+2;
}
for(i=1;i<m+1;i++){
for(j=1;j<n+1;j++){
switch (sentence1[i-1]){
case 'a':a1=true;
case 'u':a1=true;
case 'e':a1=true;
case 'o':a1=true;
case 'i':a1=true;
default:a1=false;
}
switch (sentence2[j-1]){
case 'a':a2=true;
case 'u':a2=true;
case 'e':a2=true;
case 'o':a2=true;
case 'i':a2=true;
default:a2=false;
}
if(sentence1[i-1]==sentence2[j-1]){substitution=0;
}
else if(a1==true && a2==false){substitution=4;}
else if(a1==false && a2==true){substitution=4;}
else if(a1==true && a2==true){substitution=3;}
else if(a1==false && a2==false){substitution=3;}
cost[i][j]=min(min(cost[i-1][j]+2,cost[i][j-1]+2),cost[i-1][j-1]+substitution);
}
}
for(i=0;i<m+1;i++){
for(j=0;j<n+1;j++){
cout<<cost[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
switch statements "fallthrough" without a break.
switch (sentence1[i-1]){
case 'a':a1=true; break;
case 'u':a1=true; break;
case 'e':a1=true; break;
case 'o':a1=true; break;
case 'i':a1=true; break;
default:a1=false; break;
}
Since this logic is being repeated, consider promoting it to its own function.
bool is_a_vowel( char c )
{
switch (c){
case 'a':
case 'u':
case 'e':
case 'o':
case 'i':
return true;
default:
return false;
}
Now you can have more readable and consistent code.
a1 = is_a_vowel( sentence1[i-1] );
a2 = is_a_vowel( sentence2[j-1] );

Occasional unhandled exception with atoi(string.c_str()) Updated

UPDATE
I thought stoi(string) solved it, but it only worked for a little while.
I have added the code for splitString and decrypt below.
I occasionally get unhandled exceptions with atoi() using the supposable same value.
My code looks like this:
ifstream myfile ("Save.sav");
string line = "";
if (myfile.is_open())
{
while ( myfile.good() )
{
getline (myfile,line);
}
myfile.close();
line = StaticFunctions::decrypt(line);
}
vector<string> splitString = StaticFunctions::splitString(line, 's');
return atoi(splitString[0].c_str());
So what it does is reading a savefile, then it decrypts it and then it splits the string by every 's'. When I'm debugging, the savefile is always the same and the first value is 3.
This work sometimes, maybe every 10 attempt. So every 9 out of 10 attempts I get unhandled exception at ... at memory location.
Monitoring the converted value shows it always returns 3 and then the application doesn't crash until I start the game which is a bit further in the code.
If I remove the atoi and just return 3 the application works fine.
I've tried strtod but it didn't help.
Thanks,
Markus
SplitString code:
vector<string> StaticFunctions::splitString(string str, char splitByThis)
{
vector<string> tempVector;
unsigned int pos = str.find(splitByThis);
unsigned int initialPos = 0;
// Decompose statement
while( pos != std::string::npos ) {
tempVector.push_back(str.substr( initialPos, pos - initialPos + 1 ) );
initialPos = pos + 1;
pos = str.find(splitByThis, initialPos );
}
// Add the last one
tempVector.push_back(str.substr(initialPos, std::min(pos, str.size()) - initialPos + 1));
return tempVector;
}
Decrypt code (very simple):
string StaticFunctions::decrypt(string decryptThis)
{
for(int x = 0; x < decryptThis.length(); x++)
{
switch(decryptThis[x])
{
case '*':
{
decryptThis[x] = '0';
break;
}
case '?':
{
decryptThis[x] = '1';
break;
}
case '!':
{
decryptThis[x] = '2';
break;
}
case '=':
{
decryptThis[x] = '3';
break;
}
case '#':
{
decryptThis[x] = '4';
break;
}
case '^':
{
decryptThis[x] = '5';
break;
}
case '%':
{
decryptThis[x] = '6';
break;
}
case '+':
{
decryptThis[x] = '7';
break;
}
case '-':
{
decryptThis[x] = '8';
break;
}
case '"':
{
decryptThis[x] = '9';
break;
}
}
}
return decryptThis;
}
Try use strtol instead
strtol (splitString[0].c_str(),NULL,10);
stoi(string) instead of atoi(string.c_str()) solved it.
UPDATE:
It did not solve it.