Обратный польский калькулятор в C: isdigit () проблемы - PullRequest
0 голосов
/ 25 октября 2011

Я делаю домашнее задание на C. Мне нужно построить калькулятор, который принимает RPN, конвертирует его в двойное число, добавляет / удаляет его из стека и печатает то, что осталось в стеке. Кажется, все идет хорошо, пока я не запустил его. После ввода моего ввода char [] успешно конвертируется в double (или, я так думаю), и где-то по пути (может быть, в getop ()) программа считает, что я не ввожу цифры. Вот код и вывод.

#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;
}

Выход:

Пожалуйста, введите польскую запись или ^ d, чтобы выйти. 123 Значение позиции стека равно 1 Ни цифра, ни десятичное число.
123,00 Пожалуйста, введите польскую запись или ^ d, чтобы выйти.

Любые мысли о том, что происходит, будут очень полезными. Кажется, что тогда число правильно передается, правильно форматируется от символа к двойному, и тогда что-то идет не так.

Спасибо.

Рок

Ответы [ 2 ]

3 голосов
/ 25 октября 2011

Изменение

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

до

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

чтобы вы могли видеть, что вызывает сообщение.

0 голосов
/ 26 октября 2011

Ваш вывод показывает, что getch () возвращает перевод строки ("\ n", 0x0A) в конце строки.Кроме того, если вам не нужно было писать asciiToFloat () для домашнего задания, вы должны использовать atof () или strtod () (оба объявлены в "stdlib.h") из стандартной библиотеки C.Они (обычно?) Реализованы, чтобы избежать потери точности и точности при конвертации;многократное умножение на 10 приводит к потере того же самого.Красивый код, в противном случае!:)

...