Postfix Expression - Checking for Spaces - c

So I am trying to add an if statement in my main function to check if there is some whitespace. If so it would just go on to the next number/operator in line. So for example, if I would type 2 3 4 * +, I should get 14. However, when I run the code I would get a random number. When I do it with no spaces such as 234*+, then I would get 14. Could anyone tell me what I'm doing wrong and how I would fix this?
#include <ctype.h>
#include <stdio.h>
#define MAX 20
typedef struct stack {
int data[MAX];
int top;
} stack;
int evaluate(char x, int op1, int op2) {
if (x == '+')
return (op1 + op2);
if (x == '-')
return (op1 - op2);
if (x == '*')
return (op1 * op2);
if (x == '/')
return (op1 / op2);
if (x == '%')
return (op1 % op2);
}
void init(stack *s) {
s->top = -1;
}
void push(stack *s, int x) {
s->top = s->top + 1;
s->data[s->top] = x;
}
int pop(stack *s) {
int x;
x = s->data[s->top];
s->top = s->top - 1;
return (x);
}
int main() {
stack s;
char x;
int op1, op2, val;
init(&s);
printf("Enter a Postfix Expression: ");
while ((x = getchar()) != '\n') {
if (isdigit(x))
push(&s, x - 48); //x-48 for removing the effect of ASCII
if (isspace(x))
continue;
else {
op2 = pop(&s);
op1 = pop(&s);
val = evaluate(x, op1, op2);
push(&s, val);
}
}
val = pop(&s);
printf("\nValue of expression=%d",val);
return 0;
}

First of all, char x needs to be replaced with int x. The value returned by getchar won't always fit in a char. But that's not the problem you asked about.
If the character is a digit, you treat it as a digit and a operator. This
if(isdigit(x))
push(&s,x-48); //x-48 for removing the effect of ASCII
if (isspace(x))
continue;
else
{
op2=pop(&s);
op1=pop(&s);
val=evaluate(x,op1,op2);
push(&s,val);
}
should be
if (isdigit(x)) {
push(&s, x-48);
}
else if (isspace(x)) {
continue;
}
else {
int op2 = pop(&s);
int op1 = pop(&s);
int val = evaluate(x, op1, op2);
push(&s, val);
}
or just
if (isdigit(x)) {
push(&s, x-48);
}
else if (!isspace(x)) {
int op2 = pop(&s);
int op1 = pop(&s);
int val = evaluate(x, op1, op2);
push(&s, val);
}
You shouldn't count on a trailing line feed. So you should really have the following:
while ( ( x = getchar() ) != EOF ) {
if (isspace(x))
continue;
if (isdigit(x)) {
push(&s, x-48);
} else {
int op2 = pop(&s);
int op1 = pop(&s);
int val = evaluate(x, op1, op2);
push(&s, val);
}
}
Finally, you should handle someone entering 23++, 234+ or 23!.

Related

How can I put sin cos function into this RPN calculator

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#define MAXVAL 100
#define MAXOP 100
#define NUMBER '0'
#define BUFSIZE 100
#define sinn 'sin'
int sp = 0;
double val[MAXVAL];
char buf[BUFSIZE];
int bufp = 0;
double aatof(char []);
void push(double);
double pop(void);
int ggetop(char []);
int ggetch(void);
void unggetch(int);
int main()
{
int type;
double op2;
int op3;
char s[MAXOP];
while ((type = ggetop(s)) != EOF)
{
switch (type)
{
case NUMBER:
push(aatof(s));
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-': // negative number
if (isdigit(ggetop(s))){
push(0-aatof(s));
break;}
case '--': // minus
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2 != 0.0)
push(pop() / op2);
else
printf("error: zero divisor\n");
break;
case '%':
op3 = (int)pop();
if (op3 != 0)
push((int)pop() % op3);
else
printf("error: zero divisor\n");
break;
case 'sin':
push(sin(pop()));
break;
case '\n':
printf("\t%.8g\n", pop());
break;
default:
printf("error: unknown command %s\n", s);
break;
}
}
return 0;
}
int ggetop(char s[])
{
int i, c;
while ((s[0] = c = ggetch()) == ' ' || c == '\t')
;
s[1] = '\0';
if (!isdigit(c) && c != '.')
i = 0;
if (isdigit(c))
while (isdigit(s[++i] = c = ggetch()))
;
if (c == '.')
while (isdigit(s[++i] = c = ggetch()))
;
s[i] = '\0';
if (c != EOF)
unggetch(c);
return NUMBER;
}
int ggetch(void)
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void unggetch(int c)
{
if (bufp >= BUFSIZE)
printf("unggetch: too many characters\n");
else
buf[bufp++] = c;
}
double aatof(char s[])
{
double val, power;
int i, sign;
for (i = 0; isspace(s[i]); i++)
;
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '+' || s[i] == '-')
i++;
for (val = 0.0; isdigit(s[i]); i++)
val = 10.0 * val + (s[i] - '0');
if (s[i] == '.')
i++;
for (power = 1.0; isdigit(s[i]); i++)
{
val = 10.0 * val + (s[i] - '0');
power *= 10.0;
}
return sign * val / power;
}
void push(double f)
{
if (sp < MAXVAL)
val[sp++] = f;
else
printf("error: stack full, can't push %g\n", f);
}
double pop(void)
{
if (sp > 0)
return val[--sp];
else
{
printf("error: stack empty\n");
return 0.0;
}
}
I am not sure how can I put the sin cos pow function into different cases. I've tried to use isalpha() in ggetop(char s[]) and turn letters into integer but it doesn't seem to work. what I want to do is process the letter and give back the ASCII number, and add them into type. I wonder how to process the letters altogether at once and not individually.
if(isalpha(c)){
s[++i] = c = ggetch();
return c;}
are there other ways to add sin cos and pow functions into the programs?

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

Where to place printf to avoid multiple printouts in my rpn calculator?

My rpn-calculator works, but it has a problem. The problem is that it prints out every consecutive calculation that it makes along the way.
I have tried different ways of fixing this, the latest one being adding an integer that goes up by every calculation and a printf that prints if this integer is above 0 as well as there only being one number on the stack.
However, this causes problems when there is more than one calculation going on (for example writing 5 5 + 10 5 * *) will cause 10 500 being printed out because there is only one item on the stack after the first calculation.
How can I solve this?
#define MAX_STACK_SIZE 100
#define MAX_BUFFER_SIZE 100
char buff[MAX_BUFFER_SIZE];
double x, stack[MAX_STACK_SIZE];
double t;
int i, k=0, num_operand=0;
int main(void) {
while(x != 'q') {
if( scanf("%s", buff) < 1 )
{ return 0;
}
if(isdigit(buff[0]) || isdigit(buff[1])) {
sscanf(buff, "%lf", &x);
if (num_operand < MAX_STACK_SIZE)
{
stack[num_operand]=x;
num_operand ++;
} else { printf("Make stack bigger\n");}
} else {
switch(buff[0]) {
case '+': stack[num_operand - 2] = stack[num_operand - 1] + stack[num_operand - 2];
num_operand --;
num_operand --;
t = stack[num_operand];
k++;
num_operand ++;
break;
case '-': stack[num_operand - 2] = stack[num_operand - 2] - stack[num_operand - 1];
num_operand --;
num_operand --;
t = stack[num_operand];
k++;
num_operand ++;
break;
case '/': stack[num_operand - 2] = stack[num_operand - 2] / stack[num_operand - 1];
num_operand --;
num_operand --;
t = stack[num_operand];
k++;
num_operand ++;
break;
case '*': stack[num_operand - 2] = stack[num_operand - 1] * stack[num_operand - 2];
num_operand --;
num_operand --;
t = stack[num_operand];
k++;
num_operand ++;
break;
} }
if (num_operand == 1 && k !=0) {
k = 0;
printf("%lf \n", t); }
}
}
"%s" consumes leading white-spaces like ' ' and '\n' alike - so the distinction between end of line and the space separator is lost.
To distinguish between lines of input use fgets() and process the line. Then print the result. #molbdnilo
It test for q, code needs to test the textual contents of the line, not double x. #BLUEPIXY
int main(void) {
char line[MAX_BUFFER_SIZE];
// read line
while (fgets(line, sizeof line, stdin) && line[0] != 'q') {
// Set up these variables per each line.
double x, stack[MAX_STACK_SIZE];
double t;
int i, k = 0, num_operand = 0;
const char *p = line;
char buff[MAX_BUFFER_SIZE];
int n; // # of characters scanned
// process tokens
while (sscanf(p, "%s %n", buff, &n) == 1) {
...
// next token
p += n;
} // endwhile
// print
if (num_operand == 1 && k != 0) {
k = 0;
printf("%lf \n", t);
fflush(stdout);
}
} // endwhile
Instead of displaying by the number of stacked on the stack, make sure to display the stack top explicitly with the command.
Specific example.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <math.h>
#include <ctype.h>
#define MAX_STACK_SIZE 100
#define MAX_BUFFER_SIZE 100
char buff[MAX_BUFFER_SIZE];
char *curr_buff = buff;
double stack[MAX_STACK_SIZE];
int sp = -1;
#define prompt " ok>"
char *getToken(void);
bool IsNumber(const char *token, double *value);
char *strlwr(char *s);
int cmp_charpp(const void *, const void *);
void push(double value);
double pop(void);
void add(void);
void sub(void);
void mul(void);
void Div(void);
void dot(void);
void Exit(void);
void quit(void);
void bye(void);
void cr(void);
struct command {
const char *name;
void (*func)(void);
} op_table[] = {
{"*" , mul},
{"+" , add},
{"-" , sub},
{"." , dot},
{"/" , Div},
{"=" , dot},
{"add" , add},
{"bye" , bye},
{"cr" , cr},
{"div" , Div},
{"exit", Exit},
{"mul" , mul},
{"quit", quit},
{"sub" , sub},
};
int main(void) {
while(true){
char *token;
fputs(prompt, stdout);fflush(stdout);
while(token = getToken()){
double value = 0;
if(IsNumber(token, &value)){
push(value);
} else if(*token){
strlwr(token);
struct command *op =
bsearch(&token, op_table,
sizeof(op_table)/sizeof(*op_table), sizeof(*op_table),
cmp_charpp);
if(op){
op->func();
} else {
fprintf(stderr, "\ncommand '%s' not found!!\n", token);
curr_buff = buff;
*buff = 0;
break;
}
}
}
}
}
char *getToken(void){
static char token[MAX_BUFFER_SIZE] = "";
if(curr_buff){
if(*curr_buff || curr_buff == buff && (curr_buff = fgets(buff, sizeof buff, stdin))){
int n = 0;
if(sscanf(curr_buff, "%s %n", token, &n) == 1){
curr_buff += n;
return token;
}
}
*(curr_buff = buff) = 0;
}
return NULL;
}
bool IsNumber(const char *token, double *value){
char ch = 0;
*value = FP_NAN;
return sscanf(token, "%lf%c", value, &ch)==1;
}
void push(double value){
if(sp+1 == MAX_STACK_SIZE){
fprintf(stderr, "\nstack overflow!!\n");
return;
}
stack[++sp] = value;
}
bool IsEmpty(void){
return sp == -1;
}
double pop(void){
if(IsEmpty()){
fprintf(stderr, "\nstack is empty!!\n");
return nan(NULL);//FP_NAN;
}
return stack[sp--];
}
bool pop2(double *top, double *second){
return !isnan(*top = pop()) && !isnan(*second = pop());
}
void add(void){
double top, second;
if(pop2(&top, &second))
push(second+top);
}
void sub(void){
double top, second;
if(pop2(&top, &second))
push(second-top);
}
void mul(void){
double top, second;
if(pop2(&top, &second))
push(second*top);
}
void Div(void){
double top, second;
if(pop2(&top, &second))
push(second/top);
}
void dot(void){
double top = pop();
if(!isnan(top)){
printf("%g", top);fflush(stdout);
}
}
void cr(void){
putchar('\n');
}
void Exit(void){
double top = pop();
if(isnan(top))
exit(EXIT_FAILURE);
else
exit((int)top);
}
void quit(void){
char yn[4];
if(!IsEmpty()){
printf("The stack is not empty but will it end?\n");
scanf(" %3[NYny]", yn);
if(*yn == 'y' || *yn == 'Y')
exit(EXIT_SUCCESS);
else
while(getchar()!='\n');
}else {
exit(EXIT_SUCCESS);
}
}
void bye(void){
exit(EXIT_SUCCESS);
}
char *strlwr(char *s){
for(char *p = s; *p; ++p)
*p = tolower(*p);
return s;
}
int cmp_charpp(const void *a, const void *b){
return strcmp(*(const char **)a, *(const char **)b);
}
Example of execution.
ok>5 5 + 10 5 * * = CR
500
ok>bye

C stack implementation throws bad access error

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.

Going from infix to postfix

#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.

Resources