📄 visualc++calulator.cpp
字号:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAXOP 100
#define NUMBER '0' // signal that a number was found
#define EMPTY 0
enum Optype { ND, TOR }; // ND for operand, TOR for operator
union Era
{
double nd; // op.era.nd
char tor; // op.era.tor
};
struct Op
{
int max;
int top;
enum Optype type;
union Era *era;
};
struct Op *create_stack(int max, enum Optype);
void push(union Era, struct Op *);
union Era pop(struct Op *);
void nullerr(void);
int getop(char []);
double operate(struct Op *opnd, struct Op *optor);
void print_stack(struct Op *op);
char top_tor(struct Op *);
int
main()
{
int c;
char s[MAXOP];
union Era era;
struct Op *opnd;
struct Op *optor;
opnd = create_stack(MAXOP, ND);
optor = create_stack(MAXOP, TOR);
printf(" 本程序可进行“加减乘除(+ - * /)”四则混合运算。\n");
printf(" 输入 q 或按 Ctrl+C 退出程序。\n");
printf(" 输入算式后按回车即可算出答案:\n\n");
while ((c = getop(s)) != EOF) {
switch (c) {
case NUMBER:
if (opnd->top > optor->top + 1) { // 如果是逆波兰算式
printf("\tparse error\n");
while (getchar() != '\n')
/*void*/;
opnd->top = EMPTY;
era.nd = 0.0;
}
else
era.nd = atof(s);
push(era, opnd);
break;
case '+': // + 和 - 优先级最低,把除了 '(' 以外的全部操作符弹出后入栈
case '-':
if (optor->top == EMPTY) {
era.tor = c;
push(era, optor);
}
else {
while (optor->top > EMPTY)
if (top_tor(optor) == '(')
break;
else {
era.nd = operate(opnd, optor);
push(era, opnd);
}
era.tor = c;
push(era, optor);
}
break;
case '*': // 乘除优先级最高,把相同优先级的乘和除弹出后入栈
case '/':
if (optor->top == EMPTY) {
era.tor = c;
push(era, optor);
}
else {
while (optor->top > EMPTY)
if (((era.tor = top_tor(optor)) == '+')
|| (era.tor == '-')
|| (era.tor == '('))
break;
else {
era.nd = operate(opnd, optor);
push(era, opnd);
}
era.tor = c;
push(era, optor);
}
break;
case '(': // '(' 不作运算,直接放入optor栈。
era.tor = c;
push(era, optor);
break;
case ')': // 把 '(' 之前的全部操作符弹出,计算后把 '(' 也弹出
while (optor->top > EMPTY)
if (top_tor(optor) == '(')
break;
else {
era.nd = operate(opnd, optor);
push(era, opnd);
}
pop(optor);
break;
case '\n': // 把余下的操作符全部弹出,计算后输出结果
if (opnd->top == EMPTY)
/*do nothing*/;
else
while (optor->top > EMPTY)
if (top_tor(optor) == '(')
pop(optor);
else {
era.nd = operate(opnd, optor);
push(era, opnd);
}
era = pop(opnd);
printf("\t%.8g\n", era.nd);
break;
case 'p':
print_stack(opnd);
getchar();
break;
case 'q':
exit(0);
break;
default:
printf("error: unknown command %s\n", s);
break;
}
}
return 0;
}
struct Op *create_stack(int max, enum Optype type)
{
struct Op *op;
op =(Op *) malloc(sizeof(*op));
if (op == NULL)
nullerr();
op->era = (Era *)calloc(sizeof(union Era), max);
if (op->era == NULL)
nullerr();
op->max = max;
op->top = EMPTY;
op->type = type;
return op;
}
void
push(union Era era, struct Op *op)
{
if (op->top >= op->max) {
if (op->type == ND)
printf("error: stack full, can't push %g\n", era.nd);
else
printf("error: stack full, can't push %c\n", era.tor);
}
else
op->era[op->top++] = era;
}
union Era
pop(struct Op *op)
{
if (op->top > EMPTY)
return op->era[--op->top];
else {
printf("error: stack empty\n");
if (op->type == ND)
op->era[EMPTY].nd = 0.0;
else
op->era[EMPTY].tor = 0;
return op->era[EMPTY];
}
}
void nullerr(void)
{
printf("not enough memory\n");
exit(1);
}
int getop(char s[]) // [K&R] section 4.3
{
int i, c;
while ((s[0] = c = getchar()) == ' ' || c == '\t')
/*do nothing*/;
s[1] = '\0';
if (!isdigit(c) && c != '.')
return c; // not a number
i = 0;
if (isdigit(c)) // collect integer part
while (isdigit(s[++i] = c = getchar()))
;
if (c == '.') // collect fraction part
while (isdigit(s[++i] = c = getchar()))
/*do nothing*/;
s[i] = '\0';
if (c != EOF)
ungetc(c, stdin);
return NUMBER;
}
double operate(struct Op *opnd, struct Op *optor)
{
union Era nd1, nd2, tor;
nd2 = pop(opnd);
nd1 = pop(opnd);
tor = pop(optor);
switch (tor.tor) {
case '+':
return nd1.nd + nd2.nd;
break;
case '-':
return nd1.nd - nd2.nd;
break;
case '*':
return nd1.nd * nd2.nd;
break;
case '/':
return nd1.nd / nd2.nd;
break;
default:
return 0.0;
break;
}
}
void print_stack(struct Op *op)
{
int i;
for (i = op->top; i > 0; i--)
printf("%g\n", op->era[i].nd);
}
char top_tor(struct Op *op)
{
return op->era[op->top-1].tor; // after push, top plus one
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -