spoj - opn - transform the expression - segmentation fault - c

first time i am trying to submit solution on spoj ,
this is my solution for solving the transform the expression problem on spoj.I am getting the SIGSEV error which is a runtime error , segmentation fault .
I have checked a lot in my code , but i dont see any such kind of error in my code .
Plz help solving this .
I HAVE THE EDITED CODE :-
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int precedence(char c)
{
switch (c)
{
case '/':
return 2;
case '*':
return 2;
case '+':
return 1;
case '-':
return 1;
case '^':
return 3;
case ')':
return 4;
case '(':
return -1;
default:
return -1 ;
}
}
int main()
{
//char input[400]="a*(b+c)-d/e";
// char input[400]="a+b*c-d/e*f";
// char input[400] = "(a+b*c-d)/(e*f)";
// char input[400] = "(a+(b*c))" ;
//char input[400] = "((a+b)*(z+x))";
// char input[400] = "((a+t)*((b+(a+c))^(c+d)))";
char input[402];
char *stack;
char *output;
char *p = input ;
int i , top , t , l ;
scanf("%d",&t);
while (t-- != 0 )
{
scanf("%s",input);
p = input ;
i = 0 ;
top = 0 ;
l = strlen(input);
stack = (char *)malloc(sizeof(strlen(input)));
output = (char *)malloc(sizeof(strlen(input)));
stack[top++]='(';
*(p+l)=')';
*(p+l+1)= '\0';
while(p[0] != '\0')
{
if (p[0] >= 'a' && p[0] <= 'z' )
{
output[i]=p[0];
i++;
}
else if (p[0] == '(')
{
stack[top++] = p[0];
}
else if (p[0] == ')')
{
while (stack[top-1] != '(')
{
--top;
output[i] = stack[top];
i++ ;
}
//to remove the left parenthesis
top--;
}
else if (p[0] == '+' || p[0] == '-' || p[0] == '*' || p[0] == '/' || p[0]=='^')
{
while(precedence(stack[top-1]) >= precedence(p[0]))
{
output[i]=stack[top-1];
top--;
i++;
//j = k;
}
stack[top] = p[0];
top++;
}
p++;
}
printf("%s\n",output);
free(stack);
free(output);
for(i = (strlen(input)-1) ; i >= 0 ; i--)
input[i]='\0';
}
return 0 ;
}

*(p+strlen(p))=')';
overwrites the 0-terminator of p, then
*(p+strlen(p))= '\0';
the strlen(p) in this may not find any 0-terminator anymore, and cause a segfault. Also, that line is superfluous anyway, *(p + strlen(p)) is already 0 by the definition of strlen (if p is a string, i.e. 0-terminated).
If you want to add a ')' at the end, store the length,
size_t len = strlen(p);
p[len] = ')';
p[len+1] = 0;
and use that twice. But make sure that you have enough space allocated.

Related

How to make the calculator count the expression with spaces in the input?

I tried to make calculator supporting brackets, but
I have no idea how to deal if the user's input includes expression with spaces, for example:
input: (2 + 3) * 2
i got: 2
If it's normally get (2+3)*2, it counts 10
.
My code:
#include <stdio.h>
#define MAX_SIZE 1024
int insert_operand(int *operand, int * top_num, int num) /* data is pushed into the data stack*/
{
(*top_num) ++;
operand[*top_num] = num; /*save data*/
return 0; /*Exit normally*/
}
int insert_oper (char * oper , int *top_oper , char ch)
{
(*top_oper)++;
oper[*top_oper] = ch; /*save operator*/
return 0; /*Exit normally*/
}
int compare(char *oper , int *top_oper , char ch) /* compare the priority of the operating server*/
{
if((oper[*top_oper] == '-' || oper[*top_oper] == '+') /*Determine whether the current priority is higher than the priority of the operator at the top of the stack*/
&& (ch == '*' || ch == '/'))
{
return 0;
}
else if(*top_oper == -1 || ch == '('
|| (oper[*top_oper] == '(' && ch != ')')) /*Determine whether the operator stack is empty; whether the top operator is '('*/
{
return 0;
}
else if (oper[*top_oper] =='(' && ch == ')')
{
(*top_oper)--;
return 1;
}
else
{
return -1; /*Operate the operator*/
}
}
int deal_date(int *operand ,char *oper ,int *top_num, int *top_oper) /*perform data operation*/
{
int num_1 = operand[*top_num]; /*Take out two data from the data stack*/
int num_2 = operand[*top_num - 1];
int value = 0;
if(oper[*top_oper] == '+')
{
value = num_1 + num_2;
}
else if(oper[*top_oper] == '-')
{
value = num_2 - num_1;
}
else if(oper[*top_oper] == '*')
{
value = num_2 * num_1;
}
else if(oper[*top_oper] == '/')
{
value = num_2 / num_1;
}
(*top_num) --; /*Move the top of the data stack down one bit*/
operand[*top_num] = value; /*Push the obtained value into the data stack*/
(*top_oper) --; /*Move the top of the operator stack down one bit*/
}
int main()
{
int operand[MAX_SIZE] = {0}; /*data stack, initialize*/
int top_num = -1;
char oper[MAX_SIZE] = {0}; /*operator stack, initialize*/
int top_oper = -1;
char *str = (char *) malloc (sizeof(char) * 100); /*get expression (without =)*/
scanf("%s", str);
char* temp;
char dest[MAX_SIZE];
int num = 0;
int i = 0;
while(*str != '\0')
{
temp = dest;
while(*str >= '0' && *str <= '9') /*judging whether it is data*/
{
*temp = *str;
str++;
temp++;
} /*Encounter a symbol to exit*/
if(*str != '(' && *(temp - 1) != '\0') /*Determine whether the symbol is '('*/
{
*temp = '\0';
num = atoi(dest); /*convert string to number*/
insert_operand(operand, &top_num,num); /*Push data into the data stack*/
}
while(1)
{
i = compare(oper,&top_oper,*str); /*judgment operator priority*/
if(i == 0)
{
insert_oper(oper,&top_oper,*str); /*press operator*/
break;
}
else if(i == 1) /*judging whether the expression in brackets ends*/
{
str++;
}
else if(i == -1) /* data processing */
{
deal_date(operand,oper,&top_num,&top_oper);
}
}
`
str ++; /* point to the next character of the expression */
}
`
printf("%d\n",operand[0]); /*output result*/
return 0;
I tried to count the equation even if there is a space in it. Can someone please help?
Solving the problem by removing spaces:
So if you're working with equation as string you can simply remove spaces with function like this (there will be probably better way or function in library string.h but this was first guess):
char* DeleteSpaces( char* stringWithSpaces, size_t lengthOfString)
{
char* stringWithoutSpaces = (char*)calloc(lengthOfString + 1, sizeof(char));
if( !stringWithoutSpaces )
return NULL;
for( unsigned int x = 0, y = 0; x <= lengthOfString; x++, y++ )
{
if( stringWithSpaces[x] == ' ' ) // if the character is space
{
while( stringWithSpaces[x] == ' ' && x < lengthOfString ) // skip all the spaces OR go away before you hit '\0'
x++;
stringWithoutSpaces[y] = stringWithSpaces[x]; // then copy next character into new string
}
else // if there's no space just copy the character
stringWithoutSpaces[y] = stringWithSpaces[x];
}
return stringWithoutSpaces;
}
This will basically remove all spaces from your received equation. If you really need the smallest possible memory requirement you can use realloc() at the end of the function for more optimal memory usage.
Here's simple example of how to use the function so you can test it:
int main()
{
char firstString[] = "H e l l o w o r l d\0";
char* secondString;
secondString = DeleteSpaces( firstString, strlen(firstString) );
if( !secondString )
return -1;
printf( "%s", secondString );
free( secondString );
return 0;
}
Don't forget to use free(SecondString). I hope I helped you atleast a little :)
As with the previous answer, I added in a function to remove any spaces from the entered formula in order to process the requested calculation. Also, coupled with that, I revised the "scanf" input to read in all of the entered characters which looked to be another symptom you were facing. With that, following is a refactored version of your program with the additional space compression function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 1024
int insert_operand(int *operand, int * top_num, int num) /* data is pushed into the data stack*/
{
(*top_num) ++;
operand[*top_num] = num; /*save data*/
return 0; /*Exit normally*/
}
int insert_oper (char * oper , int *top_oper , char ch)
{
(*top_oper)++;
oper[*top_oper] = ch; /*save operator*/
return 0; /*Exit normally*/
}
int compare(char *oper , int *top_oper , char ch) /* compare the priority of the operating server*/
{
if((oper[*top_oper] == '-' || oper[*top_oper] == '+') /*Determine whether the current priority is higher than the priority of the operator at the top of the stack*/
&& (ch == '*' || ch == '/'))
{
return 0;
}
else if(*top_oper == -1 || ch == '('
|| (oper[*top_oper] == '(' && ch != ')')) /*Determine whether the operator stack is empty; whether the top operator is '('*/
{
return 0;
}
else if (oper[*top_oper] =='(' && ch == ')')
{
(*top_oper)--;
return 1;
}
else
{
return -1; /*Operate the operator*/
}
}
int deal_date(int *operand ,char *oper ,int *top_num, int *top_oper) /*perform data operation*/
{
int num_1 = operand[*top_num]; /*Take out two data from the data stack*/
int num_2 = operand[*top_num - 1];
int value = 0;
if(oper[*top_oper] == '+')
{
value = num_1 + num_2;
}
else if(oper[*top_oper] == '-')
{
value = num_2 - num_1;
}
else if(oper[*top_oper] == '*')
{
value = num_2 * num_1;
}
else if(oper[*top_oper] == '/')
{
value = num_2 / num_1;
}
(*top_num) --; /*Move the top of the data stack down one bit*/
operand[*top_num] = value; /*Push the obtained value into the data stack*/
(*top_oper) --; /*Move the top of the operator stack down one bit*/
return value;
}
void compress(char *stx) /* The additional function */
{
char work[101];
int i = strlen(stx);
strcpy(work, stx);
for (int j = 0; j < i; j++)
{
stx[j] = 0;
}
i = 0;
for (int j = 0; j < (int)strlen(work); j++)
{
if (work[j] != ' ')
{
stx[i] = work[j];
i++;
}
}
}
int main()
{
int operand[MAX_SIZE] = {0}; /*data stack, initialize*/
int top_num = -1;
char oper[MAX_SIZE] = {0}; /*operator stack, initialize*/
int top_oper = -1;
char *str = (char *) malloc (sizeof(char) * 100); /*get expression (without =)*/
//scanf("%s", str);
scanf("%[^\n]", str); /* Refined the scanf call to receive all characters prior to the newline/return character */
compress(str); /* Added this function to remove spaces */
char* temp;
char dest[MAX_SIZE];
int num = 0;
int i = 0;
while(*str != '\0')
{
temp = dest;
while(*str >= '0' && *str <= '9') /*judging whether it is data*/
{
*temp = *str;
str++;
temp++;
} /*Encounter a symbol to exit*/
if(*str != '(' && *(temp - 1) != '\0') /*Determine whether the symbol is '('*/
{
*temp = '\0';
num = atoi(dest); /*convert string to number*/
insert_operand(operand, &top_num,num); /*Push data into the data stack*/
}
while(1)
{
i = compare(oper,&top_oper,*str); /*judgment operator priority*/
if(i == 0)
{
insert_oper(oper,&top_oper,*str); /*press operator*/
break;
}
else if(i == 1) /*judging whether the expression in brackets ends*/
{
str++;
}
else if(i == -1) /* data processing */
{
deal_date(operand,oper,&top_num,&top_oper);
}
}
str ++; /* point to the next character of the expression */
}
printf("%d\n",operand[0]); /*output result*/
return 0;
}
Testing out your sample formula with some additional spacing to ensure the compression function was working properly, following was the terminal output.
#Vera:~/C_Programs/Console/Calculate/bin/Release$ ./Calculate
(2 + 3) * 2
10
Give that a try and see if it meets the spirit of your project.
As pointed out in the comments and other answers, the solution may be to simply "compact" the spaces out of the string before trying to analyse the string's content.
This doesn't require a lot of code:
#include <stdio.h>
char *stripSP( char *src ) {
for( char *d = src, *s = src; ( *d = *s ) != '\0'; s++ )
d += *d != ' ';
return src;
}
int main( void ) {
char *s[] = { "Hello", "H e l l ooo", "(2 + 5) * 3" };
for( int i = 0; i < 3; i++ ) {
printf( "From '%s' ", s[i] );
printf( "'%s'\n", stripSP( s[i] ) );
}
return 0;
}
From 'Hello' 'Hello'
From 'H e l l ooo' 'Hellooo'
From '(2 + 5) * 3' '(2+5)*3'
Even more compact would be to use array indexing:
char *stripSP( char s[] ) {
for( int f=0, t=0; (s[t] = s[f++]) != '\0'; t += s[t] != ' ' ) {}
return s;
}

How to check if the expression has division by 0 in calculator C? Floating point exception

I tried to make simple calculator supporting brackets and classic operators +,-,*,/ and I also need to eliminate division by zero in it. I may not be able to cope with it, I need to check if there is division by zero in the expression and if so function return 0. Now it returns Floating point exception. Can someone help?
My code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 1024
int insert_operand(int *operand, int * top_num, int num) /* data is pushed into the data stack*/
{
(*top_num) ++;
operand[*top_num] = num; /*save data*/
return 0; /*Exit normally*/
}
int insert_oper (char * oper , int *top_oper , char ch)
{
(*top_oper)++;
oper[*top_oper] = ch; /*save operator*/
return 0; /*Exit normally*/
}
int compare(char *oper , int *top_oper , char ch) /* compare the priority of the operating server*/
{
if((oper[*top_oper] == '-' || oper[*top_oper] == '+') /*Determine whether the current priority is higher than the priority of the operator at the top of the stack*/
&& (ch == '*' || ch == '/'))
{
return 0;
}
else if(*top_oper == -1 || ch == '('
|| (oper[*top_oper] == '(' && ch != ')')) /*Determine whether the operator stack is empty; whether the top operator is '('*/
{
return 0;
}
else if (oper[*top_oper] =='(' && ch == ')')
{
(*top_oper)--;
return 1;
}
else
{
return -1; /*Operate the operator*/
}
}
int deal_date(int *operand ,char *oper ,int *top_num, int *top_oper) /*perform data operation*/
{
int num_1 = operand[*top_num]; /*Take out two data from the data stack*/
int num_2 = operand[*top_num - 1];
int value = 0;
if(oper[*top_oper] == '+')
{
value = num_1 + num_2;
}
else if(oper[*top_oper] == '-')
{
value = num_2 - num_1;
}
else if(oper[*top_oper] == '*')
{
value = num_2 * num_1;
}
else if(oper[*top_oper] == '/')
{
value = num_2 / num_1;
}
(*top_num) --; /*Move the top of the data stack down one bit*/
operand[*top_num] = value; /*Push the obtained value into the data stack*/
(*top_oper) --; /*Move the top of the operator stack down one bit*/
return value;
}
void compress(char *stx) /* The additional function */
{
char work[101];
int i = strlen(stx);
strcpy(work, stx);
for (int j = 0; j < i; j++)
{
stx[j] = 0;
}
i = 0;
for (int j = 0; j < (int)strlen(work); j++)
{
if (work[j] != ' ')
{
stx[i] = work[j];
i++;
}
}
}
int main()
{
int operand[MAX_SIZE] = {0}; /*data stack, initialize*/
int top_num = -1;
char oper[MAX_SIZE] = {0}; /*operator stack, initialize*/
int top_oper = -1;
char *str = (char *) malloc (sizeof(char) * 100); /*get expression (without =)*/
//scanf("%s", str);
scanf("%[^\n]", str); /* Refined the scanf call to receive all characters prior to the newline/return character */
compress(str); /* Added this function to remove spaces */
char* temp;
char dest[MAX_SIZE];
int num = 0;
int i = 0;
while(*str != '\0')
{
temp = dest;
while(*str >= '0' && *str <= '9') /*judging whether it is data*/
{
*temp = *str;
str++;
temp++;
} /*Encounter a symbol to exit*/
if(*str != '(' && *(temp - 1) != '\0') /*Determine whether the symbol is '('*/
{
*temp = '\0';
num = atoi(dest); /*convert string to number*/
insert_operand(operand, &top_num,num); /*Push data into the data stack*/
}
while(1)
{
i = compare(oper,&top_oper,*str); /*judgment operator priority*/
if(i == 0)
{
insert_oper(oper,&top_oper,*str); /*press operator*/
break;
}
else if(i == 1) /*judging whether the expression in brackets ends*/
{
str++;
}
else if(i == -1) /* data processing */
{
deal_date(operand,oper,&top_num,&top_oper);
}
}
str ++; /* point to the next character of the expression */
}
printf("%d\n",operand[0]); /*output result*/
return 0;
}
Thanks for all answers
I would detect if the divisor is zero along these lines:
else if(oper[*top_oper] == '/')
{
value = num_1 ? num_2 / num_1 : 0;
}
or perhaps more verbose:
else if(oper[*top_oper] == '/')
{
if(num_1)
value = num_2 / num_1;
else
value = 0;
}
and example session:
1 / 2
0

Paranthesis matching using stack implemented through array.I Used balanced() to check if stack is empty by pushing '(' & popping '(' for every ')'

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stack {
int size;
int top;
char *arr;
};
void push(struct stack *st,char x) {
if (st->top >= st->size - 1) {
printf("stack is full");
}
else {
st->top++;
st->arr[st->top] = x;
}
}
char pop(struct stack *st) {
char x;
if (st->top < 0) {
printf("stack is empty");
}
else {
x = st->arr[st->top];
st->top--;
}
return x;
}
int isempty(struct stack st) {
if (st.top < 0) {
return 1;
}
else
return 0;
}
void display(struct stack st) {
int i;
for (i = st.top; i >= 0; i--) {
printf("%c ", st.arr[i]);
}
printf("\n");
}
int balanced(char *expr) {
int i;
struct stack st;
st.size = strlen(expr);
st.top = -1;
st.arr = (char *)malloc(st.size * sizeof(char));
for (i = 0; expr[i] != '\0'; i++) {
if (expr[i] = '(') {
push(&st, expr[i]);
}
else if (expr[i] = ')') {
if (st.top < 0) return false;
else pop(&st);
}
}
if (st.top < 0) return 1;
else return 0;
}
int main() {
char *expr = "((a+b))";
printf("%d", balanced(expr));
return 0;
}
Paranthesis matching using stack implemented in array in c programming .Nothing gets printed when I call the balanced() function.How to correct the above code?
Apart from this method is there any other way to check paranthesis matching and checking if the expression is valid too i.e; (a+)b In this paranthesis is balanced but expression is not valid
In this loop:
for (i = 0; expr[i] != '\0'; i++) {
if (expr[i] = '(') {
push(&st, expr[i]);
}
else if (expr[i] = ')') {
if (st.top < 0) return false;
else pop(&st);
}
}
You have assignments, rather than checks for equality. = vs. ==.
The first condition is always true, so every character is made '(' and pushed onto the stack. Nothing is ever popped from the stack.
You also need to include <stdbool.h> if you wish to use true and false.
Correcting those issues and running the program, the output is 1.
Others have noted the assignment that should have been test for equality.
While it's interesting to use a stack, you could also simply have used a signed integer counter initialised to zero. Increment when encountering an '(' and decrement when encountering a ')'. If the counter goes negative, or a positive final value is found, then the parentheses are not paired correctly.
The world is bigger than only parentheses. Below, another (fixed size!) stack is used to match pairs of enclosing characters. Yes, 'push/pop' of a stack is a convenient way to make sure that 'nesting' meets expectations.
As for checking legitimacy of an expression, one would have to attempt to parse the expression according to some grammar rules. That is a somewhat more complicated.
#include <stdio.h>
#include <stdbool.h>
int main() {
char *str = "{(foo)({gib(bar)gab;}) ((())) []Quick brown fox ";
char stack[ 64 ] = { 0 };
int stkInd = 1;
bool good = true;
for( char *cp = str; *cp; cp++ ) {
switch( *cp ) {
case '(': stack[ stkInd++ ] = ')'; break;
case '{': stack[ stkInd++ ] = '}'; break;
case '[': stack[ stkInd++ ] = ']'; break;
case '<': stack[ stkInd++ ] = '>'; break;
case ')':
case '}':
case ']':
case '>': good = *cp == stack[ --stkInd ]; break;
}
if( stkInd >= sizeof stack ) {
printf( "Stack Full!\n" );
return -1;
}
if( !good ) {
printf( "%s\n", str );
printf( "%*s^---\n", cp - str, " " );
printf( "Unmatched '%c'\n", *cp );
return -1;
}
}
while( stkInd > 1 ) {
char c = stack[ --stkInd ];
switch( c ) {
case ')': c = '('; break;
case '}': c = '{'; break;
case ']': c = '['; break;
case '>': c = '<'; break;
}
printf( "Unpairable %c\n", c );
}
return 0;
}
Looking again at your code, isempty( ) and display( ) may give you trouble as they both deal with a copy of the stack, rather than a pointer to the stack. Since your stack is dimensioned to match the full length of the original string, this may be viewed as wasteful. Passing the stack's address and using a pointer would be more efficient.

semantical error with parenthesis balancing here

I've written a C code to check for simple parenthesis balancing which prints NO and YES if balanced, not balanced respectively.
The problem is that I'm getting NO for all inputs. Hence I'm thinking that its a semantic error but cannot find it (I have been trying for 2 days :p)
Could someone please help me here? thanks!
#include <stdio.h>
#include <stdlib.h>
typedef struct stack {
char s[1000];
int top;
} STACK;
void create(STACK *sptr) {
sptr->top = -1;
}
int isEmpty(STACK *sptr) {
if (sptr->top == -1)
return 1;
else
return 0;
}
void push(STACK *sptr, char data) {
sptr->s[++sptr->top] = data;
}
char pop(STACK *sptr) {
if (isEmpty(sptr) == 0)
return sptr->s[sptr -> top];
else
return '$';
}
char *isBalanced(char *s, STACK *sptr) {
char *y, *n;
int i = 0;
y = (char*)malloc(sizeof(char) * 4);
y[0] = 'Y';
y[1] = 'E';
y[2] = 'S';
y[3] = '\0';
n = (char*)malloc(sizeof(char) * 3);
n[0] = 'N';
n[1] = 'O';
n[2] = '\0';
while (s[i] != '\0') {
if (s[i] == '(' || s[i] == '{' || s[i] == '[') {
push(sptr, s[i]);
} else {
char x = pop(sptr);
switch (s[i]) {
case ')':
if (x != '(')
return n;
break;
case '}':
if (x != '{')
return n;
break;
case ']':
if (x != '[')
return n;
break;
}
}
++i;
}
if (isEmpty(sptr))
return y;
else
return n;
}
int main() {
STACK *sptr = (STACK *)malloc(sizeof(STACK));
char c[21];
int ch;
do {
printf("enter sequence:");
scanf("%s", c);
char *msg = isBalanced(c, sptr);
printf("%s", msg);
printf("choice?:");
scanf("%d", &ch);
} while(ch);
}
updated code:
#include <stdio.h>
#include <stdlib.h>
typedef struct stack {
char s[1000];
int top;
} STACK;
void create(STACK *sptr) {
sptr->top = -1;
}
int isEmpty(STACK *sptr) {
if (sptr->top == -1)
return 1;
else
return 0;
}
void push(STACK *sptr, char data) {
sptr->s[++sptr->top] = data;
}
char pop(STACK *sptr) {
if (isEmpty(sptr) == 0)
return sptr->s[sptr->top--];
else
return '$';
}
int isBalanced(char *s, STACK *sptr) {
int i = 0;
while (s[i] != '\0') {
if (s[i] == '(' || s[i] == '{' || s[i] == '[') {
push(sptr, s[i]);
} else {
char x = pop(sptr);
switch (s[i]) {
case ')':
if (x != '(')
return 0;
break;
case '}':
if (x != '{')
return 0;
break;
case ']':
if (x != '[')
return 0;
break;
}
}
++i;
}
if (isEmpty(sptr))
return 1;
else
return 0;
}
int main() {
STACK *sptr = malloc(sizeof(STACK));
char c[21];
int ch;
do {
printf("enter sequence:");
scanf("%s", c);
printf("%s", (isBalanced(c, sptr) ? "YES" : "NO"));
printf("choice?:");
scanf("%d", &ch);
} while(ch);
}
Here are some major issues in your code:
you do not properly initialize the stack with create(sptr) before use, preferably in main() where it is defined. Your code has undefined behavior. It prints NO by chance, probably because sptr->top has an initial value of 0, which makes the stack non-empty.
you should only pop from the stack when you encounter a closing delimiter ), ] or }.
you should prevent potential buffer overflow by telling scanf() the maximum number of characters to read into c: scanf("%20s", c). Furthermore you should test the return value to avoid undefined behavior at end of file.
Note also that the STACK can be made a local variable to avoid heap allocation and potential allocation failure, which would cause undefined behavior since it is not tested.
Here is a corrected version:
#include <stdio.h>
typedef struct stack {
char s[1000];
int top;
} STACK;
void create(STACK *sptr) {
sptr->top = -1;
}
int isEmpty(STACK *sptr) {
if (sptr->top == -1)
return 1;
else
return 0;
}
void push(STACK *sptr, char data) {
sptr->s[++sptr->top] = data;
}
char pop(STACK *sptr) {
if (isEmpty(sptr) == 0)
return sptr->s[sptr->top--];
else
return '$';
}
int isBalanced(char *s, STACK *sptr) {
int i;
for (i = 0; s[i] != '\0'; i++) {
switch (s[i]) {
case '(':
case '{':
case '[':
push(sptr, s[i]);
break;
case ')':
if (pop(sptr) != '(')
return 0;
break;
case '}':
if (pop(sptr) != '{')
return 0;
break;
case ']':
if (pop(sptr) != '[')
return 0;
break;
}
}
return isEmpty(sptr);
}
int main() {
STACK s, *sptr = &s;
char c[100];
int ch;
do {
printf("Enter sequence: ");
if (scanf(" %99[^\n]", c) != 1)
break;
create(sptr);
printf("%s\n", isBalanced(c, sptr) ? "YES" : "NO");
printf("Choice? ");
if (scanf("%d", &ch) != 1)
break;
} while (ch);
return 0;
}
In your pop function you are not decrementing the top thus your isEmpty function always returns false.
Hence you return no always.
char* isBalanced(char* s, STACK* sptr)
{
....
if(isEmpty(sptr)) return y;
else return n;
}
The following is the correct implementation:
char pop(STACK* sptr)
{
if(isEmpty(sptr) == 0)
return sptr->s[sptr->top--];
else
return '$';
}
I assume that the idea is this: an opening paren is always permitted (in the analyzed text), but a closing paren must match the last opened. This is why a stack is required. Also, in the end, if the stack is not empty that means that some parens were not closed.
So, you should use the stack, but only when you encounter parens - either opening or closing.
In the function isBalanced(), the main cycle could be this:
while (s[i] != '\0') {
if ( s[i] == '(' || s[i] == '{' || s[i] == '[' ) {
// opening - remember it
push(sptr, s[i]);
} else if ( s[i] == ')' || s[i] == '}' || s[i] == ']' ) {
// closing - it should match
if ( ! popmatch(sptr, s[i]) )
return n;
}
++i;
}
The rest of the function is ok. Now, I modified the the pop() function: renamed to popmatch, because it should check if the argument matches the top of the stack. If it does, pop the stack and return OK. So the function would be:
char popmatch(STACK* sptr, char c) {
// an empty stack can not match
if (isEmpty(sptr))
return 0;
// not empty, can check for equality
if ( c =! sptr->s[sptr->top] )
return 0;
// does not match!
// ok, it matches so pop it and return ok
sptr->top--;
return 1;
}
Please note that the code mirrors pretty well the "analysis"; when the analysis is short and clear, and the code follows the analysis, the result often is short and clear too.
I would add the flags to see which one does not match
unsigned match(const char *f)
{
int p = 0,s = 0,b = 0;
while(*f)
{
switch(*f++)
{
case '(':
p++;
break;
case ')':
p -= !!p;
break;
case '[':
s++;
break;
case ']':
s -= !!s;
break;
case '{':
b++;
break;
case '}':
b -= !!b;
break;
default:
break;
}
}
return (!p) | ((!s) << 1) | ((!b) << 2);
}
Not the stack version but just for the idea. It is rather easy to add push and pop

Infix to Postfix Algorithm in C

I'm solve an exercise in which one of the functions has to translate infix notation to postfix notation. Here follows my whole code
#include<stdio.h>
#define MAX 100
char stack[MAX];
int top;
void compact(char Descomp[], char Compac[]);
void init_stack();
int push(char Elem);
int desempilha(char *Elem);
int priority(char Operator);
int arity(char Exp[], int position);
int translate_pos(char exp[], char exp_pos[]);
int main()
{
char Exp[MAX]; /* stores the expression read from stdin */
char Exp_compact[MAX]; /* stores expression without spaces */
char Exp_pos[MAX]; /* stores the expression after the translation for postfix*/
int indicator; /* indicate if an error occurred, 0 for NO ERROR and -1 for ERROR*/
indicator = 0;
printf("\nType the expression: ");
gets(Exp);
compact(Exp, Exp_compact);
indicator = translate_pos(Exp_compact, Exp_pos);
puts(Exp_pos);
return indicator;
}
/* compact function delete spaces within the expression read from stdin */
void compact(char Descomp[], char Compac[])
{
int i;
int j;
i = 0;
j = 0;
while(Descomp[j] != '\0')
{
if(Descomp[j] != ' ')
{
Compac[i] = Descomp[j];
i++;
}
j++;
}
}
/* initiate the stack by setting top = -1 */
void init_stack()
{
top = -1;
}
/* puts the element Elem in the stack */
int push(char Elem)
{
if(top == MAX - 1) /* Stack is full */
return -1;
top++;
stack[top] = Elem;
return 0;
}
/* remove the element in stack[top] and puts it in &Elem*/
int pop(char *Elem)
{
if(top == -1) /* stack is empty */
return -1;
*Elem = stack[top];
top--;
return 0;
}
/* Return the priority of an operator */
int priority(char Operator)
{
switch(Operator)
{
case '+': return 1;
case '-': return 1;
case '*': return 2;
case '/': return 2;
case '^': return 3;
case '(': return 4;
case ')': return 5;
default : return 0;
}
}
/* returns the arity of CONSTANTS + - * / and ^, for ( an ) is merely symbolic */
int arity(char Exp[], int position)
{
if(priority(Exp[position]) == 1)
{
if( (position == 0) || ( (priority(Exp[position - 1]) >= 1) && (priority(Exp[position - 1]) <= 3) ))
return 1;
else
return 2;
}
else if( (priority(Exp[position]) > 1) && (priority(Exp[position]) <= 4))
return 2;
else
return priority(Exp[position]);
}
/* reads an infix expression and returns postfix expression */
int translate_pos(char exp[], char exp_pos[])
{
int i;
int j;
int ind;
char trash;
i = 0;
j = 0;
ind = 0;
trash = ' ';
init_stack();
while(exp[i]!= '\0')
{
if(arity(exp, i) == 0)
{
exp_pos[j] = exp[i];
j++;
}
if(arity(exp, i) == 1)
{
switch(exp[i])
{
case '-':
{
exp_pos[j] = exp_pos[i];
j++;
}
case '+': trash = exp_pos[i];
}
}
if(arity(exp, i) == 2)
{
while((top != -1) && (priority(stack[top]) <= priority(exp[i])))
{
ind = pop(&exp_pos[j]);
j++;
}
ind = push(exp[i]);
}
if(priority(exp[i]) == 4)
{
ind = push(exp[i]);
}
if(priority(exp[i]) == 5)
{
while( (top != -1) && (stack[top] != '('))
{
ind = pop(&exp_pos[j]);
j++;
}
if(stack[top] == '(')
ind = pop(&trash);
}
i++;
}
while(top != -1)
{
ind = pop(&exp_pos[j]);
j++;
}
return ind;
}
The algorithm I used to translate the expression is
while there is token to be read;
read the token;
if token is a constant
push it to Exp_Postfix;
if token is '('
push it to stack
if token is ')'
pop from the stack all symbols until '(' be find and remove '(' from the stack
if token is an operator and its arity is 2
pop all operators with less or equal priority than the token and store then in the Exp_Postfix;
push token to the stack;
if token is an operator and its arity is 1
if token is '-'
push it to Exp_postfix;
if token is '+'
pass to the next token;
pop all remaining symbols in the stack and push then, in order, to the Exp_Postfix;
I compiled the .c archive using
gcc -Wall archive.c -o archive
and executed it. I give the expression
5+(6*9^14)
It the returned expression was
5
I do not now if the error is in my code or in solution to the problem.
There are an awful lot of problems, here, for instance:
compact() and translate_pos() leave Exp_compact and Exp_pos, respectively, without a terminating \0, so you're getting garbage printed out.
your arity() function is returning 2 for an opening parenthesis.
in the first switch statement of translate_pos(), you're missing break statements.
Your priority comparison in translate_pos() when arity is 2 is back to front.
When you're comparing operator precedence, you should treat an opening parenthesis specially, since it should have the lowest precedence when on the top of the stack.
You should have a lot more else keywords in translate_pos().
You're using gets(), which was always bad, and now has actually been removed from C.
I haven't exhaustively tested it, but here's a correct version that seems to work for all the test inputs I tried:
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
/* Function prototypes */
void compact(char Descomp[], char Compac[]);
void init_stack();
int push(char Elem);
int desempilha(char *Elem);
int priority(char Operator);
int arity(char Exp[], int position);
int translate_pos(char exp[], char exp_pos[]);
/* Stack variables */
#define MAX 100
char stack[MAX];
int top;
int main(void) {
char Exp[MAX];
char Exp_compact[MAX] = {0};
char Exp_pos[MAX] = {0};
int indicator = 0;
printf("\nType the expression: ");
fgets(Exp, MAX, stdin);
compact(Exp, Exp_compact);
indicator = translate_pos(Exp_compact, Exp_pos);
puts(Exp_pos);
return indicator;
}
/* compact function delete spaces within the expression read from stdin */
void compact(char Descomp[], char Compac[]) {
int i = 0;
int j = 0;
while ( Descomp[j] ) {
if ( !isspace(Descomp[j]) ) {
Compac[i++] = Descomp[j];
}
j++;
}
}
/* initiate the stack by setting top = -1 */
void init_stack() {
top = -1;
}
/* puts the element Elem in the stack */
int push(char Elem) {
if (top == MAX - 1) /* Stack is full */
return -1;
stack[++top] = Elem;
return 0;
}
/* remove the element in stack[top] and puts it in &Elem*/
int pop(char *Elem) {
if (top == -1) /* stack is empty */
return -1;
*Elem = stack[top--];
return 0;
}
/* Return the priority of an operator */
int priority(char Operator) {
switch (Operator) {
case '+':
return 1;
case '-':
return 1;
case '*':
return 2;
case '/':
return 2;
case '^':
return 3;
case '(':
return 4;
case ')':
return 5;
default:
return 0;
}
}
/* returns the arity of OPERATORS + - * / and ^,
* for ( an ) is merely symbolic */
int arity(char Exp[], int position) {
if ( priority(Exp[position]) == 1 ) {
if ( (position == 0) ||
((priority(Exp[position - 1]) >= 1) &&
(priority(Exp[position - 1]) <= 3)) ) {
return 1;
} else {
return 2;
}
} else if ( (priority(Exp[position]) > 1) &&
(priority(Exp[position]) <= 3) ) {
return 2;
} else {
return priority(Exp[position]);
}
}
/* reads an infix expression and returns postfix expression */
int translate_pos(char exp[], char exp_pos[]) {
int i = 0, j = 0, ind = 0;
char trash = ' ';
init_stack();
while ( exp[i] ) {
if ( arity(exp, i) == 0 ) {
exp_pos[j++] = exp[i];
} else if ( arity(exp, i) == 1 ) {
switch (exp[i]) {
case '-':
exp_pos[j++] = exp[i];
break;
case '+':
trash = exp_pos[i];
break;
default:
assert(0);
}
} else if (arity(exp, i) == 2) {
while ( (top != -1) &&
(priority(stack[top]) >= priority(exp[i])) &&
stack[top] != '(' ) {
ind = pop(&exp_pos[j++]);
}
ind = push(exp[i]);
} else if ( priority(exp[i]) == 4 ) {
ind = push(exp[i]);
} else if ( priority(exp[i]) == 5 ) {
while ( (top != -1) && (stack[top] != '(') ) {
ind = pop(&exp_pos[j++]);
}
if ( (top != - 1) && stack[top] == '(') {
ind = pop(&trash);
}
}
i++;
}
while (top != -1) {
ind = pop(&exp_pos[j++]);
}
return ind;
}
Gives the following output for various test cases:
paul#local:~/src/c/postfix$ ./postfix
Type the expression: 1+2
12+
paul#local:~/src/c/postfix$ ./postfix
Type the expression: (1+2)
12+
paul#local:~/src/c/postfix$ ./postfix
Type the expression: 1+2*3
123*+
paul#local:~/src/c/postfix$ ./postfix
Type the expression: (1+2)*3
12+3*
paul#local:~/src/c/postfix$ ./postfix
Type the expression: (3+4)*4/2
34+4*2/
paul#local:~/src/c/postfix$ ./postfix
Type the expression: 5+(6*9^14)
56914^*+
paul#local:~/src/c/postfix$
I'd suggest comparing my code to yours and trying to understand the individual differences to see where you were going wrong.

Resources