'C program data structure stack calculator [closed]
I'm studying about data structure coding. I built a calculator using a stack. infix to postfix and result However, I want to get the result after all completing the input. And I want to "out" the input with an end. the last line is example when it debug.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STACK_SIZE 100
#define MAX_EXPR_SIZE 100
enum {
lparen = -9,
rparen,
plus,
minus,
times,
divide,
mod,
eos,
operand
};
int stack[MAX_STACK_SIZE];
char expr[MAX_EXPR_SIZE], postexpr[MAX_EXPR_SIZE];
int pos = 0;
static int isp[] = { 0, 19, 12, 12, 13, 13, 13, 0 };
static int icp[] = { 20, 19, 12, 12, 13, 13, 13, 0 };
void add_stack(int *top, int item) {
if (*top >= MAX_STACK_SIZE - 1)
printf("Error: Stack is full\n");
stack[++*top] = item;
}
int delete_stack(int *top) {
if (*top == -1)
printf("Error: Stack is empty\n");
return stack[(*top)--];
}
int get_token(char *symbol, int *n) {
*symbol = expr[(*n)++];
switch (*symbol) {
case '(': return lparen;
case ')': return rparen;
case '+': return plus;
case '-': return minus;
case '*': return times;
case '/': return divide;
case '%': return mod;
case 0:
case '\n': return eos;
default: return operand;
}
}
void print_token(int p) {
switch (p) {
case plus:
printf("+");
postexpr[pos++] = '+';
break;
case minus:
printf("-");
postexpr[pos++] = '-';
break;
case times:
printf("*");
postexpr[pos++] = '*';
break;
case divide:
printf("/");
postexpr[pos++] = '/';
break;
case mod:
printf("%");
postexpr[pos++] = '%';
break;
case eos:
printf(" ");
break;
}
}
void postfix(void) {
char symbol;
int token;
int n = 0;
int top = 0;
stack[0] = eos;
token = get_token(&symbol, &n);
for(; token != eos; token = get_token(&symbol, &n)) {
if (token == operand) {
printf("%c", symbol);
postexpr[pos++] = symbol;
}
else if (token == rparen) {
while (stack[top] != lparen)
print_token(delete_stack(&top));
delete_stack(&top);
} else {
while (isp[stack[top] + 9] >= icp[token + 9])
print_token(delete_stack(&top));
add_stack(&top, token);
}
}
while ((token = delete_stack(&top)) != eos)
print_token(token);
printf("\n");
}
int eval(void) {
int token;
char symbol;
int op1, op2;
int n = 0;
int top = 0;
stack[0] = eos;
token = get_token(&symbol, &n);
for(; token != eos; token = get_token(&symbol, &n)) {
if (token == operand)
add_stack(&top, symbol - '0');
else {
op2 = delete_stack(&top);
op1 = delete_stack(&top);
switch (token) {
case plus: add_stack(&top, op1 + op2); break;
case minus: add_stack(&top, op1 - op2); break;
case times: add_stack(&top, op1 * op2); break;
case divide: add_stack(&top, op1 / op2); break;
case mod: add_stack(&top, op1 % op2); break;
}
}
}
return delete_stack(&top);
}
int main(void) {
printf("Input expression : ");
scanf("%s", expr);
printf("Postfix expression: ");
postfix();
strcpy(expr, postexpr);
printf("Evaluation of the expression : %d", eval());
}
this is example when it done
input //
(8*6)+2/4
(8*6)+4/2
out //
print//
postfix (8*6)+2/4
result (8*6)+2/4
postfix (8*6)+4/2
result (8*6)+4/2
//
Solution 1:[1]
Here are some problems and possible improvements to your code:
printf("%")has undefined behavior. You should writeprintf("%%")or simplyputchar('%')- you should parse numbers with multiple digits
- you should skip spaces and TABs
- you should detect invalid characters
- you should detect invalid expressions
- you should not use global variables
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STACK_SIZE 100
enum {
error = -10,
lparen = -9,
rparen,
plus,
minus,
times,
divide,
mod,
eos,
operand, /* 0 and above are operand values */
};
static int const isp[] = { 0, 19, 12, 12, 13, 13, 13, 0 };
void add_stack(int *stack, int *top, int item) {
if (*top >= MAX_STACK_SIZE - 1) {
printf("Error: Stack is full\n");
return;
}
stack[++*top] = item;
}
int delete_stack(int *stack, int *top) {
if (*top < 0) {
printf("Error: Stack is empty\n");
return eos;
}
return stack[(*top)--];
}
int get_token(const char *expr, int *pos) {
for (;;) {
int c = expr[*pos];
if (c == '\0' || c == '\n')
return eos;
*pos += 1;
if (c == ' ' || c == '\t')
continue;
if (c >= '0' && c <= '9') {
int value = c - '0';
while ((c = expr[*pos]) >= '0' && c <= '9') {
*pos += 1;
value = value * 10 + (c - '0');
}
return value;
}
switch (c) {
case '(': return lparen;
case ')': return rparen;
case '+': return plus;
case '-': return minus;
case '*': return times;
case '/': return divide;
case '%': return mod;
default: *pos -= 1; return error;
}
}
}
void print_token(char *postexpr, int *ppos, int token) {
int pos = *ppos;
switch (token) {
case error: postexpr[pos++] = '?'; break;
case lparen: postexpr[pos++] = '('; break;
case rparen: postexpr[pos++] = ')'; break;
case plus: postexpr[pos++] = '+'; break;
case minus: postexpr[pos++] = '-'; break;
case times: postexpr[pos++] = '*'; break;
case divide: postexpr[pos++] = '/'; break;
case mod: postexpr[pos++] = '%'; break;
case eos: break;
default:
/* insert a space between numbers */
if (pos > 0 && postexpr[pos - 1] >= '0' && postexpr[pos - 1] <= '9')
postexpr[pos++] = ' ';
pos += sprintf(postexpr + pos, "%d", token);
break;
}
*ppos = pos;
postexpr[pos] = '\0';
}
int put_error(const char *message, const char *expr, int col) {
if (col < 0) {
printf("%s\n", message);
} else {
printf("%s at column %d\n", message, col + 1);
printf("%s\n%*s\n", expr, col + 1, "^");
}
return -1;
}
int postfix(const char *expr, char *postexpr) {
int stack[MAX_STACK_SIZE];
int token, n = 0, top = 0, pos = 0, last = eos;
stack[0] = eos;
while ((token = get_token(expr, &n)) != eos) {
if (token == error) {
return put_error("syntax error", expr, n);
}
if (token >= operand) {
if (last >= operand) {
return put_error("missing operator", expr, n - 1);
}
print_token(postexpr, &pos, token);
} else
if (token == rparen) {
if (last < operand && last != rparen) {
return put_error("missing operand", expr, n - 1);
}
while (stack[top] != lparen) {
if (stack[top] == eos) {
return put_error("invalid parenthesis", expr, n - 1);
}
print_token(postexpr, &pos, delete_stack(stack, &top));
}
delete_stack(stack, &top);
} else {
if (token == lparen) {
if (last >= operand || last == rparen) {
return put_error("missing operator", expr, n - 1);
}
} else {
if (last < operand && last != rparen) {
return put_error("missing operand", expr, n - 1);
}
while (isp[stack[top] - lparen] >= isp[token - lparen]) {
print_token(postexpr, &pos, delete_stack(stack, &top));
}
}
add_stack(stack, &top, token);
}
last = token;
}
if (last < operand && last != rparen) {
return put_error("missing operand", expr, n);
}
while ((token = delete_stack(stack, &top)) != eos) {
if (token == lparen) {
return put_error("unmatched parenthesis", expr, -1);
}
print_token(postexpr, &pos, token);
}
return 0;
}
int eval(const char *expr) {
int stack[MAX_STACK_SIZE];
int token, n = 0, top = 0;
stack[0] = eos;
while ((token = get_token(expr, &n)) != eos) {
if (token >= operand) {
add_stack(stack, &top, token);
} else {
int op2 = delete_stack(stack, &top);
int op1 = delete_stack(stack, &top);
switch (token) {
case plus: add_stack(stack, &top, op1 + op2); break;
case minus: add_stack(stack, &top, op1 - op2); break;
case times: add_stack(stack, &top, op1 * op2); break;
case divide: add_stack(stack, &top, op1 / op2); break;
case mod: add_stack(stack, &top, op1 % op2); break;
}
}
}
return delete_stack(stack, &top);
}
int main() {
char expr[100], postexpr[200];
for (;;) {
printf("Input expression: ");
if (scanf("%99s", expr) != 1)
break;
if (!postfix(expr, postexpr)) {
printf("Postfix expression: %s\n", postexpr);
printf("Evaluation of the expression: %d\n", eval(postexpr));
}
}
printf("Done.\n");
return 0;
}
Sample run:
Input expression: 1
Postfix expression: 1
Evaluation of the expression: 1
Input expression: 1+
missing operand at column 3
1+
^
Input expression: 1+1
Postfix expression: 1 1+
Evaluation of the expression: 2
Input expression: (1+2*3)
Postfix expression: 1 2 3*+
Evaluation of the expression: 7
Input expression: (1+2*3)*(3+4*5/6)
Postfix expression: 1 2 3*+3 4 5*6/+*
Evaluation of the expression: 42
Input expression: Done.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
