问题
缺陷
1.输入必须正确输入算符(运算符+界限符)和操作数,若输入非(算符和操作数),无法判断出(因为默认非算符的数都为操作数,否则无法保留两位数及以上的运算结果)
2.输入的操作数必须为个位数,因为输入类型是字符,只能读取一个字符(且,输入类型不能是int型,int无法写入算符)
3.运算结果只能返回255个值(ASCII码只能表示255个:-128127其中0127才有对照表)范围:(-176+48=-128,再小就超出范围)-1760(‘0’为48)79(79+48=127,再大就超出范围了),超出范围(过小则变为79逐渐变小;过大则变为-176逐渐变大)
4.算符匹配错误返回-1
#include <stdio.h>
#include <stdlib.h>
#include<iostream>
#include<string>
using namespace std;
typedef enum {da , xiao, deng, ERROR }pre;//枚举元素得是字母与数字组成的符号序列
typedef char ElemType;
typedef struct StackNode* StackLink;
struct StackNode{
ElemType data;
StackLink next;
};
//初始化
void InitStack(StackLink &S){
S = NULL;
return;
}
//入栈
void Push(StackLink &S, ElemType e){
StackLink p = (StackLink)malloc(sizeof(StackNode));
p->data = e;
p->next = S;
S = p;
return;
}
//出栈
void Pop(StackLink &S, ElemType &e){
e = S->data;
S = S->next;
return;
}
//返回栈顶元素
ElemType GetHead(StackLink S){
if (S == NULL)return 0;
return S->data;
}
//堆栈判空
bool StackEmpty(StackLink S){
if (S == NULL)return true;
return false;
}
//算符判断优先级
pre Precede(ElemType x,ElemType y){
if ((x == '('&&y == '#') || (x == ')'&&y == '(') || (x == '#'&&y == ')'))
return ERROR;
else if (x == '+'||x=='-'){
if (y == '+' || y == '-' || y == ')' || y == '#')
return da ;
else
return xiao ;
}
else if (x == '*'||x=='/'){
if (y == '+' || y == '-' || y == '*' || y == '/' || y == ')' || y == '#')
return da ;
else
return xiao ;
}
else if (x == '('){
if (y == ')')
return deng;
else
return xiao ;
}
else if (x == ')')
return da ;
else{
if (y == '#')
return deng;
else
return xiao ;
}
}
//运算
ElemType Operate(ElemType a, ElemType x, ElemType b){
int c = a - '0',d = b - '0';
ElemType sum;
if (x == '+')
sum=(c + d + '0');
else if (x == '-')
sum=(c - d + '0');
else if (x == '*')
sum=(c*d + '0');
else
sum=(c / d + '0');
return sum;
}
//表达式求值
//1.输入必须正确输入算符(运算符+界限符)和操作数,若输入非(算符和操作数),无法判断出(因为默认非算符的数都为操作数,否则无法保留两位数及以上的运算结果)
//2.输入的操作数必须为个位数,因为输入类型是字符,只能读取一个字符
//3.输入类型不能是int型,int无法写入算符
//表达式以#开头#结尾,开头的#用程序写,压入栈,结尾的#通过键盘输入
int EvaluateExpression(){
StackLink OPND, OPTR;
InitStack(OPND);//初始化OPND栈,寄存操作数或运算结果
InitStack(OPTR);//初始化OPTR栈,寄存算符
Push(OPTR, '#');//表达式起始符#入栈
ElemType p,theta,a,b;//p是键盘输入的,theta,a和b是算符和两个操作数(当输入为算符且优先级高时运算用:a theta b)
cin >> p;
while (p != '#'||GetHead(OPTR)!='#'){//表达式没有扫描完毕或OPTR的栈顶元素不为‘#’
//如果是算符就比较优先级(当出现优先级高的算符就运算,优先级低的就入栈)
if (p == '+' || p == '-' || p == '*' || p == '/' || p == '(' || p == ')'||p=='#')
switch (Precede(GetHead(OPTR),p))
{
case xiao://若优先级低,先把算符压入OPTR不计算
Push(OPTR, p);
cin >> p;
break;
case da://若优先级高,则进行运算,弹出OPTR栈顶的算符和OPND的两个数
//输入)的情况下优先级总是高【(则等于,可消掉括号】,前一个算符参与后运算不输入新p,)会循环到下一次和前一个算符再比较优先级直到遇到(
Pop(OPTR, theta);//p为弹出的算符
Pop(OPND, b);//先出的是后进的
Pop(OPND, a);//后出的是先进的
Push(OPND, Operate(a, theta, b));//运算结果压入OPND
break;
case deng://若优先级相等(只有()和##两种情况)则括号匹配成功,消去栈顶的(/#并且不让p入栈,写新p
//(##其实不会出现,当p为#且栈顶元素为#时就退出循环了已经)
Pop(OPTR, p);//p是弹出的废弃算符
cin >> p;
break;
default:
return -1;
}
//如果是操作数就入栈OPND
else{
Push(OPND, p);
cin >> p;
}
}
int sum = GetHead(OPND)-'0';
return sum;
}
int main(){
printf("结果是:%d",EvaluateExpression());
system("PAUSE");
return 0;
}
0.结构体和枚举类型
注意枚举元素得是字母与数字组成的符号序列
typedef enum {da , xiao, deng, ERROR }pre;//枚举元素得是字母与数字组成的符号序列
typedef char ElemType;
typedef struct StackNode* StackLink;
struct StackNode{
ElemType data;
StackLink next;
};
1.链栈的基本操作
//初始化
void InitStack(StackLink &S){
S = NULL;
return;
}
//入栈
void Push(StackLink &S, ElemType e){
StackLink p = (StackLink)malloc(sizeof(StackNode));
p->data = e;
p->next = S;
S = p;
return;
}
//出栈
void Pop(StackLink &S, ElemType &e){
e = S->data;
S = S->next;
return;
}
//返回栈顶元素
ElemType GetHead(StackLink S){
if (S == NULL)return 0;
return S->data;
}
//堆栈判空
bool StackEmpty(StackLink S){
if (S == NULL)return true;
return false;
}
2.表达式求值
2.1算符判断优先值
typedef enum {da , xiao, deng, ERROR }pre;//枚举元素得是字母与数字组成的符号序列
typedef char ElemType;
typedef struct StackNode* StackLink;
//算符判断优先级
pre Precede(ElemType x,ElemType y){
if ((x == '('&&y == '#') || (x == ')'&&y == '(') || (x == '#'&&y == ')'))
return ERROR;
else if (x == '+'||x=='-'){
if (y == '+' || y == '-' || y == ')' || y == '#')
return da ;
else
return xiao ;
}
else if (x == '*'||x=='/'){
if (y == '+' || y == '-' || y == '*' || y == '/' || y == ')' || y == '#')
return da ;
else
return xiao ;
}
else if (x == '('){
if (y == ')')
return deng;
else
return xiao ;
}
else if (x == ')')
return da ;
else{
if (y == '#')
return deng;
else
return xiao ;
}
}
2.2优先级较大情况下的运算
//运算
ElemType Operate(ElemType a, ElemType x, ElemType b){
int c = a - '0',d = b - '0';
ElemType sum;
if (x == '+')
sum=(c + d + '0');
else if (x == '-')
sum=(c - d + '0');
else if (x == '*')
sum=(c*d + '0');
else
sum=(c / d + '0');
return sum;
}
2.3求值步骤(求值的主体函数)
注意
1.输入
——1.1.输入必须正确输入算符(运算符+界限符)和操作数,若输入非(算符和操作数),无法判断出(因为默认非算符的数都为操作数,否则无法保留两位数及以上的运算结果)
——1.2.输入的操作数必须为个位数,因为输入类型是字符,只能读取一个字符
——1.3.输入类型不能是int型,int无法写入算符
2表达式以#开头#结尾,开头的#用程序写,压入栈,结尾的#通过键盘输入
int EvaluateExpression(){
StackLink OPND, OPTR;
InitStack(OPND);//初始化OPND栈,寄存操作数或运算结果
InitStack(OPTR);//初始化OPTR栈,寄存算符
Push(OPTR, '#');//表达式起始符#入栈
ElemType p,theta,a,b;//p是键盘输入的,theta,a和b是算符和两个操作数(当输入为算符且优先级高时运算用:a theta b)
cin >> p;
while (p != '#'||GetHead(OPTR)!='#'){//表达式没有扫描完毕或OPTR的栈顶元素不为‘#’
//如果是算符就比较优先级(当出现优先级高的算符就运算,优先级低的就入栈)
if (p == '+' || p == '-' || p == '*' || p == '/' || p == '(' || p == ')'||p=='#')
switch (Precede(GetHead(OPTR),p))
{
case xiao://若优先级低,先把算符压入OPTR不计算
Push(OPTR, p);
cin >> p;
break;
case da://若优先级高,则进行运算,弹出OPTR栈顶的算符和OPND的两个数
//输入)的情况下优先级总是高【(则等于,可消掉括号】,前一个算符参与后运算不输入新p,)会循环到下一次和前一个算符再比较优先级直到遇到(
Pop(OPTR, theta);//p为弹出的算符
Pop(OPND, b);//先出的是后进的
Pop(OPND, a);//后出的是先进的
Push(OPND, Operate(a, theta, b));//运算结果压入OPND
break;
case deng://若优先级相等(只有()和##两种情况)则括号匹配成功,消去栈顶的(/#并且不让p入栈,写新p
//(##其实不会出现,当p为#且栈顶元素为#时就退出循环了已经)
Pop(OPTR, p);//p是弹出的废弃算符
cin >> p;
break;
default:
return -1;
}
//如果是操作数就入栈OPND
else{
Push(OPND, p);
cin >> p;
}
}
int sum = GetHead(OPND)-'0';
return sum;
}
主函数
int main(){
printf("结果是:%d",EvaluateExpression());
system("PAUSE");
return 0;
}