I have to make a code that takes in an expression in infix notation, and outputs the correct answer.
The sample input is like this:
3
2.8982 + 4.8674 - 5.5170 - 1.4080 + 3.6204 - 3.8340 - 5.9121
1.8752 ^ 3.7947 ^ 3.9259 / 5.0828 ^ 2.3765 ^ 1.6631
3.8120 / 5.3817 * 5.0096 * 1.0598 / 3.7128 + 5.8597 / 4.3995 ^ 5.1891 - 3.0547 / 2.5795
The first input is an integer that says how many expressions will follow.
To solve this, I created a function result() which takes in a string that contains the expression. This function works but only for the first iteration of the loop.
From this error, I suspect that there's something off with how I take the input, so I placed a print statement in my main function to see if I get the correct input from STDIN:
int main(void) {
int num; //get num of expressions
scanf("%d", &num);
getchar(); //get newline
char exp[MAX];
//gets the whole string of input
for(int a = 0; a < num; a++) {
fgets(exp, MAX, stdin);
exp[strlen(exp)-1] = 0;
printf("STDIN: %s\n", exp);
//double ans = result(exp);
memset(exp, 0, MAX);
//printf("%0.4lf\n\n", ans);
}
}
This is my output:
STDIN: 2.8982 + 4.8674 - 5.5170 - 1.4080 + 3.6204 - 3.8340 - 5.9121
STDIN: 1.8752 ^ 3.7947 ^ 3.9259 / 5.0828 ^ 2.3765 ^ 1.6631
STDIN: 3.8120 / 5.3817 * 5.0096 * 1.0598 / 3.7128 + 5.8597 / 4.3995 ^ 5.1891 - 3.0547 / 2.5795
So, from here, I know that STDIN does get the correct input. Next, in my result function, I placed a print statement that checks the value of the string that is inputted into the function. Now, if I un-comment the line in main that calls the function result, and put in the same input, I get a different output.
STDIN: 2.8982 + 4.8674 - 5.5170 - 1.4080 + 3.6204 - 3.8340 - 5.9121
FUNCTION: 2.8982 + 4.8674 - 5.5170 - 1.4080 + 3.6204 - 3.8340 - 5.9121
STDIN: 947 ^ 3.9259 / 5.0828 ^ 2.3765 ^ 1.6631
FUNCTION: 947 ^ 3.9259 / 5.0828 ^ 2.3765 ^ 1.6631
STDIN: 5.3817 * 5.0096 * 1.0598 / 3.7128 + 5.8597 / 4.3995 ^ 5.1891 - 3.0547 / 2.5795
FUNCTION: 5.3817 * 5.0096 * 1.0598 / 3.7128 + 5.8597 / 4.3995 ^ 5.1891 - 3.0547 / 2.5795
Why does this happen? This error also happens even if I remove the print statement in the function. It happens as long as I call the function result()
Input from STDIN when I called the function:
STDIN: 2.8982 + 4.8674 - 5.5170 - 1.4080 + 3.6204 - 3.8340 - 5.9121
STDIN: 947 ^ 3.9259 / 5.0828 ^ 2.3765 ^ 1.6631
STDIN: 5.3817 * 5.0096 * 1.0598 / 3.7128 + 5.8597 / 4.3995 ^ 5.1891 - 3.0547 / 2.5795
I suspect it has something to do with whitespace, but I can't figure out where that error would occur? I've taken care of getting the newline already?
Full Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#define MAX 100000
struct Stack {
int data[MAX];
int top;
};
typedef struct Stack Stack;
double numbers[MAX]; //stack for numbers
int numTop;
void Initialize(Stack *S) {
S->top = -1;
memset(S->data, 0, MAX);
}
void initNumbers() {
numTop = -1;
memset(numbers, 0, MAX);
}
char peek(Stack *S) {
return S->data[S->top];
}
void push(Stack *S, char c) {
S->top++;
S->data[S->top] = c;
}
char pop(Stack *S) {
char value = S->data[S->top];
S->top--;
return value;
}
int isEmpty(Stack *S) {
if(S->top == -1) {
return 1; //empty
} else {
return 0;
}
}
int isDigit(char c) {
if(c >= '0' && c <= '9' || c == '.') {
return 1;
} else {
return 0;
}
}
int isOperation(char c) {
if(c == '+' || c == '-' || c == '*' || c == '/' || c == '^') {
return 1;
} else {
return 0;
}
}
double ConvertTodouble(char exp[], int a, int size) {
char temp[MAX];
memset(temp, 0, MAX);
for(int i = 0; i < size; i++) {
temp[i] = exp[a];
a++;
}
return atof(temp);
}
void pushNum(double num) { //for num array
numTop++;
numbers[numTop] = num;
}
double popNum() {
double result = numbers[numTop];
numTop--;
return result;
}
double evaluate(double a, double b, char op) {
if(op == '+') {
return a + b;
} else if(op == '-') {
return a - b;
} else if(op == '*') {
return a * b;
} else if(op == '/') {
return a / b;
} else if(op == '^') {
return pow(a, b);
}
}
int weight(char c) {
switch(c) {
case '+':
case '-': return 1;
break;
case '*':
case '/': return 2;
break;
case '^': return 3;
break;
}
}
//if isp > icp, pop (returns 1)
//this returns 1 if isp > icp (left associative)
//returns 1, we pop
int higherPrecedence(char instack, char incoming) {
int isp = weight(instack);
int icp = weight(incoming);
if((isp == icp) && instack == '^') {
return 0;
} else if((isp == icp) && instack != '^') {
return 1;
}
if(isp > icp) {
return 1;
} else {
return 0;
}
}
double result(char exp[]) {
Stack S; //stack for operations (+,-,*,/,^)
double ans = 0;
Initialize(&S);
initNumbers();
int len = strlen(exp);
int flag = 0;
for(int i = 0; i < len; i++) {
if(exp[i] == ' ') {
getchar();
} else if(isDigit(exp[i])) {
//gets number from char array and converts to double
flag = i; //flag determines how many spaces to move pointer later
for(int a = i; a < len; a++) {
if(exp[a] == ' ') {
break;
} else {
flag++;
}
}
int size = flag - i;
double number = ConvertTodouble(exp, i, size);
pushNum(number);
i = flag - 1; //update the index so we won't repeat operation
} else if (exp[i] == '(') {
push(&S, '(');
} else if(isOperation(exp[i])) {
while(!isEmpty(&S) && peek(&S) != '(' && higherPrecedence(peek(&S), exp[i])) {
char op = pop(&S);
double b = popNum();
double a = popNum();
ans = evaluate(a,b,op);
pushNum(ans);
}
push(&S, exp[i]);
} else if(exp[i] == ')') {
while(!isEmpty(&S) && peek(&S) != '(') {
char op = pop(&S);
double b = popNum();
double a = popNum();
ans = evaluate(a,b,op);
pushNum(ans);
}
char throw = pop(&S); //this gets the '('
}
}
while(!isEmpty(&S)) {
char op = pop(&S);
double b = popNum();
double a = popNum();
ans = evaluate(a,b,op);
pushNum(ans);
if(numTop == 0) {
break;
}
}
return ans;
}
int main(void) {
int num; //get num of expressions
scanf("%d", &num);
getchar(); //get newline
char exp[MAX];
//gets the whole string of input
for(int a = 0; a < num; a++) {
printf("Before: %s\n", exp);
fgets(exp, MAX, stdin);
exp[strlen(exp)-1] = 0;
printf("STDIN: %s\n", exp);
double ans = result(exp);
memset(exp, 0, MAX);
//printf("%0.4lf\n\n", ans);
}
}
Well I guess I found the bug.
You can see what happened here
1.8752 ^ 3.7947 ^ 3.9259 / 5.0828 ^ 2.3765 ^ 1.6631
^
|
you got it from here.
12 charcaters got missing.
Check the previous line
2.8982 + 4.8674 - 5.5170 - 1.4080 + 3.6204 - 3.8340 - 5.9121
x x x x x x x x x x x x
There are 12 spaces.
So this is what causes the error.
for(int i = 0; i < len; i++) {
if(exp[i] == ' ') {
getchar();
Change the logic of your code. Hope this helps.