Frage

I'm doing a homework assignment in C. I have to build a calculator that takes in RPN, converts it to a double, adds / removes it from stack and prints what's left on the stack. Everything seems to be going well until I run it. Upon entering my input, the char[] gets successfully converted to double (or so i think) and somewhere along the way (maybe in getop()) does the program think that i'm not entering digits. Here is the code and the output.

#include <stdio.h>

#define MAXOP 100    /* maximum size of the operand of operator */
#define NUMBER '0'  /* signal that a number was found */

int getOp(char []); /* takes a character string as an input */
void push(double); 
double pop(void);
double asciiToFloat(char []);

/* reverse polish calculator */
int main()
{

    int type;
    double op2;
    char s[MAXOP];

    printf("Please enter Polish Notation or ^d to quit.\n");
    while ((type = getOp(s)) != EOF) {
        switch (type)   {
        case NUMBER:
            push(asciiToFloat(s));
            break;
        case '+':
            push(pop() + pop());
            break;
        case '*':
            push(pop() * pop());
            break;
        case '-':
            op2 = pop();
            push(pop() - op2);
            break;
        case '/':
            op2 = pop();
            if (op2 != 0.0)
                push(pop() / op2);
            else
                printf("error : zero divisor!\n");
            break;
        case '\n':
            printf("\t%.2f\n", pop()); /* this will print the last item on the stack */ 
            printf("Please enter Polish Notation or ^d to quit.\n"); /* re-prompt the user for further calculation */
            break;
        default:
            printf("error: unknown command %s.\n", s);
            break;
        }
    }
    return 0;   
}

#include <ctype.h>

/* asciiToFloat: this will take ASCII input and convert it to a double */
double asciiToFloat(char s[])
{
    double val;
    double power;

    int i;
    int sign;

    for (i = 0; isspace(s[i]); i++) /* gets rid of any whitespace */
        ;
    sign = (s[i] == '-') ? -1 : 1; /* sets the sign of the input */
    if (s[i] == '+' || s[i] == '-') /* excludes operands, plus and minus */
        i++;
    for (val = 0.0; isdigit(s[i]); i++) 
         val = 10.0 * val + (s[i] - '0'); 
    if (s[i] = '.')
        i++;
    for (power = 1.0; isdigit(s[i]); i++) {
        val = 10.0 * val + (s[i] - '0');
        power *= 10.0;
    }
    return sign * val / power;
}



#define MAXVAL 100  /* maximum depth of value stack */

int sp = 0;     /* next free stack position */
double val[MAXVAL]; /* value stack */

/* push: push f onto value stack */
void push(double f)
{
    if (sp < MAXVAL) {
        val[sp++] = f; /* take the input from the user and add it to the stack */
        printf("The value of the stack position is %d\n", sp);
    }
    else
        printf("error: stack full, cant push %g\n", f);
}

/* pop: pop and return the top value from the stack */
double pop(void)
{
    if (sp > 0)
        return val[--sp];
    else {
        printf("error: stack empty\n"); 
        return 0.0; 
    }
}

#include <ctype.h>

int getch(void);
void ungetch(int);

/* getOp: get next operator or numeric operand */
int getOp(char s[])
{

    int i;
    int c;

    while ((s[0] = c = getch()) == ' ' || c == '\t')
        ;
    s[1] = '\0';
    if (!isdigit(c) && c != '.') {
        printf("Neither a digit or a decimal.\n");
        return c;   /* neither a digit nor a decimal */
    }
    i = 0;
    if (isdigit(c)) /* grab the integer */
        while (isdigit(s[++i] = c = getch()))
            ;
    if (c == '.') /* grab the fraction */
                while (isdigit(s[++i] = c = getch()))
                        ;   
    s[i] = '\0';
    if (c != EOF)
        ungetch(c);
    return NUMBER;
}

#define BUFSIZE 100

char buf[BUFSIZE];  /* buffer for ungetch */
int bufp = 0;       /* next free position in buffer */

/* getch: get a number that may or may not have been pushed back */
int getch(void)
{
    return (bufp > 0) ? buf[--bufp] : getchar(); 
}

/* ungetch: if we read past the number, we can push it back onto input buffer */
void ungetch(int c)
{
    if (bufp >= BUFSIZE)
        printf("ungetch: to many characters.\n");
    else
        buf[bufp++] = c;
}

Output :

Please enter Polish Notation or ^d to quit. 123 The value of the stack position is 1 Neither a digit or a decimal.
123.00 Please enter Polish Notation or ^d to quit.

Any thoughts regarding what's going on will be super helpful. It seems like then number is properly getting passed in, properly formatted from char to double, and then something goes wrong.

Thank you.

Rock

War es hilfreich?

Lösung

Your output shows that getch() is returning the line feed ("\n", 0x0A) at the end of the line. Also, unless you were required to write asciiToFloat() for your homework assignment, you should use atof() or strtod() (both declared in "stdlib.h") from the Standard C Library. They are (usually?) implemented to avoid loss of precision and accuracy during the conversion; repeatedly multiplying by 10 causes a loss of same. Nice looking code, otherwise! :)

Andere Tipps

Change

        printf("Neither a digit or a decimal.\n");

to

        printf("Neither a digit or a decimal: %d 0x%x.\n", c, c);

so you can see what is causing the message.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top