I am trying to evaluate a binary tree (inorder). The result always remains
the same or giving an unexpected answer. I do not know where the problem is, can
anyone help me? First I have converted postfix expression to expression tree than evaluate expression tree. I shall be very thankful.
The result is unexpected when I run this program. This the header file.
#define POST2EXPTREE_H_INCLUDED
#define MAX 100
struct node
{
char ch;
struct node *left;
struct node *right;
} *stack[MAX];
typedef struct node node;
void push(node *str);
node *pop();
void convert(char exp[]);
void display(node *temp);
#endif
#include <stdio.h>
#include <stdlib.h>
#include"post2expTree.h"
#define SIZE 100
int top = -1;
void push(node *str)
{
if (top >= MAX-1)
printf("Stack is Full ");
else
{
stack[top] = str;
top++;
}
}
node *pop()
{
node *exp;
if (top < 0)
printf("Stack is Empty ");
else
exp = stack[--top];
return exp;
}
void convert(char exp[])
{
node *op1, *op2;
node *temp;
int i;
for (i=0;exp[i]!='\0';i++)
if (exp[i] >= 'a'&& exp[i] <= 'z'|| exp[i] >= 'A' && exp[i] <= 'Z' ||isalnum(exp[i]))
{
temp = (node*)malloc(sizeof(node));
temp->ch = exp[i];
temp->right = NULL;
temp->left = NULL;
push(temp);
}
else if (exp[i] == '+' || exp[i] == '-' || exp[i] == '*' || exp[i] == '/' || exp[i] == '%'
|| exp[i] == '^')
{
op1 = pop();
op2 = pop();
temp = (node*)malloc(sizeof(node));
temp->ch = exp[i];
temp->right = op1;
temp->left = op2;
push(temp);
}
}
void display(node *temp)
{
if (temp != NULL)
{
display(temp->left);
printf("%c", temp->ch);
display(temp->right);
}
}
int evaluate(node *temp)
{
int left,right,value;
if ((temp->ch) >= 0 || (temp->ch <=9))
{
return temp->ch;
}
else
{
left = evaluate(temp -> left);
right = evaluate(temp -> right);
switch(temp->ch)
{
case '+':
value = left + right;
break;
case '-':
value = left - right;
break;
case '*':
value = left * right;
break;
case '/':
value = left / right;
break;
case '%':
value = left % right;
break;
case '^':
value = left ^ right;
break;
}
temp->ch = value;
}
return value;
}
int top = -1;
void push(node *str)
{
if (top >= MAX-1)
printf("Stack is Full ");
else
{
stack[top] = str;
top++;
}
}
Here top is initialized to -1, and the very first push() wrongly accesses stack[-1]; correct that by changing the else block to stack[++top] = str;.
node *pop()
{
node *exp;
if (top < 0)
printf("Stack is Empty ");
else
exp = stack[--top];
return exp;
}
Here top is decremented before accessing the stack off by one; correct that by changing the else block to exp = stack[top--];.
int evaluate(node *temp)
{
int left,right,value;
if ((temp->ch) >= 0 || (temp->ch <=9))
{
return temp->ch;
Here you forgot that you store the operands as single digits '0' to '9', not as values 0 to 9. Correct that by changing to:
int left, right, value = temp->ch-'0';
if (value >= 0 && value <= 9)
{
return value;
Related
I have spent the last two hours trying to debug my code that is supposed to check if the input consists of well-formed brackets. What I mean by well formed is that ()()[] or ([()]) are acceptable but ((((() is not.
I'm not allowed to use any header file apart from <stdio.h>
#include <stdio.h>
void cross(char str[], int i, int j) {
str[i] = 'X';
str[j] = 'X';
}
int iscrossed(char str[]) {
int i = 0;
while (str[i] != '\0') {
if (str[i] != 'X')
return 0;
i++;
}
return 1;
}
int check(char str[]) {
int i = 1, j;
while (str[i] != '\0') {
if (str[i] == ')') {
for (j = i - 1; j >= 0; j--) {
if (str[j] == '(') {
cross(str, str[i], str[j]);
}
break;
}
} else
if (str[i] == ']') {
for (j = i - 1; j >= 0; j--) {
if (str[j] == '[') {
cross(str, str[i], str[j]);
}
break;
}
}
i++;
}
if (iscrossed(str) == 1)
return 1;
else
return 0;
}
int main() {
char str[20];
scanf("%s", str);
printf("%d\n", check(str));
}
For certain inputs the program prints a zero followed by a segmentation fault and for the others it just prints a zero.
Please keep in mind that I'm a beginner programmer so please don't include too much heavy stuff in your hints. I'd be grateful for any help on this.
Edit: It would be wonderful if your answer tells me the errors in my code, because that was my question in the first place.
Here a simple recursive solution:
#include <stdio.h>
int brace(const char **s, char cc)
{
while(1) {
if(**s == cc) { return 0; }
switch(**s) {
case '\0': return -1;
case '[': ++(*s); if(brace(s, ']')) { return -1; } ++(*s); break;
case '{': ++(*s); if(brace(s, '}')) { return -1; } ++(*s); break;
case '(': ++(*s); if(brace(s, ')')) { return -1; } ++(*s); break;
case ']':
case '}':
case ')': return -1;
default: ++(*s);
}
}
}
int check_brace(const char *s)
{
return brace(&s, '\0');
}
int main()
{
printf("%d\n", check_brace(" hekl(l o{ asdf } te)ts()({})"));
}
Returns -1 when somethings wrong. Otherwise 0.
There are multiple problems in your code:
you call cross(str, str[i], str[j]); instead of cross(str, i, j); when you find matches for parentheses and brackets.
the break statement should be moved inside the if block.
your method does not allow detection of nesting errors
your method would have undefined behavior if str is an empty string (which you cannot input via scanf())
Here is a modified version:
#include <stdio.h>
void cross(char str[], int i, int j) {
str[i] = str[j] = 'X';
}
int iscrossed(char str[]) {
int i = 0;
while (str[i] != '\0') {
if (str[i] != 'X')
return 0;
i++;
}
return 1;
}
int check(char str[]) {
int i = 0, j;
while (str[i] != '\0') {
if (str[i] == ')') {
for (j = i - 1; j >= 0; j--) {
if (str[j] == '(') {
cross(str, i, j);
break;
}
}
} else
if (str[i] == ']') {
for (j = i - 1; j >= 0; j--) {
if (str[j] == '[') {
cross(str, i, j);
break;
}
}
}
i++;
}
return iscrossed(str);
}
int main() {
char str[80];
if (scanf("%79s", str) == 1) {
printf("%d\n", check(str));
}
return 0;
}
Here is a simpler alternative:
#include <stdio.h>
const char *check(const char str[], int endc) {
while (str) {
int c = *str++;
switch (c) {
case '(': str = check(str, ')'); break;
case '[': str = check(str, ']'); break;
case '{': str = check(str, '}'); break;
case ')':
case ']':
case '}':
case '\0': return c == endc ? str : NULL;
}
}
return NULL;
}
int main() {
char str[80];
if (fgets(str, sizeof str, stdin)) {
printf("%d\n", check(str, '\0') != NULL);
}
return 0;
}
Pseudocode of a possible answer:
initialize char[] unclosed
int latest_unclosed_index = -1
for each char in string {
if char == opening_bracket {
latest_unclosed_index += 1
unclosed[latest_unclosed_index] = char
} else if char == closing_bracket {
if latest_unclosed_index < 0 {
return false
} else if char == closing_of(unclosed[latest_unclosed_index]) {
unclosed[latest_unclosed_index] = null
latest_unclosed_index -= 1
} else {
return false
}
}
}
if latest_unclosed_index == -1 {
return true
} else {
return false
}
This works by keeping an array of all unclosed opening brackets in the order that you encounter them in, and removing them whenever you encounter a closing bracket, as a sort of stack.
This solution has a complexity of O(n).
A problem with this implementation is that there is an unknown amount of brackets in string, which may cause the array to overflow if it isn't large enough.
Solution:
To be sure that this solution doesn't overflow, the size of the array should be at least half the size of the input string, and you'll have to check at each character if there are enough characters left in the input string to be able to completely close all brackets.
Use a list implementation (or write your own) instead of an array for unclosed.
If its ok for you to use stdlib.h then,
#include <stdio.h>
#include <stdlib.h>
#define bool int
// structure of a stack node
struct sNode {
char data;
struct sNode* next;
};
// Function to push an item to stack
void push(struct sNode** top_ref, int new_data);
// Function to pop an item from stack
int pop(struct sNode** top_ref);
// Returns 1 if character1 and character2 are matching left
// and right Brackets
bool isMatchingPair(char character1, char character2)
{
if (character1 == '(' && character2 == ')')
return 1;
else if (character1 == '{' && character2 == '}')
return 1;
else if (character1 == '[' && character2 == ']')
return 1;
else
return 0;
}
// Return 1 if expression has balanced Brackets
bool areBracketsBalanced(char exp[])
{
int i = 0;
// Declare an empty character stack
struct sNode* stack = NULL;
// Traverse the given expression to check matching
// brackets
while (exp[i])
{
// If the exp[i] is a starting bracket then push
// it
if (exp[i] == '{' || exp[i] == '(' || exp[i] == '[')
push(&stack, exp[i]);
// If exp[i] is an ending bracket then pop from
// stack and check if the popped bracket is a
// matching pair*/
if (exp[i] == '}' || exp[i] == ')'
|| exp[i] == ']') {
// If we see an ending bracket without a pair
// then return false
if (stack == NULL)
return 0;
// Pop the top element from stack, if it is not
// a pair bracket of character then there is a
// mismatch.
// his happens for expressions like {(})
else if (!isMatchingPair(pop(&stack), exp[i]))
return 0;
}
i++;
}
// If there is something left in expression then there
// is a starting bracket without a closing
// bracket
if (stack == NULL)
return 1; // balanced
else
return 0; // not balanced
}
// Driver code
int main()
{
char exp[100] = "{()}[]";
// Function call
if (areBracketsBalanced(exp))
printf("Balanced \n");
else
printf("Not Balanced \n");
return 0;
}
// Function to push an item to stack
void push(struct sNode** top_ref, int new_data)
{
// allocate node
struct sNode* new_node
= (struct sNode*)malloc(sizeof(struct sNode));
if (new_node == NULL) {
printf("Stack overflow n");
getchar();
exit(0);
}
// put in the data
new_node->data = new_data;
// link the old list off the new node
new_node->next = (*top_ref);
// move the head to point to the new node
(*top_ref) = new_node;
}
// Function to pop an item from stack
int pop(struct sNode** top_ref)
{
char res;
struct sNode* top;
// If stack is empty then error
if (*top_ref == NULL) {
printf("Stack overflow n");
getchar();
exit(0);
}
else {
top = *top_ref;
res = top->data;
*top_ref = top->next;
free(top);
return res;
}
}
Features
Support nested parantheses like (())
Support bad nestings such as ([)]
Commented but not by me (see the below spoiler)
Note: i feel guilty that i have copied code from here
The algorithm
Pseudocode Like Block code!
If it's not ok for you to use stdlib.h,then someone may edit this code and remove the errors that occur when we remove that line(#include <stdlib.h>),I am not a c guy and i don't know to edit,i just copy pasted !
First attempt didn't worked with bad nesting, as MOehm wrote in the comments.
Storing the opened braces that not have been closed yet helps to recognize bad nesting. The last opened brace will determine which closing brace is need.
#include <stdio.h>
int check(char str[], int size)
{
char opened[size/2];
char close;
int i = 0;
int pos = 0;
int error = 0;
while((i < size) || (pos < size/2))
{
if((str[i] == '(') || (str[i] == '['))
{
opened[pos] = str[i];
pos++;
}
else if((str[i] == ')') || (str[i] == ']'))
{
if(str[i] == close)
{
opened[pos-1] = 0;
pos--;
}
else
{
error = 1;
break;
}
}
printf("%s\n", opened);
if(pos > 0)
{
switch(opened[pos-1])
{
case '(':
close = ')';
break;
case '[':
close = ']';
break;
}
}
else
close = 0;
i++;
}
return error;
}
int main() {
char str[20];
printf("%d\n", check(str, sizeof(str)));
return 0;
}
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
Am building a stack in C. Stack occasionally fails with a EXC_BAD_ACCESS error on the if check in my isEmpty() function, and I'm not sure why.
Typedefs & definitions:
#define NodeSize sizeof(StackNode)
struct stackNode {
int data;
struct stackNode *nextPtr;
};
typedef struct stackNode StackNode;
typedef StackNode *StackNodePtr;
Stack operation functions
void push(StackNodePtr *topPtr, int value) {
// Declare a new node and set it to the top
StackNode *node;
node = malloc(sizeof(NodeSize));
node->data = value;
node->nextPtr = *topPtr;
// Reassign the pointer to the top
*topPtr = node;
printStack(*topPtr);
}
int pop(StackNodePtr *topPtr) {
StackNode *node = *topPtr;
if (isEmpty(node)) {
return 0;
}
// Grab the current top node and reset the one beneath it to the top pointer.
*topPtr = node->nextPtr;
printStack(*topPtr);
return node->data;
}
int isEmpty(StackNodePtr topPtr) {
if (topPtr == NULL || topPtr->nextPtr == NULL) { // BAD_ACCESS
return 1;
}
return 0;
}
void printStack(StackNodePtr topPtr) {
StackNode *iter = topPtr;
// If the stack is immediately empty, just print that.
if (!isEmpty(iter->nextPtr)) {
// Iterate over each element in the stack and print its data
for (;isEmpty(iter); iter = iter->nextPtr) {
printf("%d ", iter->data);
}
printf("NULL");
} else {
printf("NULL");
}
printf("\n");
}
void evaluatePostfixExpression(char *expr) {
// Create the stack and insert an initial parenthesis
StackNode *head;
head = malloc(NodeSize);
for (int i = 0; expr[i] != '\0'; i++) {
char token = expr[i];
// If the current character is a digit
if (token >= '0' && token <= '9') {
push(&head, token - '0');
// If it's an operator
} else if (token == '+' || token == '-' || token == '*' || token == '/' || token == '^' || token == '%') {
int x = pop(&head);
int y = pop(&head);
int result = calculate(y, x, token);
push(&head, result);
}
}
int output = pop(&head);
printf("The value of the expression is: %d\n", output);
}
int calculate(int op1, int op2, char operator) {
switch (operator) {
case '+':
return op1 + op2;
case '-':
return op1 - op2;
case '*':
return op1 * op2;
case '/':
return op1 / op2;
case '%':
return op1 % op2;
}
if (operator == '^') {
int result = 1;
for (int i = 0; i < op2; i++) {
result *= op1;
}
return result;
}
return 0;
}
Even just a hint in the right direction would be appreciated.
Request for context:
int main() {
char postfix[255] = "54*81+4/+";
evaluatePostfixExpression(postfix);
return 0;
}
void evaluatePostfixExpression(char *expr) {
// Create the stack and insert an initial parenthesis
StackNode *head;
head = malloc(NodeSize);
for (int i = 0; expr[i] != '\0'; i++) {
char token = expr[i];
// If the current character is a digit
if (token >= '0' && token <= '9') {
push(&head, token - '0');
// If it's an operator
} else if (token == '+' || token == '-' || token == '*' || token == '/' || token == '^' || token == '%') {
int x = pop(&head);
int y = pop(&head);
int result = calculate(y, x, token);
push(&head, result);
}
}
int output = pop(&head);
printf("The value of the expression is: %d\n", output);
}
int calculate(int op1, int op2, char operator) {
switch (operator) {
case '+':
return op1 + op2;
case '-':
return op1 - op2;
case '*':
return op1 * op2;
case '/':
return op1 / op2;
case '%':
return op1 % op2;
}
if (operator == '^') {
int result = 1;
for (int i = 0; i < op2; i++) {
result *= op1;
}
return result;
}
return 0;
}
It looks like the expression
if (topPtr == NULL || topPtr->nextPtr == NULL)
is giving you an error because topPtr doesn't point to a valid node, nor it's null. So topPtr->nextPtr will give an error, due to the fact that topPtr is not a valid pointer.
According to your code, your head->nextPtr is not initialized to NULL, so this seems to be the cause of the problem.
By the way: Why do you initialize your head variable with an empty node? As far as I can see, you could just use head = NULL and it would work.
Last, but not least: you should free your node variable in the pop() function, in order to avoid a memory leak.
Hope it helps.
What does it mean by item=infix_exp[i++]; in the following C code? Line no 21. It is for infix to postfix conversion. As far as I know, here i is array index. But why is it incrementing without any loop?
This is the Code
#include<stdio.h>
#include<conio.h>
#define SIZE 100
int top = -1;
char stack[SIZE];
void push(char item);
char pop();
int is_operator(char symbol);
int precedence(char symbol);
void main()
{
int i;
int j;
char infix_exp[SIZE], postfix_exp[SIZE];
char item;
char x;
printf("\nEnter Infix expression in parentheses: \n");
gets(infix_exp);
i=0;
j=0;
item=infix_exp[i++]; /* HERE */
while(item != '\0')
{
if(item == '(')
{
push(item);
}
else if((item >= 'A' && item <= 'Z') ||
(item >= 'a' && item <= 'z'))
{
postfix_exp[j++] = item;
}
else if(is_operator(item) == 1)
{
x=pop();
while(is_operator(x) == 1 && precedence(x)
>= precedence(item))
{
postfix_exp[j++] = x;
x = pop();
}
push(x);
push(item);
}
else if(item == ')')
{
x = pop();
while(x != '(')
{
postfix_exp[j++] = x;
x = pop();
}
}
else
{
printf("\nInvalid Arithmetic Expression.\n");
getch();
}
item = infix_exp[i++];
}
postfix_exp[j++] = '\0';
printf("\nArithmetic expression in Postfix notation: ");
puts(postfix_exp);
getch();
}
void push(char item)
{
if(top >= SIZE-1)
{
printf("\nStack Overflow. Push not possible.\n");
}
else
{
top = top+1;
stack[top] = item;
}
}
char pop()
{
char item = NULL;
if(top <= -1)
{
printf("\nStack Underflow. Pop not possible.\n");
}
else
{
item = stack[top];
stack[top] = NULL;
top = top-1;
}
return(item);
}
int is_operator(char symbol)
{
if(symbol == '^' || symbol == '*' || symbol == '/' ||
symbol == '+' || symbol == '-')
{
return 1;
}
else
{
return 0;
}
}
int precedence(char symbol)
{
if(symbol == '^')
{
return(3);
}
else if(symbol == '*' || symbol == '/')
{
return(2);
}
else if(symbol == '+' || symbol == '-')
{
return(1);
}
else
{
return(0);
}
}
item=infix_exp[i++]; means to fetch ith element of the array to item, then increment i by 1.
It seems the line is there because the author of the code prefered to write item=infix_exp[i++]; twice (the another one is in line 59) to using while((item=infix_exp[i++]) != '\0').
item=infix_exp[i++]; is equivalent to
item=infix_exp[i];
i++;
except that latter has one more sequence point.
It is just the same as
item=infix_exp[i];
i = i + 1;
The statement where you are getting confused is
item=infix_exp[i++]
Before this line of statement if the value of i is 0 then in this line the value of i is also 0 but the value of i in the next line is 1.
This statement is not in loop but the value of i is used in a loop. Each time the loop iterates the value of i is increased by one. Besides, i++ has no relation with loop. If you want to make the effect of increment in the very next line then you can do so.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "stack.h"
#define MAX_EQU_LEN 100
static int prec(char operator)
{
switch (operator)
{
case '*':
return 5;
case '/':
return 4;
case '%':
return 3;
case '+':
return 2;
case '-':
return 1;
default:
break;
}
return 0;
}
static int isNumeric(char* num)
{
if(atoi(num) == 0)
{
return 0;
}
return 1;
}
char* infix_to_postfix(char* infix)
{
char* postfix = malloc(MAX_EQU_LEN);
stack* s = create_stack();
s->size = strlen(infix);
node* tempPtr = s->stack;
unsigned int i;
char symbol,next;
for(i = 0; i < s->size ; i++)
{
symbol = *((infix + i));
tempPtr = s->stack;
if(isNumeric(&symbol) != 1)
{
strcat(postfix, &symbol);
}
else if(symbol == '(')
{
push(s, symbol);
}
else if(symbol == ')')
{
while(s->size != 0 && top(s) != '(')
{
next = tempPtr->data;
pop(s);
strcat(postfix, &next);
tempPtr = s->stack;
if(tempPtr->data == '(')
{
pop(s);
}
}
}
else
{
while(s->size != 0 && prec(top(s)) > prec(symbol))
{
next = tempPtr->data;
pop(s);
strcat(postfix, &next);
push(s,next);
}
}
while(s->size != 0)
{
next = tempPtr->data;
pop(s);
strcat(postfix, &next);
}
}
return postfix;
}
int evaluate_postfix(char* postfix) {
//For each token in the string
int i,result;
int right, left;
char ch;
stack* s = create_stack();
node* tempPtr = s->stack;
for(i=0;postfix[i] < strlen(postfix); i++){
//if the token is numeric
ch = postfix[i];
if(isNumeric(&ch)){
//convert it to an integer and push it onto the stack
atoi(&ch);
push(s, ch);
}
else
{
pop(&s[i]);
pop(&s[i+1]);
//apply the operation:
//result = left op right
switch(ch)
{
case '+': push(&s[i],right + left);
break;
case '-': push(&s[i],right - left);
break;
case '*': push(&s[i],right * left);
break;
case '/': push(&s[i],right / left);
break;
}
}
}
tempPtr = s->stack;
//return the result from the stack
return(tempPtr->data);
}
This file is part of a program that uses a stack struct to perform an infix to postfix on an input file. The other functions have been tested and work fine but when I try to add this part and actually perform the operations the program segmentation faults. A debugger says it occurs in the infix_to_postfix function however it doesn't say which line and I can't figure out where. Does anyone know why this would seg fault?
You've done a few things wrong:
if(isNumeric(&symbol) != 1)
The function isNumeric() expects a null terminated string as input, not a pointer to a single character.
strcat(postfix, &symbol);
Here the same thing applies.
strcat(postfix, &next);
I'm guessing this is wrong too. If you want to turn a single character into a string, you can do this:
char temp[2] = {0};
temp[0] = symbol;
strcat(postfix, temp);
static int isNumeric(char* num)
{
if(atoi(num) == 0)
{
return 0;
}
return 1;
}
What if the string is "0"? Consider using strtol instead because it offers a more powerful means of testing the success of the outcome.
An unrelated stylistic note: your first function looks overcomplicated to me. Although it's perfectly possible that the way I'd do it is also overcomplicated.
static int prec(char operator)
{
switch (operator)
{
case '*':
return 5;
case '/':
return 4;
case '%':
return 3;
case '+':
return 2;
case '-':
return 1;
default:
break;
}
return 0;
}
If a function performs a simple mapping from one set to another, It could usually be performed more simply (and faster) as an array lookup. So I'd start with a string of the input characters.
char *operators = "*" "/" "%" "+" "-";
Note that the compiler will concatenate these to a single string value with a null-terminator.
int precedence[] = { 5, 4, 3, 2, 1, 0 };
Then testing whether a char is an operator is:
#include <string.h>
if (strchr(operators, chr))
...;
And getting the precedence becomes:
p = precedence[strchr(operators, chr) - operators];
If there are more values to associate with the operator, I'd consider using an X-Macro to generate a table and a set of associated enum values to use as symbolic indices.