1

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.

chqrlie
  • 131,814
  • 10
  • 121
  • 189

3 Answers3

1

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++);
}
1

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;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
1

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.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335