В этот раз проблема не в scanf()
, а в том, как вы анализируете входные данные.
Нет ничего плохого в том, чтобы разбирать входной символ за символом, наоборот, это значительно упрощаетхотя бы почти во всех случаях.Но анализ символа за символом также означает, что вы анализируете каждое положительное число больше девяти, а также символ за символом или лучше цифра за цифрой - вы должны построить полное число из одной цифры.Вы анализируете «слева направо», поэтому просто умножьте на десять и добавьте цифру.Промойте и повторяйте, пока у вас не останется цифр, и положите результат в стек.
Пример:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#define SIZE 6
/* you should look up what "static" means and when and how to use */
static int stack[SIZE]; //stack size
static int top = 0; //top of stack
/*
* You need to expicitely add "void" to the argumet list.
* It defaults to "int" otherwise.
* Please do yourself a favor and switch all warnings on.
*/
void pop(void);
void clear(void);
void display(void);
void top_element(void);
void add(void);
void multiply(void);
void subtract(void);
void division(void);
void power(void);
/* Most checks and balances omitted! */
int main(void)
{
/* "int" to make things easier */
int input;
int flag = 1, anumber;
while (flag == 1) {
printf(": ");
/* get a(n ASCII) character */
input = fgetc(stdin);
if (isdigit(input)) {
anumber = 0;
/*
* We have a digit. Parse input for more digits until
* no further digits appear and add all digits to "anumber".
* We assume a decimal representation here.
*/
/* TODO: check for overflow! */
for (;;) {
anumber *= 10;
anumber += input - '0';
input = fgetc(stdin);
if (!isdigit(input)) {
break;
}
}
/* Push number on the stack */
if (top < SIZE) {
stack[top] = anumber;
top++;
} else {
printf("Error: stack overflow\n");
}
}
/* "input" from fgetc() is an integer, we can use a switch */
switch (input) {
case 'p':
pop();
break;
case 'c':
clear();
break;
case 'd':
display();
break;
case '=':
top_element();
break;
case '+':
add();
break;
case '^':
power();
break;
case 'q':
flag = 0;
break;
default:
printf("Error: invalid command\n");
break;
}
}
printf("Goodbye!\n");
return 0;
}
void pop(void)
{
if (top == 0)
printf("Error: stack is empty\n");
else
top--;
}
void clear(void)
{
top = 0;
}
void display(void)
{
int i;
if (top == 0)
printf("Error: stack is empty\n");
else {
for (i = top - 1; i >= 0; i--)
printf("%d\n", stack[i]);
}
}
void top_element(void)
{
printf("%d\n", stack[top - 1]);
}
void add(void)
{
if (top < 2)
printf("Error: not enough operands for the requested operation\n");
else {
int ans = stack[top - 1] + stack[top - 2];
stack[top - 2] = ans;
top--;
}
}
/* Using pow() from math.h is not a good idea beause it uses floating point */
/* TODO check for overflows! */
static int integer_pow(int x, int n)
{
int r;
r = 1;
while (n != 0) {
if (n & 1) {
r *= x;
}
x *= x;
n >>= 1;
}
return r;
}
void power(void)
{
if (top < 2)
printf("Error: not enough operands for the requested operation\n");
else {
int ans = integer_pow(stack[top - 2], stack[top - 1]);
stack[top - 2] = ans;
top--;
}
}
Тест:
$ ./stackbcalc
: 123+23=
Error: not enough operands for the requested operation
: 23
: Error: invalid command
: q
Goodbye!
Не работает.Зачем?Функция add()
ожидает два операнда в стеке.Вам также нужно поместить +
в стек (это целое число), и как только вы в конце наберете =
, вы сможете оценить стек.Вам может понадобиться кое-что узнать о нотации infix / postfix / prefix, чтобы успешно это сделать.
Подсказка: я бы также проигнорировал пробел (пробел и табуляция, возможно, даже возврат) в переключателе.