Calculator Program using stack - c

I am writing a calculator program in c using stack, In below program I used concept of infix to postfix conversion and next postfix evaluation.
I am getting correct answer for 1+2 answer is 3 but for 11+1 or any two and more digit i am getting wrong answer.
Can anyone help me what I will include in my code so that it work for more than two digit like 28+25 or any?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define SIZE 50 /* Size of Stack */
int top = -1;
char pofx[50];
char s[SIZE];
int infix_to_postfix() {
char infx[50], ch;
int i = 0, k = 0;
void push(char elem) { /* Function for PUSH operation */
s[++top] = elem;
}
char pop() { /* Function for POP operation */
return (s[top--]);
}
int pr(char elem) { /* Function for precedence */
switch (elem) {
case '#':
return 0;
case '(':
return 1;
case '+':
case '-':
return 2;
case '*':
case '/':
return 3;
}
return -1;
}
printf("\n\nEnter a Value to calculate : ");
gets(infx);
push('#');
while ((ch = infx[i++]) != '\0') {
if (ch == '(') push(ch);
else if (isalnum(ch)) pofx[k++] = ch;
else if (ch == ')') {
while (s[top] != '(')
pofx[k++] = pop();
char elem = pop(); /* Remove ( */
} else { /* Operator */
while (pr(s[top]) >= pr(ch))
pofx[k++] = pop();
push(ch);
}
}
while (s[top] != '#') /* Pop from stack till empty */
pofx[k++] = pop();
pofx[k] = '\0'; /* Make pofx as valid string */
printf("\n\nGiven Infix Expn: %s Postfix Expn: %s\n", infx, pofx);
return (int) pofx[k];
}
void postfix_evaluate() {
char ch;
int i = 0, op1, op2;
void pushit(int elem) { /* Function for PUSH operation */
s[++top] = elem;
}
int popit() { /* Function for POP operation */
return (s[top--]);
}
infix_to_postfix();
while ((ch = pofx[i++]) != '\0') {
if (isdigit(ch)) pushit(ch - '0'); /* Push the operand */
else { /* Operator,pop two operands */
op2 = popit();
op1 = popit();
switch (ch) {
case '+':
pushit(op1 + op2);
break;
case '-':
pushit(op1 - op2);
break;
case '*':
pushit(op1 * op2);
break;
case '/':
pushit(op1 / op2);
break;
}
}
}
printf("\n Given Postfix Expn: %s\n", pofx);
printf("\n Result after Evaluation: %d\n", s[top]);
}
int main() {
postfix_evaluate();
return 0;
}

part of my own code that might be useful:
if (isdigit(gi.n.nch))
{
gi.x = chr2num(gi.n.nch);
gi.n= nextchar( gi.n, len, instr);
while(isdigit(gi.n.nch))
{
gi.x *= 10;
gi.x += chr2num(gi.n.nch);
gi.n= nextchar( gi.n, len, instr);
}
}

Related

Code not fully generating a post fix expression

I was hoping to get a bit of help, my program is supposed to take a prefix expression and generate the post fix in order. for example the expression 234*+ should generate 23+4
I am getting: Enter postfix expression: 234+
Infix expression: (3*)(2+)
I think I am on the right track just not sure what I did wrong, Thank you in advance
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define MAX_SIZE 100
typedef struct stack {
char data[MAX_SIZE];
int top;
} Stack;
void push(Stack *s, char x) {
if (s->top == MAX_SIZE - 1) {
printf("Stack overflow\n");
return;
}
s->top++;
s->data[s->top] = x;
}
char pop(Stack *s) {
if (s->top == -1) {
printf("Stack underflow\n");
return '\0';
}
char x = s->data[s->top];
s->top--;
return x;
}
int isOperator(char x) {
switch (x) {
case '+':
case '-':
case '/':
case '*':
return 1;
}
return 0;
}
int main() {
char postfix[MAX_SIZE];
char infix[MAX_SIZE];
printf("Enter postfix expression: ");
scanf("%s", postfix);
Stack s;
s.top = -1;
int i = 0;
while (postfix[i] != '\0') {
if (isOperator(postfix[i])) {
char op1 = pop(&s);
char op2 = pop(&s);
char temp[5];
temp[0] = '(';
temp[1] = op2;
temp[2] = postfix[i];
temp[3] = ')';
temp[4] = '\0';
strcat(infix, temp);
push(&s, op1);
} else {
push(&s, postfix[i]);
}
i++;
}
printf("Infix expression: %s\n", infix);
return 0;
}
I have been trying with a simple expression as stated above but not too sure what is messed up

Printing the wrong value when evaluating postfix expressions

I wrote a program which is used to evaluate postfix expression, I am not getting any compiler error/warnings but I am not getting the correct output, which probably means the issue is with the calculation but I don't know where.
My Code:
#include <ctype.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAX 20
char s[MAX], top = 0;
void main() {
char postfix[MAX], ch;
int i, op1, op2, res;
clrscr();
printf("\n\t\t program to evaluate postfix expression");
printf("\n\t\t.......");
printf("\n enter the postfix expression:\n");
scanf("%s", &postfix);
for (i = 0; i < strlen(postfix); i++) {
ch = postfix[i];
if (isdigit(ch))
push(ch = '0');
else {
op2 = pop();
op1 = pop();
switch (ch) {
case '+':
res = op1 + op2;
break;
case '-':
res = op1 - op2;
break;
case '*':
res = op1 * op2;
break;
case '/':
res = op1 / op2;
break;
case '^':
res = pow(op1, op2);
break;
default:
printf("invalid choice");
}
push(res);
}
}
printf("result of above expression is:%d\n", pop());
getch();
}
push(int element) {
++top;
s[top] = element;
}
int pop() {
int element;
element = s[top];
--top;
return (element);
}
You should fix the typo and change push(ch = '0'); to
push(ch - '0');
ch is a character, isdigit(ch), or better isdigit((unsigned char)ch) tells you it is a digit, ch - '0'is the digit value, a number in the range0to9`.
Your code ch = '0' stores the digit '0' into ch and pushes this value, which is the character code or 0 on your system, 48 in ASCII.

How do I ignore spaces in a string input?

I am creating a program that evaluates a postfix expression contained in a single line of a text file. I'm having some trouble dealing with blank spaces in the scanned file. What I've done so far is scan the single line from the file into a buffer, and then process the string one character at a time. How do I ignore blank spaces once I've read the line into a string? For example:
2 4 3 * +
Here is the full program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
int stack[1000];
int top = -1;
void push(int x);
int pop();
bool isOperator(char ch);
int performOperation(int op1, int op2, char op);
int main()
{
char exp[1000], buffer[15];
int i, num, op1, op2, len, j, x;
int stack[1000];
char fileName[20];
FILE *inFile;
char *e;
printf("Please enter text file:");
scanf("%s", fileName);
inFile = fopen(fileName, "r");
if (inFile == NULL) {
printf("Error\n");
return -1;
}
int N = 0; i = 0, temp;
while (!feof(inFile)) {
fgets(buffer, 15, inFile);
N++;
}
printf("Postfix expression:\n");
printf("%s", buffer);
e = buffer;
while (*e != '\0') {
if (isdigit(*e)) {
num = *e - 48;
push(num);
} else {
op1 = pop();
op2 = pop();
if (isOperator(*e)) {
int ans;
ans = performOperation(op1, op2, *e);
}
push(ans);
}
e++;
}
printf(" The value of the expression is %d\n", ans);
}
void push(int x)
{
stack[++top] = x;
}
int pop()
{
return stack[top--];
}
bool isOperator(char ch) {
if (ch == '+' || ch == '-' || ch == '*'|| ch == '/')
return true;
else
return false;
}
int performOperation(int op1, int op2, char op) {
int ans;
switch (op) {
case '+':
ans = op2 + op1;
break;
case '-':
ans = op2 - op1;
break;
case '*':
ans = op2 * op1;
break;
case '/':
ans = op2 / op1;
break;
}
return ans;
}
Any help is appreciated.
I forgot to mention that we are only dealing with single-digit numbers.
You can remove the spaces so you don't have to deal with them
void remove_spaces(char* s) {
const char* d = s;
do {
while (*d == ' ') {
++d;
}
} while (*s++ = *d++);
}
If I have understood correctly the problem is processing embedded white spaces.
To resolve the problem you can rewrite the while loop at least the following way
int ans = 0;
for ( e = buffer; *e != '\0'; ++e ) {
if ( !isspace( ( unsigned char )*e ) )
{
if ( isdigit( ( unsigned char )*e ) ) {
num = *e - '0';
push(num);
} else if ( isOperator(*e) ) {
op1 = pop();
op2 = pop();
ans = performOperation(op1, op2, *e);
push(ans);
}
}
}
ans = pop();
printf(" The value of the expression is %d\n", ans);
Pay attention to this statement before the printf call
ans = pop();
You have to pop the answer from the stack before printing it. Also you should process invalid characters and check whether the stack is empty.
Also this loop
int N = 0; i = 0, temp;
while (!feof(inFile)) {
fgets(buffer, 15, inFile);
N++;
}
seams does not make sense and the condition of the loop is incorrect. For example for an empty file the variable buffer will not contain a valid data.
There are multiple problems in your code:
The loop while (!feof(inFile)) is incorrect. You should instead use:
while (fgets(buffer, sizeof buffer, inFile)) {
/* handle the string expression in buffer */
you should not push the number immediately when encountering a digit, you should parse the number that may have more than one digit.
once you parse numbers correctly, you can discard any white space encountered in the parser.
Here is a modified version:
#include <stdio.h>
bool isOperator(char ch) {
if (ch == '+' || ch == '-' || ch == '*'|| ch == '/')
return true;
else
return false;
}
int performOperation(int op1, int op2, char op) {
int ans;
switch(op) {
case '+':
ans = op2 + op1;
break;
case '-':
ans = op2 - op1;
break;
case '*':
ans = op2 * op1;
break;
case '/':
ans = op2 / op1;
break;
}
return ans;
}
int main() {
char fileName[100];
char buffer[100];
FILE *inFile;
printf("Please enter text file:");
if (scanf("%99s", fileName) != 1) {
printf("No input\n");
return 1;
}
inFile = fopen(fileName, "r");
if (inFile == NULL) {
printf("Error\n");
return -1;
}
while (fgets(buffer, sizeof buffer, inFile);
printf("Postfix expression:\n");
printf("%s", buffer);
char *e = buffer;
while (*e != '\0') {
if (isdigit((unsigned char)*e)) {
int num = 0;
while (isdigit((unsigned char)*e)) {
num = num * 10 + *e++ - '0';
}
push(num);
} else
if (isspace((unsigned char)*e) {
e++; // ignore white space
} else
if (isOperator(*e)) {
int op1 = pop();
int op2 = pop();
int ans = performOperation(op1, op2, *e++);
push(ans);
} else {
printf("Invalid character in expression: %c\n", *e++);
}
}
int ans = pop();
printf(" The value of the expression is %d\n", ans);
}
fclose(inFile);
return 0;
}

Program not receiving required input

I have a problem with my homework. I have some code written by teacher and I suppose to edit it in order to make a calculator. So I added couple of lines i thought it will work, but sadly it's not the case. Program returns always that operands or operator is wrong. Can you have a look?
main.c
#include "stdio.h"
#include "evalexpression.h"
int main() {
char string[100];
int result;
result = InterCalc(string);
CalcFilter(result, string);
return 0;
}
evalexpression.c
#include "stdio.h"
#include "string.h"
#include "evalexpression.h"
#include "math.h"
#include "float.h"
static float f1, f2;
static char op;
int isValidExpression(const char *str) {
int res;
char ops[10];
res = sscanf(str, "%f %s %f", &f1, ops, &f2);
if (res == 3) {
if (ops[0] == '+' || ops[0] == '-' || ops[0] == '^' || ops[0] == '*' || ops[0] == '/') {
op = ops[0];
return 1;
} else
return 0;
} else
return 0;
}
int getOperator() {
return (op);
}
float getFstOperand() {
return (f1);
}
float getSecOperand() {
return (f2);
}
float getExprValue() {
int operation;
operation = getOperator();
switch (operation) {
case 1:
return (getFstOperand() + getSecOperand());
break;
case 2:
return (getFstOperand() - getSecOperand());
break;
case 3:
return (getFstOperand() / getSecOperand());
break;
case 4:
return (getFstOperand() * getSecOperand());
break;
case 5:
return (pow(getFstOperand(), getSecOperand()));
break;
default:
return 0;
}
}
int InterCalc(char *my_string) {
fgets(my_string, sizeof(my_string), stdin);
if (strcmp(my_string, "exit\n") == 0) {
printf("Program ended\n");
return 0;
} else
if (isValidExpression(my_string) == 0) {
printf("Expression error\n");
return 0;
} else
return 1;
}
void CalcFilter(int a, char *str) {
float calculation_value;
printf("Press 'E' to display the invalid line or press 'V' to display the valid line\n");
int choice;
choice = getchar();
switch (choice) {
case 'E':
case 'e':
if (a == 0) printf("The line %s is invalid.\n", str);
else if (a == 1) printf("There's nothing wrong with the line %s\n", str);
break;
case 'V':
case 'v':
if (a == 1) {
calculation_value = getExprValue();
printf("The result of %s is %f.\n", str, calculation_value);
}
if (a == 0) printf("The line %s is invalid\n", str);
break;
default:
printf("You haven't chosen the valid option of the switch\n");
break;
}
}
You should pass the size of the destination buffer to function InterCalc(). As written, it can only read sizeof(char*) - 1 bytes at a time. You should also check for end of file.
int InterCalc(char *my_string, size_t size) {
if (fgets(my_string, size, stdin) == NULL
|| strcmp(my_string, "exit\n") == 0) {
printf("Program ended\n");
return 0;
} else
if (isValidExpression(my_string) == 0) {
printf("Expression error\n");
return 0;
} else {
return 1;
}
}
Invoke from main():
#include <stdio.h>
#include "evalexpression.h"
int main(void) {
char string[100];
int result;
result = InterCalc(string, sizeof(string));
CalcFilter(result, string);
return 0;
}
Notes:
you should use the <stdio.h> syntax for standard headers.
you should prevent buffer overflow by passing the maximum number of characters for %s formats in sscanf(): sscanf(str, "%f %9s %f", &f1, ops, &f2);
EDIT: There is another problem in GetExrValue(): you switch on values from 0 to 5 for op instead of the operation character. Here is a way to correct this:
float getExprValue(void) {
switch (getOperator()) {
case '+':
return getFstOperand() + getSecOperand();
case '-':
return getFstOperand() - getSecOperand();
case '/':
return getFstOperand() / getSecOperand();
case '*':
return getFstOperand() * getSecOperand();
case '^':
return pow(getFstOperand(), getSecOperand());
default:
return 0;
}
}

How do I detect an operator vs. int in C using scanf?

How do I read in the following input in my RPN calculator so that it will find the operator no matter what order?
2
2+
4
As of now my scanf only sees the first char in the string and I can only do this:
2
2
+
4
I'm also trying to add an option for integer vs floating point mode. (ex. when 'i' is entered, operate in floating point and vice versa.)
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
int *p;
int *tos;
int *bos;
void push(int i);
int pop(void);
int main (void)
{
int a, b;
//float c, d;
char s[80];
//char op; //declare string of 80 chars
p = (int *) malloc(MAX*sizeof(int)); //get stack memory
if (!p){
printf("Allocation Failure\n");
exit(1);
}
tos = p;
bos = p + MAX-1;
printf("\nRPN Calculator\n");
printf("Enter 'i' for integer mode\n");
printf("Enter 'f' for floating point mode\n");
printf("Enter 'q' to quit\n");
do {
printf("> ");
// gets(s);
// scanf("%s", s); //read integer
scanf("%s", s);
// switch (*s) {
switch(*s) {
case 'i':
printf("(Integer Mode)\n");
break;
case 'f':
printf("(Floating Point Mode)\n");
break;
case '+':
a = pop();
b = pop();
printf("%d\n", a+b);
push(a+b);
break;
case '-':
a = pop();
b = pop();
printf("%d\n", b-a);
push(b-a);
break;
case '*':
a = pop();
b = pop();
printf("%d\n", a*b);
push(a*b);
break;
case '/':
a = pop();
b = pop();
if(a == 0){
printf("Cannot divide by zero\n");
break;
}
printf("%d\n", b/a);
push(b/a);
break;
case '.':
a = pop();
push(a);
printf("Current value on top of stack: %d\n", a);
break;
default:
push(atoi(s));
}
} while (*s != 'q');
return 0;
}
// Put an element on the stack
void push (int i)
{
if (p > bos){
printf("Stack Full\n");
return;
}
*p = i;
p++;
}
// Get the element from the top of the stack
int pop (void)
{
p--;
if(p < 0) {
printf("Stack Underflow\n");
return 0;
}
return *p;
}
Your scanf reads the whole string. It's the following switch that judges by the first character and misses that + in 2+.
To improve it you can use the strtol function. It will parse an integer out of the string and return to you the location where the integer ended - if that's still not the end of the string, there may be an operator there.
A similar function for floating point numbers is strtod.
Here's some sample code of strtol applicable to your example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* input = "25+";
char* endptr;
int val = strtol(input, &endptr, 10);
if (*endptr == '\0')
{
printf("Got only the integer: %d\n", val);
}
else
{
printf("Got an integer %d\n", val);
printf("Leftover: %s\n", endptr);
}
return 0;
}
I'm not sure if I fully understood your question, but you could iterate through the string like this:
for(i = 0; i < strlen(s); i++)
{
// Here comes your switch section like this
switch(s[i]) {
.....
}
}
Remember also to include string.h.
I really didn't understand your code.
If expect the user to enter one character each time, I mean one character + enter, you should use a simple char instead of char[]. And if you pretend to use a string you should receive it and parse it pzico said.
You could do something like that. The problem would be in the treatment of numbers with multiple digits, but thinking a little bit you can fix this problem. I wrote an attempt, but I'm pretty sure it's not going to work.
printf("\nRPN Calculator\n");
printf("Enter 'i' for integer mode\n");
printf("Enter 'f' for floating point mode\n");
printf("Enter 'q' to quit\n");
scanf("%c", s);
switch(*s){
case 'i':
printf("(Integer Mode)\n");
break;
case 'f':
printf("(Floating Point Mode)\n");
break;
case 'q':
printf("Bye Bye\n");
return;
break;
}
printf("Enter the expression one character each time\n");
do {
scanf("%c", s);
switch(s) {
case '+':
a = pop();
b = pop();
printf("%d\n", a+b);
push(a+b);
break;
case '-':
a = pop();
b = pop();
printf("%d\n", b-a);
push(b-a);
break;
case '*':
a = pop();
b = pop();
printf("%d\n", a*b);
push(a*b);
break;
case '/':
a = pop();
b = pop();
if(a == 0){
printf("Cannot divide by zero\n");
break;
}
printf("%d\n", b/a);
push(b/a);
break;
case '.':
a = pop();
push(a);
printf("Current value on top of stack: %d\n", a);
break;
default:
a = pop()*10+atoi(s);
push(a);
}
} while (s != 'q');
Another problem in your code is in your pop function. What do you want to do with this test:
if(p < 0) {
printf("Stack Underflow\n");
return 0;
}
You are expecting your pointer to reach the address 0?
Anyway I hope this is not your homework.

Resources