C program data structure stack calculator [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 11 months ago.
Improve this question
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
//

Here are some problems and possible improvements to your code:
printf("%") has undefined behavior. You should write printf("%%") or simply putchar('%')
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.

Related

I am doing a mini project on stack applications, and get errors

The program:
evaluates postfix and prefix expressions
reverse a string
parenthesis balancing
decimal to binary conversion
infix to postfix conversion
There a some extra characters (emojis) appended in the output. I would like to fix that.
Also I have used two pop functions with int and char return type how can I reduce it to one single function.
extra characters in the output of decimal to binary conversion, also that one extra left parenthesis when printing "balanced parenthesis"
This a first year college project.
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20
int stack[MAX], opp1, opp2, top = -1;
struct stack
{
char stck[20];
int top;
}
s;
void push(int x)
{
top++;
stack[top] = x;
}
int pop()
{
char c;
c = stack[top];
top = top - 1;
printf("%c", c);
}
char pop1()
{
if (top == -1)
return -1;
else
return stack[top--];
}
void postfixeval()
{
char postfix[20];
int res, i;
gets(postfix);
for (i = 0; postfix[i] != '\0'; i++)
{
if (isdigit(postfix[i]))
{
push(postfix[i] - 48);
}
else
{
opp2 = pop();
opp1 = pop();
switch (postfix[i])
{
case '+':
push(opp1 + opp2);
break;
case '-':
push(opp1 - opp2);
break;
case '*':
push(opp1 *opp2);
break;
case '/':
push(opp1 / opp2);
break;
case '^':
res = pow(opp1, opp2);
break;
}
}
}
printf("result is %d \n", pop());
}
void prefixeval()
{
int len;
char prefix[20];
int res, i;
gets(prefix);
len = strlen(prefix);
for (i = len - 1; i >= 0; i--)
{
if (isdigit(prefix[i]))
{
push(prefix[i] - 48);
}
else
{
opp1 = pop();
opp2 = pop();
switch (prefix[i])
{
case '+':
push(opp1 + opp2);
break;
case '-':
push(opp1 - opp2);
break;
case '*':
push(opp1 *opp2);
break;
case '/':
push(opp1 / opp2);
break;
case '^':
res = pow(opp1, opp2);
push(res);
break;
}
}
}
printf("result is %d \n", pop());
}
int match(char a, char b)
{
if (a == '[' && b == ']')
return 1;
if (a == '{' && b == '}')
return 1;
if (a == '(' && b == ')')
return 1;
}
int check(char exp[])
{
int i;
char temp;
for (i = 0; i < strlen(exp); i++)
{
if (exp[i] == '(' || exp[i] == '{' || exp[i] == '[')
push(exp[i]);
if (exp[i] == ')' || exp[i] == '}' || exp[i] == ']')
if (top == -1)
{
return 0;
}
else
{
temp = pop();
if (!match(temp, exp[i]))
{
printf("Mismatched parentheses are : ");
printf("%c and %c\n", temp, exp[i]);
return 0;
}
}
}
if (top == -1)
{
printf("Balanced Parentheses\n");
return 1;
}
else
{
return 0;
}
}
void dectobin(int n)
{
while (n != 0)
{
push(n % 2);
n = n / 2;
}
while (top != -1)
{
printf("%d", pop());
}
}
int priority(char x)
{
if (x == '(')
return 0;
if (x == '+' || x == '-')
return 1;
if (x == '*' || x == '/')
return 2;
}
void intopost()
{
char exp[100];
char *e, x;
printf("Enter the expression : \n");
scanf("%s", exp);
printf("\n");
e = exp;
while (*e != '\0')
{
if (isalnum(*e))
printf("%c ", *e);
else if (*e == '(')
push(*e);
else if (*e == ')')
{
while ((x = pop1()) != '(')
printf("%c ", x);
}
else
{
while (priority(stack[top]) >= priority(*e))
printf("%c ", pop1());
push(*e);
}
e++;
}
while (top != -1)
{
printf("%c ", pop1());
}
}
int main()
{
int ch, i, len;
char postfix[20], prefix[20], str[30];
do {
printf("\n----STACK APPLICATIONS----\n");
printf("1.postfix expression evaluation\n2.prefix expression evaluation\n3.reverse a string\n4.paranthesis balancing\n5.decimal to binary\n6.infix to postfix\n7.exit\n");
printf("enter choice");
scanf("%d", &ch);
switch (ch)
{
case 1:
{
printf("enter postfix expression\n");
scanf("%c", &postfix);
postfixeval();
break;
}
case 2:
{
printf("enter prefix expression\n");
scanf("%c", prefix);
prefixeval();
break;
}
case 3:
{
printf("enter string\n");
scanf("%s", str);
len = strlen(str);
for (i = 0; i < len; i++)
{
push(str[i]);
}
printf("reversed string is:");
for (i = 0; i < len; i++)
{
pop();
}
break;
}
case 4:
{
char exp[20];
int valid;
printf("Enter an algebraic expression : \n");
scanf("%s", exp);
valid = check(exp);
if (valid == 1)
{
printf("Valid expression\n");
}
else
{
printf("Invalid expression\n");
}
break;
}
case 5:
{
int dec;
printf("enter decimal number\n");
scanf("%d", &dec);
dectobin(dec);
break;
}
case 6:
{
intopost();
break;
}
case 7:
{
exit(0);
}
default:
printf("invalid choice\n");
}
} while (ch != 7);
}
Here are the additional characters appended with the output
Here is one 'improvement' that you should learn about 'C'.
printf(
"1.postfix expression evaluation\n"
"2.prefix expression evaluation\n"
"3.reverse a string\n"
"4.paranthesis balancing\n"
"5.decimal to binary\n"
"6.infix to postfix\n"
"7.exit\n"
);
The compiler will 'join-up' those 'segments' (because there is no comma between a close quote and the next open quote.)
Once you have that, you can go back to basics and get this much displaying and functioning:
printf(
// "1.postfix expression evaluation\n"
// "2.prefix expression evaluation\n"
// "3.reverse a string\n"
// "4.paranthesis balancing\n"
// "5.decimal to binary\n"
// "6.infix to postfix\n"
"7.exit\n"
);
Don't try to run before you can walk...
To demonstrate 'incremental development' and 'learning/exploring':
// test.c - string segments in source code
#include <stdio.h>
int main() {
printf(
"Hello "
"World!\n"
);
return 0;
}

No output from the program

In our student class we are building a small program to process the data from Oil & Gas Industry. The program at a rough condition, but we learn a lot through the project.
The program is compiled this way
In the below sections you can find the whole code of the source files. Here is the compilation routine:
gcc -fPIC -c parser.c -o parser.o
gcc -shared parser.c -o parser.dll
gcc -c well.c - o well.o
gcc -c main.c -o main.o
gcc main.o well.o -L. -lparser -o well.exe
Then we execute it this way: well.exe "WELL_DATA.csv" "NUM OF WELL TO FIND" >> well.log
The problem the execution starts, but the output from fprintf appears just sometimes, but usually not... We hope you can help us resolve our problem
main.c file content
#include"well.h"
FILE* input;
struct WELL* head = NULL; //the head of the list
struct TNode* tree = NULL;
int main(int argc, char *argv[3]) {
CBUFFER* buffer = malloc(sizeof(CBUFFER));
buffer->len = BUFFER_SIZE;
input = fopen(argv[1], "r");
struct WELL* instance = NULL;
while(buffer->len != 0){
flushBuffer(buffer);
getNextLine(input, buffer);
if (buffer->len == 0)
break;
parseData(buffer);
instance = createWell(buffer);
addWell(instance, &head);
}
instance = getWell(argv[2], head);
if (instance != NULL)
fprintf(stdout,"NAME = %s\tLIFT_TYPE = %i\tMONTHLY_OIL_FLOW_RATE = %.2f\n", instance->name, instance->prodMethod, instance->oil.monthly);
else fprintf(stdout,"No such well\n");
freeList(head);
fclose(input);
return 0;
}
In the following sections you can find the rest of the code. Here is the parser.c which processes the data:
#include "parser.h"
unsigned short getNextLine(FILE* input, CBUFFER* buffer){
//printf("Getting next line\n");
unsigned short len = 0;
char symbol = fgetc(input);
if (!input || !buffer)
return 0;
while ((symbol != '\n' && (symbol != EOF))){
//
*((buffer->data) + len) = symbol;
symbol = fgetc(input);
len++;
}
*((buffer->data) + len) = '\n';
buffer->len = len;
buffer->index = 0;
return buffer->len;
}
unsigned short parseData(CBUFFER* buffer){
char *temp = malloc(sizeof(char) * (buffer->len + 1));
unsigned short i = 0;
unsigned short j = 0;
while (*((buffer->data) + i) != '\n'){
if (*((buffer->data) + i) == '\0' || *((buffer->data) + i) == '\r' || *((buffer->data) + i) == '\v' ||
*((buffer->data) + i) == '\t' || *((buffer->data) + i) == '\f')
i++;
else{
if (*((buffer->data) + i) == ';')
*(temp + j) = '\0';
else
*(temp + j) = *((buffer->data) + i);
j++;
}
i++;
}
*(temp + j) = '\n';
flushBuffer(buffer);
i = 0;
while (*(temp + i) != '\n'){
*((buffer->data) + i) = *(temp + i);
i++;
}
*((buffer->data) + i) = '\0';
free(temp);
buffer->len = i;
return buffer->len;
}
char* getValue(CBUFFER* buffer)
{
int i = buffer->index;
int j = buffer->index;
char c;
for (; i <= buffer->len; i++)
{
c = buffer->data[i];
if (c == '\0')
{
char* newValue = (char*)malloc(sizeof(char) * (i - buffer->index + 1));
for (; j <= i ; j++)
{
newValue[j - buffer->index] = buffer->data[j];
}
newValue[j - buffer->index] = '\0';
buffer->index = i + 1;
return newValue;
}
}
return NULL;
}
DATE getDate(char* input, char delimeter){
DATE date;
unsigned short number = 0;
char c = input[0];
for(unsigned short i = 1, j = 0; i < 12; i++){
number = number * 10 + atoi(&c);
c = input[i];
if((c == delimeter) || (c == '\0')){
if (j == 0) date.day = number;
if (j == 1) date.month = number;
if (j == 2){
date.year = number;
break;
}
number = 0;
j++;
}
}
return date;
}
int flushBuffer(CBUFFER* buffer) {
unsigned short i = 0;
while( i < buffer->len){
*((buffer->data)+i) = '\0';
i++;
}
buffer->len = 0;
return 0;
}
And the part which defines the well-object we work with well.c:
#include "well.h"
struct WELL* createWell(CBUFFER* pbuffer) {
struct WELL* instance = malloc(sizeof(struct WELL));
char * nextValue = getValue(pbuffer);
unsigned i = 0;
while ( nextValue != NULL){
setProperty(instance, i, nextValue);
i++;
nextValue = getValue(pbuffer);
}
instance->next = NULL;
return instance;
}
unsigned setProperty(struct WELL* instance, unsigned prop_index, char* value) {
switch(prop_index){
case 0:
setWellName(instance, value);
break;
case 1:
setWellDate(instance, getDate(value, '/'));
break;
case 2:
setProductionMethod(instance, value);
break;
case 3:
setFormation(instance, value);
break;
case 4:
setPump(instance, value);
break;
case 5:
setProduction(instance, OIL, MONTH, atof(value));
break;
case 6:
setProduction(instance, OIL, YEAR, atof(value));
break;
case 7:
setProduction(instance, OIL, COMMULATIVE, atof(value));
break;
case 8:
setProduction(instance, WATER, MONTH, atof(value));
break;
case 9:
setProduction(instance, WATER, YEAR, atof(value));
break;
case 10:
setProduction(instance, WATER, COMMULATIVE, atof(value));
break;
// PAY ATTENTION THAT cases from 11 to 13 are skipped!
// THIS IS BECAUSE WE DON'T NEED m3 PARAMETERS as it is
// AND CAN CALCULATE THEM from tons using density parameter
case 14:
setProduction(instance, MIX, MONTH, atof(value));
break;
case 15:
setProduction(instance, MIX, YEAR, atof(value));
break;
case 16:
setProduction(instance, MIX, COMMULATIVE, atof(value));
break;
case 17:
setProduction(instance, MIX, MONTH, atof(value));
break;
case 18:
setProduction(instance, MIX, YEAR, atof(value));
break;
case 19:
setProduction(instance, MIX, COMMULATIVE, atof(value));
break;
}
return 0;
}
unsigned addWell(struct WELL* instance, struct WELL** head) {
if (*head == NULL) {
*head = instance;
} else {
struct WELL* tmp = *head;
while (tmp->next){
tmp = tmp->next;
}
tmp->next = instance;
}
return 0;
}
struct WELL* getWell(char* key, struct WELL* head) {
if (head == NULL) return NULL;
struct WELL* currentWell = head;
while (strcmp(currentWell->name, key) != 0) {
if (currentWell->next == NULL) return NULL;
currentWell = currentWell->next;
}
return currentWell;
}
char* setWellName(struct WELL* instance, char* value) {
strcpy(instance->name, value);
return instance->name;
}
char* setFormation(struct WELL* instance, char* value) {
strcpy(instance->devFormation, value);
return instance->devFormation;
}
char* setPump(struct WELL* instance, char* value) {
strcpy(instance->pump, value);
return instance->pump;
}
DATE setWellDate(struct WELL* instance, DATE date) {
instance->startDate.day = date.day;
instance->startDate.month = date.month;
instance->startDate.year = date.year;
return instance->startDate;
}
WLIFT_TYPE setProductionMethod(struct WELL* instance, char* value) {
if (!strcmp(value, "flush"))
instance->prodMethod = FLUSH;
if (!strcmp(value, "gaslift"))
instance->prodMethod = GAS_LIFT;
if (!strcmp(value, "pump"))
instance->prodMethod = PUMP;
return instance->prodMethod;
}
double setProduction(struct WELL* instance, WFLUID fluid, WPERIOD period , double value) {
if (fluid == OIL) {
if (period == MONTH) {
instance->oil.monthly = value;
return instance->oil.monthly;
} else if (period == YEAR) {
instance->oil.year = value;
return instance->oil.year;
} else if (period == COMMULATIVE) {
instance->oil.commulative = value;
return instance->oil.commulative;
}
} else if (fluid == GAS) {
if (period == MONTH) {
instance->gas.monthly = value;
return instance->gas.monthly;
} else if (period == YEAR) {
instance->gas.year = value;
return instance->gas.year;
} else if (period == COMMULATIVE) {
instance->gas.commulative = value;
return instance->gas.commulative;
}
} else if (fluid == WATER) {
if (period == MONTH) {
instance->water.monthly = value;
return instance->water.monthly;
} else if (period == YEAR) {
instance->water.year = value;
return instance->water.year;
} else if (period == COMMULATIVE) {
instance->water.commulative = value;
return instance->water.commulative;
}
} else if (fluid == MIX) {
if (period == MONTH) {
instance->liquid.monthly = value;
return instance->liquid.monthly;
} else if (period == YEAR) {
instance->liquid.year = value;
return instance->liquid.year;
} else if (period == COMMULATIVE) {
instance->liquid.commulative = value;
return instance->liquid.commulative;
}
}
}

Wrong answer from a program (infix notation->postfix notation) in C

I made a program which changes infix notation to postfix notation with using stack in C.
I made a function which prints the result of the postfix notation(from infix notaton).
But, the result of a notation is wrong. This should be '195' but its result is '-61'.
The results of the other notations are right but only the notation(op2) has this problem.
What should I do to fix this problem?
This is my code:
typedef char element;
typedef struct {
element stack[MAX_STACK_SIZE];
int top;
} StackType;
void init(StackType *s) {
s->top = -1;
}
int is_empty(StackType *s) {
return (s->top == -1);
}
int is_full(StackType *s) {
return (s->top == (MAX_STACK_SIZE - 1));
}
void push(StackType *s, element item) {
if (is_full(s)) {
fprintf(stderr, "FULL STACK ERROR\n");
return;
}
else s->stack[++(s->top)] = item;
}
element pop(StackType *s) {
if (is_empty(s)) {
fprintf(stderr, "EMPTY STACK ERROR\n");
exit(1);
}
else return s->stack[(s->top)--];
}
int eval(char exp[]) {
int op1, op2, value, i = 0;
int len = strlen(exp);
char ch;
StackType s;
init(&s);
for (i = 0; i < len; i++) {
ch = exp[i];
if (ch != '+' && ch != '-' && ch != '*' && ch != '/') {
value = ch - '0';
push(&s, value);
}
else {
op2 = pop(&s);
op1 = pop(&s);
switch (ch) {
case '+': push(&s, op1 + op2); break;
case '-': push(&s, op1 - op2); break;
case '*': push(&s, op1 * op2); break;
case '/': push(&s, op1 / op2); break;
}
}
}
return pop(&s);
}
char* infix_to_postfix(char exp[]) {
int i = 0, j = 0;
char ch, top_op;
int len = strlen(exp);
char *ex = (char *)malloc(sizeof(char)*(len + 1));
StackType s;
init(&s);
for (i = 0; i < len; i++) {
ch = exp[i];
switch (ch) {
case '+': case '-': case '*': case '/':
while (!is_empty(&s) && (prec(ch) <= prec(peek(&s)))) {
ex[j++] = pop(&s);
}
push(&s, ch);
break;
case '(':
push(&s, ch);
break;
case ')':
top_op = pop(&s);
while (top_op != '(') {
ex[j++] = top_op;
top_op = pop(&s);
}
break;
default:
ex[j++] = ch;
break;
}
}
while (!is_empty(&s)) {
ex[j++] = pop(&s);
}
ex[j] = NULL;
return ex;
}
void main() {
char *op1 = "(9-(3+2))*3+4*((4+2)/3)-1";
char *op2 = "(4*5-3)/3+((2+5*7)-8+9)*5";
char *op3 = "7*3-7-4+1/3+6-8*2";
char *pos1, *pos2, *pos3;
pos1 = infix_to_postfix(op1);
pos2 = infix_to_postfix(op2);
pos3 = infix_to_postfix(op3);
printf(" Result : %d\n", eval(pos1));
printf(" Result : %d\n", eval(pos2));
printf(" Result : %d\n", eval(pos3));
}
[RESULT]
Result : 19
Result : -61 // This should be '195'.
Result : 0
The clue is 61+195 = 256. Which means that somewhere, your computations are being saved to chars. Looks like it is element.
typedef element int;

Using a stack to do an 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;
char temp[2] = {0};
for(i = 0; i < s->size ; i++)
{
symbol = *((infix + i));
temp[0] = symbol;
tempPtr = s->stack;
if(isNumeric(temp) != 1)
{
strcat(postfix, temp);
}
else if(symbol == '(')
{
push(s, symbol);
}
else if(symbol == ')')
{
while(s->size != 0 && top(s) != '(')
{
next = tempPtr->data;
temp[0] = next;
pop(s);
strcat(postfix, temp);
tempPtr = s->stack;
if(tempPtr->data == '(')
{
pop(s);
}
}
}
else
{
while(s->size != 0 && prec(top(s)) > prec(symbol))
{
next = tempPtr->data;
temp[0] = next;
pop(s);
strcat(postfix,temp);
push(s,next);
}
}
while(s->size != 0)
{
next = tempPtr->data;
temp[0] = next;
pop(s);
strcat(postfix, temp);
}
}
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; 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[0]);
pop(&s[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 code is part of a bigger program that is designed to convert simple math from infix to postfix and then evaluate it. This will be aided by a stack to hold the numbers and symbols. However when I run the program it seg faults and all the debugger says is that it is in the infix_to_postfix function and I cannot figure out what part of the code makes it seg fault.

Line in text file is evaluated multiple times?

I need to convert infix to postfix and evaluate postfix expression. When reading from a file, I should be able to evaluate multiple expressions at once. But when I run it and it encounters an expression that is not well-formed in the sense that there are more closed parentheses than open ones, it evaluates that expression 2 or 3 times.
Code:
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define MAX 1000
typedef struct stack
{
int data[MAX];
int top;
} stack;
int priority(char);
void init(stack*);
int empty(stack*);
int full(stack*);
char pop(stack*);
void push(stack*, char);
char top(stack*);
void add(char*, char, int);
void keyboard();
void read_file();
int change(char);
void pushYO(double);
double popYO();
stack s;
char x;
int i, token, topYO = -1;
double result[MAX];
char filepath[MAX];
int main()
{
char choice;
init(&s);
system("CLS");
printf("[1] Keyboard \n[2] Read from text file \n[3] Exit \n");
scanf("%c", &choice);
if(choice != '1' && choice != '2' && choice != '3')
{
main();
}
else if(choice == '1')
{
keyboard();
}
else if(choice == '2')
{
read_file();
}
else if(choice == '3')
{
printf("\nThank you for using Kei Shirabe's \ninfix to postfix converter and evaluator! :)\n");
exit(0);
}
}
void keyboard() //the keyboard input version. this works fine
{
//code here
}
void read_file()
{
int z, count, form, paren;
double one, two, three = 1;
char infx[MAX];
char pofx[MAX];
char choice;
FILE *text = fopen("text.txt", "a");
printf("Enter path of file:");
scanf("%s",&filepath);
FILE *textYO = fopen(filepath, "r");
if((textYO) == NULL)
{
printf("\nError! Unable to open %s\n\n", filepath);
}
else
{
while((fgets(infx, MAX, textYO))!= NULL)
{
form = -1, paren = 0, count = 0, z = 0;
infx[
strlen(infx)-1] = '\0';
for (i=0; i<strlen(infx); i++)
{
if((token = infx[i]) != '\n')
{
if(isalnum(token))
{
form++;
}
else
{
if(token == '(')
{
paren++;
}
else if(token == ')')
{
paren--;
}
else
{
form--;
}
}
if (paren < 0)
{
printf("%s", infx);
fprintf(text, "%s", infx);
printf("\n\nError! Not well formed :( \n-----------------\n");
fprintf(text, "\n\nError! Not well formed :( \n-----------------\n");
}
else
if(isalnum(token))
{
add(pofx, token, count);
count++;
}
else
if(token == '(')
{
push(&s, '(');
}
else
{
if(token == ')')
while((x = pop(&s)) != '(')
{
add(pofx, x, count);
count++;
}
else
if(token == '^')
{
push(&s, token);
}
else
{
while(priority(token) <= priority(top(&s)) && !empty(&s))
{
x = pop(&s);
add(pofx, x, count);
count++;
}
push(&s, token);
}
}
}
else
{
while(!empty(&s))
{
x = pop(&s);
add(pofx, x, count);
count++;
}
}
}
if(form != 0 || paren != 0)
{
printf("%s", infx);
fprintf(text, "%s", infx);
printf("\n\nError! Not well formed :( \n-----------------\n");
fprintf(text, "\n\nError! Not well formed :( \n-----------------\n");
}
else
{
form = -1, paren = 0;
printf("%s", infx);
fprintf(text, "%s", infx);
printf("\n\nPostfix: %s \n\n", pofx);
fprintf(text, "\n\nPostfix: %s\n\n", pofx);
while((token = pofx[z++]) != '\0')
{
three = 1;
if(!isdigit(token) && !isalpha(token))
{
two = popYO();
one = popYO();
switch(token)
{
case '+':
pushYO(one+two); break;
case '-':
pushYO(one-two); break;
case '*':
pushYO(one*two); break;
case '/':
pushYO(one/two); break;
case '^':
if (two > 0)
{
for(i=0;i<two;i++)
{
three = three * one;
}
pushYO(three);
three = 1; break;
}
else
{
for(i=0;i<(two-(2*two));i++)
{
three = three * one;
}
pushYO((1/three));
three = 1; break;
}
}
}
else if(isalpha(token))
{
if(isupper(token))
{
pushYO(token - '#');
}
if(islower(token))
{
pushYO(token - change(token));
}
}
else
{
pushYO(token - '0');
}
}
printf("Result: %lf\n-----------------\n", result[topYO]);
fprintf(text, "Result: %lf\n-----------------\n", result[topYO]);
}
}
}
fclose(text);
fclose(textYO);
printf("\nRun again? \n[1] Yes \n[any other key] No\n");
scanf("%c", &choice);
scanf("%c", &choice);
if(choice == '1')
{
main();
}
else
{
printf("\nThank you for using Kei Shirabe's \ninfix to postfix converter and evaluator! :)\n");
exit(0);
}
}
//other functions down here, not important
Sample text file (and yes there is an extra space at the end):
(1+2))
(1+2*3)
For this text file, the expression (1+2)) is evaluated three times, each result being "Not well formed". The last expression works as expected.
Any help please?

Resources