#c #rpn
#c #rpn
Вопрос:
Я выполняю домашнее задание на C. Мне нужно создать калькулятор, который принимает RPN, преобразует его в double, добавляет / удаляет его из стека и печатает то, что осталось в стеке. Кажется, все идет хорошо, пока я его не запустил. При вводе моего ввода символ [] успешно преобразуется в 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%.2fn", 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 %dn", sp);
}
else
printf("error: stack full, cant push %gn", f);
}
/* pop: pop and return the top value from the stack */
double pop(void)
{
if (sp > 0)
return val[--sp];
else {
printf("error: stack emptyn");
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] = '';
if (!isdigit(c) amp;amp; 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] = '';
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, чтобы выйти.
Любые мысли о том, что происходит, будут очень полезны. Похоже, что тогда число правильно передается, правильно форматируется из char в double, а затем что-то идет не так.
Спасибо.
Рок
Комментарии:
1. попробуйте очистить буфер перед вводом инструкции switch.
2. Также, когда я запускаю это, я не получаю приглашение, которое вы получаете. Как вы это используете, просто с
./<filename>.out
?
Ответ №1:
Изменить
printf("Neither a digit or a decimal.n");
Для
printf("Neither a digit or a decimal: %d 0x%x.n", c, c);
таким образом, вы можете увидеть, что вызывает сообщение.
Комментарии:
1. Спасибо за помощь. Вот результат: пожалуйста, введите польскую нотацию или ^d, чтобы выйти. 12 Значение позиции стека не равно 1 Ни цифре, ни десятичной дроби: 10 0xa. 12.00
Ответ №2:
Ваш вывод показывает, что getch() возвращает перевод строки (» n», 0x0A) в конце строки. Кроме того, если вам не нужно было писать asciiToFloat() для вашего домашнего задания, вы должны использовать atof() или strtod() (оба объявлены в «stdlib.h») из стандартной библиотеки C. Они (обычно?) реализовано, чтобы избежать потери точности и точности во время преобразования; многократное умножение на 10 приводит к потере того же значения. Красивый код, в противном случае! 🙂