算术表达式求值演示
问题描述:表达式计算是实现程序设计语言的基本问题之一,也是栈的应用的典型例子。设计一个程序,演示用算符优先法对算术表达式求值的过程。
基本要求:以字符序列的形式从键盘输入语法正确的,不含变量的整型表达式。利用教科书表3.1给出的算符优先关系,实现对算术四则混合运算表达式的求值,并仿照教科书的例3.1演示在求值中运算符栈、运算数栈、输入字符和主要操作的变化过程。
测试数据:3*(7-2)
1+2+3+4
88-1*5
1024/4*8
1024/(4*8)
(20+2)*(6/2)
3-3-3
8/(9-9)
2*(6+2*(3+6*(6+6)))
(((6+6)*6+3)*2+6)*2
实现提示:(1)设置运算符栈和运算数栈辅助分析算符优先关系。
(2)在读入表达式的字符序列的同时,完成运算符和运算数(整数)的识别处理,以及相应的运算。
(3)在识别出运算数的同时,要将其字符序列形式转换成整数形式。
(4)在程序的适当位置输出运算符栈、运算数栈、输入字符和主要操作的内容。
选作内容:(1)扩充运算符集合,如增加乘方、一元减和赋值等运算。
(2)运算量可以是变量。
(3)运算量可以是实数类型。
(4)计算器的功能和仿真界面。
stack.h
#pragma once
#define STACK_TEST
#ifdef STACK_TEST
#ifdef __cplusplus
extern "C" {
#endif // __cpluscplus
struct StackNode
{
struct StackNode* next;
};
struct LStack
{
struct StackNode header;
int size;
};
typedef void* LinkStack;
// 采用头插法push元素
LinkStack Init();
void Push(LinkStack stack, void* data);
void Pop(LinkStack stack);
void* Top(LinkStack stack);
int Size(LinkStack stack);
void Destroy(LinkStack stack);
bool Empty(LinkStack stack);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // STACK
stack.cpp
#include <iostream>
#include "stack.h"
LinkStack Init()
{
struct LStack* stack = (struct LStack*)malloc(sizeof(struct LStack));
if (NULL == stack) return NULL;
stack->header.next = NULL;
stack->size = 0;
}
void Push(LinkStack stack, void* data)
{
if (NULL == stack) return;
if (NULL == data) return;
struct LStack* linkStack = (struct LStack*)stack;
struct StackNode* node = (struct StackNode*)data;
node->next = linkStack->header.next;
linkStack->header.next = node;
linkStack->size++;
}
void Pop(LinkStack stack)
{
if (NULL == stack) return;
struct LStack* linkStack = (struct LStack*)stack;
if (linkStack->size == 0) return;
struct StackNode* pDel = linkStack->header.next;
linkStack->header.next = pDel->next;
linkStack->size--;
}
void* Top(LinkStack stack)
{
if (NULL == stack) return NULL;
struct LStack* linkStack = (struct LStack*)stack;
return linkStack->header.next;
}
int Size(LinkStack stack)
{
if (NULL == stack) return -1;
return ((struct LStack*)stack)->size;
}
void Destroy(LinkStack stack)
{
if (NULL == stack) return;
free(stack);
}
bool Empty(LinkStack stack)
{
return Size(stack) > 0;
}
expr.h
#pragma once
#include "stack.h"
// + - * / ( )#
const char expr_table[7][7] = {
{ '>', '>', '<', '<', '<', '>', '>'},
{ '>', '>', '<', '<', '<', '>', '>'},
{ '>', '>', '>', '>', '<', '>', '>'},
{ '>', '>', '>', '>', '<', '>', '>'},
{ '<', '<', '<', '<', '<', '=', '\0'},
{ '>', '>', '>', '>', '\0', '>', '>'},
{ '<', '<', '<', '<', '<', '\0', '='}
};
int expr_label(char ch);
bool is_numeric(char ch);
char get_top(struct LStack* stack);
void pop(struct LStack* stack, char* ch);
void pop(struct LStack* stack, double* val);
void pop(struct LStack* stack);
void push(struct LStack* stack, char ch);
void push(struct LStack* stack, double val);
char Precede(char ch1, char ch2);
double Operate(double a, char expr, double b);
double EvaluateExpression();
expr.cpp
#include <iostream>
#include "expr.h"
#include "stack.h"
using namespace std;
struct CharType
{
struct StackNode node;
char ch;
};
struct NumType
{
struct StackNode node;
double val;
};
int expr_label(char ch)
{
int i = -1;
switch (ch)
{
case '+':
i = 0;
break;
case '-':
i = 1;
break;
case '*':
i = 2;
break;
case '/':
i = 3;
break;
case '(':
i = 4;
break;
case ')':
i = 5;
break;
case '#':
i = 6;
break;
}
return i;
}
bool is_numeric(char ch)
{
return '0' <= ch && ch <= '9';
}
char get_top(struct LStack* stack)
{
return ((struct CharType*)Top(stack))->ch;
}
void pop(struct LStack* stack, char* ch)
{
*ch = ((struct CharType*)Top(stack))->ch;
Pop(stack);
}
void pop(struct LStack* stack, double* val)
{
*val = ((struct NumType*)Top(stack))->val;
Pop(stack);
}
void pop(struct LStack* stack)
{
Pop(stack);
}
void push(struct LStack* stack, char ch)
{
struct CharType* data = new CharType;
data->ch = ch;
Push(stack, data);
}
void push(struct LStack* stack, double val)
{
struct NumType* data = new NumType;
data->val = val;
Push(stack, data);
}
char Precede(char ch1, char ch2)
{
return expr_table[expr_label(ch1)][expr_label(ch2)];
}
double Operate(double a, char expr, double b)
{
double ans = 0;
switch (expr)
{
case '+':
ans = a + b;
break;
case '-':
ans = a - b;
break;
case '*':
ans = a * b;
break;
case '/':
if (!b)
{
cout << "除数不能为0!!!" << endl;
exit(-1);
}
ans = a / b;
break;
}
return ans;
}
double EvaluateExpression()
{
struct LStack* OPND = (struct LStack*)Init();
struct LStack* OPTR = (struct LStack*)Init();
char ch;
int flag = 0;
push(OPTR, '#');
cin >> ch;
while (ch != '#' || get_top(OPTR) != '#')
{
if (is_numeric(ch))
{
double num = (double)(ch - '0');
if (!flag)
push(OPND, num);
else
{
double tmp = ((struct NumType*)Top(OPND))->val;
((struct NumType*)Top(OPND))->val = tmp * 10 + num;
}
flag = 1;
cin >> ch;
}
else
{
flag = 0;
switch (Precede(get_top(OPTR), ch))
{
case '<':
push(OPTR, ch);
cin >> ch;
break;
case '>':
char theta;
pop(OPTR, &theta);
double a,b;
pop(OPND, &b);
pop(OPND, &a);
push(OPND, Operate(a, theta, b));
break;
case '=':
pop(OPTR);
cin >> ch;
break;
default:
cout << "illegal expression" << endl;
exit(-1);
break;
}
}
}
return ((struct NumType*)Top(OPND))->val;
}
main.cpp
#include <iostream>
#include "expr.h"
using namespace std;
void banner()
{
cout << "##############################################################" << endl;
cout << " 实验三 算术表达式求值演示 " << endl;
cout << "##############################################################" << endl;
}
int main()
{
banner();
cout << "\n\tPlease input a expression(end with '#'): " << endl;
int ans = EvaluateExpression();
cout << "The answer is " << ans << endl;
return EXIT_SUCCESS;
}
结语
选做内容有空更新