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;
}
Related
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
I am getting a "Type mismatch in parameter 1 in call to 'push'" error at the 28th line of the code in Turbo C++, please help me as I have to submit my project, I know that Turbo C++ is a very old compiler but that's what our University Teacher recommends so I cant do nothing in that
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
#include <stdio.h>
#include <conio.h>
int stack[100];
int top = -1;
void in2post(char[]);
void push(int);
int pop();
int prec(char);
int cal(char[]);
void main()
{
char in[100], post[100];
clrscr();
printf("Enter an infix expression: ");
gets(in);
in2post(in);
getch();
}
void in2post(char in_exp[])
{
int x = 0, y = 0, z, result = 0;
char a, c, post_exp[100];
char t;
push("\0");
t = in_exp[x];
while (t != '\0')
{
if (isalnum(t))
{
post_exp[y] = t;
y++;
}
else if (t == '(')
{
push('(');
}
else if (t == ')')
{
while (stack[top] != '(')
{
c = pop();
post_exp[y] = c;
y++;
}
c = pop();
}
else
{
while (prec(stack[top]) >= prec(t))
{
c = pop();
post_exp[y] = c;
y++;
}
push(t);
}
x++;
t = in_exp[x];
}
while (top != -1)
{
c = pop();
post_exp[y] = c;
y++;
}
printf("\nThe equivalent postfix expression is: ");
for (z = 0; z < y; z++)
printf("%c", post_exp[z]);
printf("\n\nDo you want to evaluate the postfix expression? (Y/N): ");
scanf("%c", &a);
if (a == 'y' || a == 'y')
{
result = cal(post_exp);
printf("\nResult = % d\n", result);
getch();
}
else if (a == 'n' || a == 'N')
{
exit(0);
}
}
int cal(char post[])
{
int m, n, x, y, j = 0, len;
len = strlen(post);
while (j < len)
{
if (isdigit(post[j]))
{
x = post[j] - '0';
push(x);
}
else
{
m = pop();
n = pop();
switch (post[j])
{
case '+':
x = n + m;
break;
case '-':
x = n - m;
break;
case '*':
x = n * m;
break;
case '/':
x = n / m;
break;
}
push(x);
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
// Function push
void push(char x){
stack[++top] = x;
}
//Function pop
char pop(){
if(top == -1)
return -1;
else
return stack[top--];
}
//Arithmetic operator precedence
int priority(char x){
if(x == '(')
return 0;
if(x == '+' || x == '-')
return 1;
if(x == '*' || x == '/')
return 2;
else
return -1;
}
//Function to convert infix to postfix
char postfix(){
char *e, x = '\0';
char exps[20];
e = exps;
printf("\nEnter an expression: \n");
scanf("%s",exps);
while(*e != '\0') //While loop to arrange stack
{
if(isalnum(*e)) //isalnum convert character to ASCII code
printf("%c",*e);
else if(*e == '(')
push(*e);
else if(*e == ')')
{
while((x = pop()) != '(')
printf("%c", x);
}
else
{
while(priority(stack[top]) >= priority(*e))
printf("%c",pop());
push(*e);
}
e++;
}
while(top != -1)
{
printf("%c",pop());
}
exit(0);
return 0;
}
//Function to read file called default input
char read_file(){
char file_location[100];
int user_option=1;
FILE *fp;
character =ch;
while (user_option == 1) {
printf("Enter the location of the file:\n\n");
getchar();
gets(file_location);
fp = fopen(file_location,"r"); //read file
if( fp == NULL )
{
perror("Error while opening the file, \n\n");
exit(EXIT_FAILURE);
}
printf("The contents of the %s file are :\n\n" , file_location);
while( ( *ch = fgetc(fp) !=EOF))
printf("%s" ,ch);
fclose(fp);
postfix();
break;
}
return 0;
}
int manual_input() {
int choice=0;
while(choice == 0)
{
printf("\n\t\t\t\tMENU");
printf("\n\t------------------------------");
printf("\n\n\t 1. Postfix");
printf("\n\t 2. Prefix");
printf("\n\t 3. Both");
printf("\n\t 4. Exit");
printf("\n\tWould you like to convert it to: ");
scanf( "%d", &choice );
switch(choice)
{
case 1:
printf("\nYOU SELECTED OPTION 1 %c",1);
break;
case 2:
printf("\nYOU SELECTED OPTION 2 %c",2);
break;
case 3:
printf("\nYOU SELECTED OPTION 3 %c",3);
break;
default:
printf("\nYOU SELECTED OPTION 4 %c",4);
exit(0);
}
postfix();
}
return 0;
}
int main(){
printf("\nHi ,how would you like to input expression? \n");
printf("1.Get from file\n");
printf("2.Input own expression\n");
scanf("%d",&option);
if (option == 1) {
read_file();
} else {
manual_input();
}
}
Alright so I know my codes a little messy, had some problems indenting certain parts of code. Hopefully you can still understand. So my question is how do I get the characters from the file default.txt and pass it to my postfix function?
In my read_file function I manage to print the characters (ch) using a while loop. My goal here is to store the string so my postfix function can perform some calculation on it since I am trying to convert infix to postfix.
If you're wondering, this program gets user to choose whether to enter an expression through a file or manual input. The expression (which is an infix) is then converted to postfix.
Thanks
like this
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX_EXP_LEN 256
//Stringification
#define S_(n) #n
#define S(n) S_(n)
int top = -1;
char stack[MAX_EXP_LEN];
void push(char x){
stack[++top] = x;
}
char pop(void){
if(top == -1)
return -1;
else
return stack[top--];
}
int priority(char x){
if(x == '(')
return 0;
if(x == '+' || x == '-')
return 1;
if(x == '*' || x == '/')
return 2;
else
return -1;
}
void postfix(const char *exps){//Use the input expression as an argument
const char *e = exps;
char x = '\0';
while(*e != '\0'){
if(isalnum(*e))
printf("%c",*e);
else if(*e == '(')
push(*e);
else if(*e == ')'){
while((x = pop()) != '(')
printf("%c", x);
} else {
while(priority(stack[top]) >= priority(*e))
printf("%c", pop());
push(*e);
}
e++;
}
while(top != -1){
printf("%c", pop());
}
puts("");
}
void read_file(char exps[MAX_EXP_LEN + 1]){
char file_location[FILENAME_MAX+1] = "";
FILE *fp;
printf("Enter the location of the file:\n\n");
scanf("%" S(FILENAME_MAX) "[^\n]%*c", file_location);
fp = fopen(file_location, "r");
if( fp == NULL ){
perror("Error while opening the file.\n\n");
exit(EXIT_FAILURE);
}
fscanf(fp, "%" S(MAX_EXP_LEN) "s", exps);
fclose(fp);
}
void manual_input(char exps[MAX_EXP_LEN + 1]){
printf("Input expression\n");
scanf("%" S(MAX_EXP_LEN) "s", exps);
}
int main(void){
char exps[MAX_EXP_LEN + 1] = "";
int option;
printf("\nHi ,how would you like to input expression? \n");
printf("1.Get from file\n");
printf("2.Input own expression\n");
scanf("%d", &option);
scanf("%*[^\n]");scanf("%*c");//clear stdin
if (option == 1)
read_file(exps);//exps pass to function
else
manual_input(exps);
postfix(exps);
}
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;
}
}
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);
}
}