1 程序设计
为了实现用栈计算算数表达式的值,需设置两个工作栈:用于存储运算符的栈operandStack,以及用于存储操作数及中间结果的栈operatorStack。
算法基本思想如下:
1)首先将操作数栈operandStack设为空栈,而将'#'作为运算符栈operatorStack的栈底元素,这样的目的是判断表达式是否求值完毕。
2)依次读入表达式的每个字符,表达式须以'#'结尾,若是操作数则入栈operandStack,若是运算符,则将此运算符c与operatorStack的栈顶元素top比较优先级后执行相应的操作,具体操作如下:
①若top的优先级小于c,即top<c,则将c直接入栈operatorStack,并读入下一字符赋值给c;
②若top的优先级等于c,即top=c,则弹出operatorStack的栈顶元素,并读入下一字符赋值给c,这一步目的是进行括号操作;
③若top优先级高于c,即top>c,则表明可以计算,此时弹出operandStack的栈顶两个元素,并且弹出operatorStack栈顶的的运算符,计算后将结果放入占operandStack中,然后继续比较top和c的优先级,直至top不大于c。
④重复①②③直至operatorStack栈空,此时求值结束。
算符间的优先关系如下表所示:
表中需要注意的是θ1为opter的栈顶元素,θ2位从表达式中读取的操作符,此优先级表可以用二维数组实现。
2 C语言实现
代码:
相关变量
#include <stdlib.h>
#include <stdio.h>
#define STACK_INIT_SIZE 100 //栈初始开辟空间大小
#define STACK_INCREMENT 10 //栈追加空间大小
//优先级数组,2表示top>c,1表示top<c,0表示top=c,-1表示错误
int prior[7][7] = {{2,2,1,1,1,2,2},{2,2,1,1,1,2,2},{2,2,2,2,1,2,2},
{2,2,2,2,1,2,2},{1,1,1,1,1,0,-1},{2,2,2,2,-1,2,2},{1,1,1,1,1,-1,0}};
栈的实现
//******************************************************************
// 整形栈的实现
//******************************************************************
//整形栈结构体
typedef struct {
int *base;
int *top;
int size;
}intStack;
//栈初始化
intStack intStack_init()
{
intStack s;
s.base = (int *)malloc(sizeof(int)*STACK_INIT_SIZE);
s.top = s.base;
s.size = STACK_INIT_SIZE;
return s;
}
//入栈
void intPush(intStack *s, int e)
{
if(s->top - s->base >= s->size)
{
s->size += STACK_INCREMENT;
s->base = realloc(s->base, sizeof(int)*s->size);
}
*s->top = e;
s->top++;
}
//出栈
int intPop(intStack *s)
{
if(s->top != s->base)
{
s->top--;
return *s->top;
}
return -1;
}
//******************************************************************
// 字符栈的实现
//******************************************************************
//字符栈结构体
typedef struct {
char *base;
char *top;
int size;
}charStack;
//栈初始化
charStack charStack_init()
{
charStack s;
s.base = (char *)malloc(sizeof(char)*STACK_INIT_SIZE);
s.top = s.base;
s.size = STACK_INIT_SIZE;
return s;
}
//入栈
void charPush(charStack *s, char e)
{
if(s->top - s->base >= s->size)
{
s->size += STACK_INCREMENT;
s->base = realloc(s->base, sizeof(char)*s->size);
}
*s->top = e;
s->top++;
}
//出栈
char charPop(charStack *s)
{
if(s->top != s->base)
{
s->top--;
return *s->top;
}
return -1;
}
//得到栈顶元素,但不出栈
char getTop(charStack *s)
{
s->top--;
char temp = *s->top;
s->top++;
return temp;
}
求解表达式
//******************************************************************
// 使用栈结构求解表达式
//******************************************************************
//得到操作符在数组prior中的索引值
int getIndex(char operator)
{
switch(operator)
{
case '+' : return 0;
case '-' : return 1;
case '*' : return 2;
case '/' : return 3;
case '(' : return 4;
case ')' : return 5;
case '#' : return 6;
}
}
//求得两个操作数和一个操作符的运算结果
int compute(int operand1, int operand2, char operator)
{
switch(operator)
{
case '+' : return operand1 + operand2;
case '-' : return operand1 - operand2;
case '*' : return operand1 * operand2;
case '/' : return operand1 / operand2;
}
}
//由表达式字符串指针,得到下一个操作符或操作数
//得到操作符标记key=0,得到操作数标记key=1
//返回偏移后的字符串指针
char *operand_or_operator(char *p, int *operand, char *operator, int *key)
{
while(*p == ' ') p++; //跳过空格
if(*p >= '0' && *p <= '9') //得到操作数
{
*operand = 0;
int dec = 1; //十进制数位权重
intStack s = intStack_init(); //使用整形栈转化数值
while(*p >= '0' && *p <= '9') //操作数位由高到低依次压入栈中
{
intPush(&s, *p - '0');
p++;
}
while(s.base != s.top) //依次读取栈中操作数各位
{
*operand += intPop(&s) * dec;
dec *= 10;
}
*key = 1;
}
else //得到操作符
{
switch(*p)
{
case '+' :*operator = '+';break;
case '-' :*operator = '-';break;
case '*' :*operator = '*';break;
case '/' :*operator = '/';break;
case '(' :*operator = '(';break;
case ')' :*operator = ')';break;
case '#' :*operator = '#';break;
}
p++;
*key = 0;
}
return p;
}
//由表达式字符串得到最终计算结果
int output(char *p)
{
intStack operandStack = intStack_init(); //初始化操作数栈
charStack operatorStack = charStack_init(); //初始化操作符栈
charPush(&operatorStack, '#');
int operand, key, index1, index2;
char operator;
while(operatorStack.base != operatorStack.top) //操作符栈空代表计算结束
{
p = operand_or_operator(p, &operand, &operator, &key);
if(key) //得到操作数
intPush(&operandStack, operand);
else //得到操作符
{
index1 = getIndex(getTop(&operatorStack));
index2 = getIndex(operator);
while(prior[index1][index2] == 2) //top优先级高于c
{
intPush(&operandStack, compute(intPop(&operandStack), intPop(&operandStack), charPop(&operatorStack)));
index1 = getIndex(getTop(&operatorStack));
}
if(prior[index1][index2] == 1) //top优先级低于c
{
charPush(&operatorStack, operator);
}
else if(prior[index1][index2] == 0) //top优先级等于c
{
charPop(&operatorStack);
}
else
{
printf("Enter Error!!!\n");
return 0XFFFFFFFF;
}
}
}
return intPop(&operandStack);
}
主函数
//******************************************************************
// 主函数
//******************************************************************
void main()
{
char str[100];
int out;
printf("\n请输入规范的四则运算表达式,以#结尾:\n");
scanf("%s", str);
out = output(str);
if(out != 0XFFFFFFFF)
printf("结果等于:\n%d\n\n", out);
system("date /T");
system("TIME /T");
system("pause");
exit(0);
}
运行结果:
3 Python实现
代码:
#coding=gbk
import datetime
import time
from pip._vendor.distlib.compat import raw_input
#优先级列表
prior = [[2,2,1,1,1,2,2], [2,2,1,1,1,2,2], [2,2,2,2,1,2,2],
[2,2,2,2,1,2,2], [1,1,1,1,1,0,-1], [2,2,2,2,-1,2,2], [1,1,1,1,1,-1,0]]
#########################################################################################
# 栈类
#########################################################################################
class Stack:
def __init__(self):
self._s = []
def push(self, e):
self._s.append(e)
def pop(self):
if self._s:
return self._s.pop()
else:
raise LookupError("stack is empty!")
def isEmpty(self):
return bool(self._s)
def getTop(self):
return self._s[-1]
#########################################################################################
# 表达式求值函数模块
#########################################################################################
#由操作符得到优先级列表索引值
def getIndex(operator):
var = 0
if operator == '+':
var = 0
elif operator == '-':
var = 1
elif operator == '*':
var = 2
elif operator == '/':
var = 3
elif operator == '(':
var = 4
elif operator == ')':
var = 5
elif operator == '#':
var = 6
return var
#得到一个操作符作用于两个操作数的结果
def compute(operand2, operand1, operator):
var = 0
if operator == '+':
var = operand1 + operand2
elif operator == '-':
var = operand1 - operand2
elif operator == '*':
var = operand1 * operand2
elif operator == '/':
var = operand1 / operand2
return var
#由表达式字符串和索引值得到下一个操作数或操作符
#函数返回3元列表,list[0]是操作数或操作符,list[1]是偏移后的索引值
#list[3]是标记值,返回操作符标记0,返回操作数返回1
def operand_or_operator(string, index):
var = []
while string[index] == ' ':
index += 1
if string[index] in ['+', '-', '*', '/', '(', ')', '#']:
var = [string[index], index+1, 0]
elif string[index] in [str(x) for x in range(0, 10)]:
temp = index
while string[index] in [str(x) for x in range(0, 10)]:
index += 1
var = [int(string[temp:index]), index, 1]
return var
#由表达式字符串得到最终结果
def output(string):
operandStack = Stack() #操作数栈
operatorStack = Stack() #操作符栈
operatorStack.push('#')
index = 0
while operatorStack._s != []: #操作符栈空计算结束
value = operand_or_operator(string, index)
if value[2] == 1: #得到操作数
operandStack.push(value[0])
elif value[2] == 0: #得到操作符
index1 = getIndex(operatorStack.getTop())
index2 = getIndex(value[0])
while prior[index1][index2] == 2: #top>c
operandStack.push(compute(operandStack.pop(),operandStack.pop(),operatorStack.pop()))
index1 = getIndex(operatorStack.getTop())
if prior[index1][index2] == 1: #top<c
operatorStack.push(value[0])
elif prior[index1][index2] == 0: #top=c
operatorStack.pop()
else: #输入错误
return 0XFFFFFFFF
index = value[1]
return operandStack.pop()
########################################################################################
# 主模块
########################################################################################
if __name__ == '__main__':
string = input("\n请输入规范的四则运算表达式,以#结束:\n")
out = output(string)
if out == 0XFFFFFFFF:
print("Enter Error!!!")
else:
print("结果等于:\n{}\n\n".format(out))
datetime = datetime.datetime.now()
print(datetime.strftime("%Y-%m-%d\n%H:%M:%S"))
input("Press Enter to exit…")