1.思路
 + 5#
还需要两个栈,S1栈用来存储数字,S2栈用来存储运算符号
初始化符号栈:将#字符入栈
S1 :NULL S2:#
第一次是一个数字2,则入数字栈S1
S1 :2 S2:#
第二次 字符 * ,当前符号栈S2顶元素是 #, 而当前的字符是*,然后在表中找到第7行第3列是一个 <号,则入符号栈 S2
S1 :2 S2:# *
第三次 字符是 ( , 当前符号栈S2顶元素是 * , 然后在表中找到第3行第5列是一个 < 号,则入符号栈 S2
S1 :2 S2:# * (
第四次 字符是 3 ,如果是数字的时候,需要做一个处理,这个数字可能是一个一位数字也可能是多位数字
> //当前字符是数字
if (Isoperator(ch) == -1) {
int x = ch - '0';
ch = str[index++];
//当前的数字是多位时候,不是1位
while (Isoperator(ch) == -1) {
x = x * 10 + ch - '0';
ch = str[index++];
}
PushD(&OPD, x);
}
所以这个代码不断循环判断,如果是数字则不断的合并,例如第一次是3,第二次是5,则3 * 10 + 5得35,如果还有数字 则35 * 10 + 数字,通过这样的循环方式合并数字
最终第四次得到一个35,将35入数字栈S1
S1 :2 35 S2:# * (
第五次,字符是 - ,当前符号栈S2是(, 然后在表中的第5行,第2列中是一个 < 号,则入符号栈S2
S1 :2 35 S2:# * ( -
第六次,字符是1,继续循环处理,最终得到一个10,将10入数字栈S1
S1 :2 35 10 S2:# * ( -
第七次, 字符是 ) , 符号栈S2顶元素是 - , 然后在表中的第2行第6列中是一个 > 号,则出栈
在数字栈S1中出两个元素 分别是35 和10,以及在符号栈S2中出一个符号 -
最终将35 - 10的结果是25入数字栈S1
S1 :2 25 S2:# * (
第八次字符是 ) ,符号栈S2顶元素是 ( , 然后在表中去找到第5行第6列,是等号,如果是等号则,符号栈S2则出栈一个元素
S1 :2 25 S2:# *
第九次字符是 + , 符号栈S2顶元素是 * , 然后在表中找到第3行第1列是一个 > 号,则出栈
在数字栈S1中出两个元素 分别是2 和25,以及在符号栈S2中出一个符号 *
最终2 * 25的结果是50入数字栈
S1 :50 S2:#
第十次字符是 + ,符号栈S2顶元素是 # ,然后在表中找到第7行第1列,是一个 < 号,则入符号栈S2
S1 :50 S2:# +
第十一次字符是5, 则入数字栈S1
S1 :50 5 S2:# +
第十二次字符是 #, 符号栈S2顶元素是+,然后在表中去找到第1行,第7列,是一个 > 号,则出栈
在数字栈S1中出两个元素 分别是50 和5,以及在符号栈S2中出一个符号 +
最终50 + 5得到的结果入数字栈
S1 :55 S2:#
第十三次字符是 #,符号栈S2顶元素是#,最终循环结束
//符号栈底不为# 或者表达式没有结束
while (ch != '#' || GetTopR(&OPR) != '#')
2. 部分代码解析
2.1基本框架介绍
typedef char ElemType_char;
ElemType_char op[7] = { '+', '-', '*', '/', '(', ')', '#' };
//输入字符是否属于符号集合,如果是,则返回它在数组中的位置,否则,返回-1
int Isoperator(ElemType_char ch) {
for (int i = 0; i < 7; i++) {
if (op[i] == ch) {
return i;
}
}
return -1;
}
while (ch != '#' || GetTopR(&OPR) != '#') {
//当前字符是数字
if (Isoperator(ch) == -1) {
}
else {
}
}
这个代码是基本的框架,当如果符号栈顶和表达式当前的字符,都是字符#时候就结束,当前字符不是在op数组中里面的运算符号时候,则返回-1,所以if判断,返回的值是-1的时候,则是数字,否则else就是符号
如果是数字则在if里面做操作,如果是符号,则在else里面做操作
2.2 对数字进行处理
ElemType_char op[7] = { '+', '-', '*', '/', '(', ')', '#' };
//输入字符是否属于符号集合,如果是,则返回它在数组中的位置,否则,返回-1
int Isoperator(ElemType_char ch) {
for (int i = 0; i < 7; i++) {
if (op[i] == ch) {
return i;
}
}
return -1;
}
//当前字符是数字
if (Isoperator(ch) == -1) {
int x = ch - '0';
ch = str[index++];
//当前的数字是多位时候,不是1位
while (Isoperator(ch) == -1) {
x = x * 10 + ch - '0';
ch = str[index++];
}
PushD(&OPD, x);
}
如果是数字,需要对数字做一个处理,这个数字可能是多位的,需要循环合并这么一个操作,最终把合并的结果进行入栈
2.3 对符号处理
typedef char ElemType_char;
ElemType_char op[7] = { '+', '-', '*', '/', '(', ')', '#' };
ElemType_char cmp[7][7] = {
{'>', '>', '<', '<','<', '>', '>'}, {'>', '>', '<', '<','<', '>', '>'},
{'>', '>', '>', '>','<', '>', '>'}, {'>', '>', '>', '>','<', '>', '>'},
{'<', '<', '<', '<','<', '=', '-'}, {'>', '>', '>', '>','-', '>', '>'},
{'<', '<', '<', '<','<', '-', '='}
};
//输入字符是否属于符号集合,如果是,则返回它在数组中的位置,否则,返回-1
int Isoperator(ElemType_char ch) {
for (int i = 0; i < 7; i++) {
if (op[i] == ch) {
return i;
}
}
return -1;
}
//比较两个运算符优先级
ElemType_char Compare(ElemType_char ch1, ElemType_char ch2) {
int row = Isoperator(ch1);
int col = Isoperator(ch2);
return cmp[row][col];
}
switch (Compare(GetTopR(&OPR), ch)) {
case '>' :{
ElemType_char theta;
ElemType_int a, b;
//数字栈 出栈两个数字 符号栈出栈一个符号
PopD(&OPD, &b);
PopD(&OPD, &a);
PopR(&OPR, &theta);
PushD(&OPD, Execute(a, theta, b));
}break;
case '=' : {
PopR(&OPR, &ch);
ch = str[index++];
}break;
case '<': {
PushR(&OPR, ch);
ch = str[index++];
}break;
}
当如果是符号,则这些代码就是在else执行,switch里面栈顶元素与当前字符进行处理,栈顶元素在一维数组op去查找对应的下标,表达式字符也在数组op去查找对应的下标,通过对应下标返回对应的二维数组的cmp的运算符号,从而执行对应case
3.整体代码
#include <stdio.h>
#include <stdlib.h>
#define STACK_INIT_SIZE 10
#define STACKINCREMENT 10
#define ARRAY_MAX 100
#define OVERFLOW -1
#define ERROR 0
#define OK 1
typedef int ElemType_int;
typedef char ElemType_char;
ElemType_char op[7] = { '+', '-', '*', '/', '(', ')', '#' };
ElemType_char cmp[7][7] = {
{'>', '>', '<', '<','<', '>', '>'}, {'>', '>', '<', '<','<', '>', '>'},
{'>', '>', '>', '>','<', '>', '>'}, {'>', '>', '>', '>','<', '>', '>'},
{'<', '<', '<', '<','<', '=', '-'}, {'>', '>', '>', '>','-', '>', '>'},
{'<', '<', '<', '<','<', '-', '='}
};
//数字栈结构
typedef struct StackD {
ElemType_int data;
}StackD;
//指向栈底和栈顶的指针结构
typedef struct {
StackD* base; //栈底指针
StackD* top; //栈顶指针
ElemType_int stacksize; //栈当前的大小
}SqStackD;
//符号栈结构
typedef struct StackR {
ElemType_char data;
}StackR;
//指向栈底和栈顶的指针结构
typedef struct {
StackR* base; //栈底指针
StackR* top; //栈顶指针
ElemType_int stacksize; //栈当前的大小
}SqStackR;
//初始化数字栈
ElemType_int InitStackD(SqStackD* S) {
//1.构造空栈 S
S->base = (StackD*)malloc(STACK_INIT_SIZE * sizeof(StackD));
//2.对构造的栈进行判断,是否构造成功
if (!S->base) { printf("栈内存分配失败!\n"); exit(OVERFLOW); }
//3.初始化top和base位置
S->top = S->base;
//4.初始化栈当前的大小
S->stacksize = STACK_INIT_SIZE;
//5.初始化成功 return OK
return OK;
}
//初始化符号栈
ElemType_int InitStackR(SqStackR* S) {
//1.构造空栈 S
S->base = (StackR*)malloc(STACK_INIT_SIZE * sizeof(StackR));
//2.对构造的栈进行判断,是否构造成功
if (!S->base) { printf("栈内存分配失败!\n"); exit(OVERFLOW); }
//3.初始化top和base位置
S->top = S->base;
//4.初始化栈当前的大小
S->stacksize = STACK_INIT_SIZE;
//5.初始化成功 return OK
return OK;
}
//获取数字栈顶
ElemType_int GetTopD(SqStackD* S, ElemType_int* e) {
//当栈不为空,则用e返回S的栈顶元素,并且返回OK,否则返回ERROR
if (S->base == S->top) return ERROR;
*e = (S->top - 1)->data;
return OK;
}
//获取符号栈顶
ElemType_int GetTopR(SqStackR* S, ElemType_char* e) {
//当栈不为空,则用e返回S的栈顶元素,并且返回OK,否则返回ERROR
if (S->base == S->top) return ERROR;
*e = (S->top - 1)->data;
return OK;
}
//数字入栈
ElemType_int PushD(SqStackD* S, ElemType_int e) {
//1.判断当前栈是否已经是满栈
if (S->top - S->base >= S->stacksize) {
printf("\n当前栈已经是满栈,需要重新分配内存!当前满内存大小为:%d\n", S->stacksize);
//2.当前栈内存以及满了,则扩展栈的空间
S->base = (StackD*)realloc(S->base, (S->stacksize + STACKINCREMENT) * sizeof(StackD));
// 2.1. 扩展内存后,判断该内存是否存在
if (!S->base) { printf("栈内存分配失败!\n"); exit(OVERFLOW); }
// 2.2. 重新设置top位置
S->top = S->base + S->stacksize;
// 2.3. 重新初始化栈的大小
S->stacksize = S->stacksize + STACKINCREMENT;
printf("当前栈已经成功分配%d个大小,最终当前栈的总大小为:%d\n\n", STACKINCREMENT, S->stacksize);
}
//3.元素入栈
(S->top++)->data = e;
//4. return OK
return OK;
}
//符号入栈
ElemType_int PushR(SqStackR* S, ElemType_char e) {
//1.判断当前栈是否已经是满栈
if (S->top - S->base >= S->stacksize) {
printf("\n当前栈已经是满栈,需要重新分配内存!当前满内存大小为:%d\n", S->stacksize);
//2.当前栈内存以及满了,则扩展栈的空间
S->base = (StackR*)realloc(S->base, (S->stacksize + STACKINCREMENT) * sizeof(StackR));
// 2.1. 扩展内存后,判断该内存是否存在
if (!S->base) { printf("栈内存分配失败!\n"); exit(OVERFLOW); }
// 2.2. 重新设置top位置
S->top = S->base + S->stacksize;
// 2.3. 重新初始化栈的大小
S->stacksize = S->stacksize + STACKINCREMENT;
printf("当前栈已经成功分配%d个大小,最终当前栈的总大小为:%d\n\n", STACKINCREMENT, S->stacksize);
}
//3.元素入栈
(S->top++)->data = e;
//4. return OK
return OK;
}
//数字出栈
ElemType_int PopD(SqStackD* S, ElemType_int* e) {
//当栈不为空,则用e返回S的栈顶元素,并且删除栈顶元素 返回OK
//否则返回 ERROR
if (S->top == S->base) { printf("当前栈为空栈,出栈失败!\n"); return ERROR; }
*e = (--S->top)->data;
return OK;
}
//符号出栈
ElemType_int PopR(SqStackR* S, ElemType_char* e) {
//当栈不为空,则用e返回S的栈顶元素,并且删除栈顶元素 返回OK
//否则返回 ERROR
if (S->top == S->base) { printf("当前栈为空栈,出栈失败!\n"); return ERROR; }
*e = (--S->top)->data;
return OK;
}
//获取数字栈顶
ElemType_int GetTopD(SqStackD* S) {
//当栈不为空,则用e返回S的栈顶元素,并且删除栈顶元素 返回OK
//否则返回 ERROR
if (S->top == S->base) { printf("当前栈为空栈,取栈顶失败!\n"); return ERROR; }
return (S->top - 1)->data;
}
//获取符号栈顶
ElemType_char GetTopR(SqStackR* S) {
//当栈不为空,则用e返回S的栈顶元素,并且删除栈顶元素 返回OK
//否则返回 ERROR
if (S->top == S->base) { printf("当前栈为空栈,取栈顶失败!\n"); return ERROR; }
return (S->top - 1)->data;
}
//判断数字栈是否为空 如果为空返回 OK 否则返回ERROR
ElemType_int StackEmptyD(SqStackD* S) {
if (S->top == S->base) return OK;
return ERROR;
}
///判断符号栈是否为空 如果为空返回 OK 否则返回ERROR
ElemType_int StackEmptyR(SqStackR* S) {
if (S->top == S->base) return OK;
return ERROR;
}
//输入字符是否属于符号集合,如果是,则返回它在数组中的位置,否则,返回-1
int Isoperator(ElemType_char ch) {
for (int i = 0; i < 7; i++) {
if (op[i] == ch) {
return i;
}
}
return -1;
}
//比较两个运算符优先级
ElemType_char Compare(ElemType_char ch1, ElemType_char ch2) {
int row = Isoperator(ch1);
int col = Isoperator(ch2);
return cmp[row][col];
}
//返回两个操作数运算的结果
ElemType_int Execute(ElemType_int a, ElemType_char theta, ElemType_int b) {
int result;
switch (theta)
{
case '+': result = a + b; break;
case '-' :result = a - b; break;
case '*' :result = a * b; break;
case '/' :result = a / b; break;
}
return result;
}
//输入表达式并求值
int EvaluateExp() {
//定义存储表达式数组
ElemType_char str[ARRAY_MAX] = { 0 };
//遍历下标
ElemType_int index = 0;
//临时变量 存储每一个字符
ElemType_char ch = 0;
//定义数字栈
SqStackD OPD;
//定义符号栈
SqStackR OPR;
//初始化数字栈
InitStackD(&OPD);
//初始化符号栈
InitStackR(&OPR);
//将 # 入符号栈
PushR(&OPR, '#');
printf("输入表达式:");
scanf("%s", str);
//获取第一个字符
ch = str[index++];
//符号栈底不为# 或者表达式没有结束
while (ch != '#' || GetTopR(&OPR) != '#') {
//当前字符是数字
if (Isoperator(ch) == -1) {
int x = ch - '0';
ch = str[index++];
//当前的数字是多位时候,不是1位
while (Isoperator(ch) == -1) {
x = x * 10 + ch - '0';
ch = str[index++];
}
PushD(&OPD, x);
}
//当前字符是符号
else {
switch (Compare(GetTopR(&OPR), ch)) {
case '>' :{
ElemType_char theta;
ElemType_int a, b;
//数字栈 出栈两个数字 符号栈出栈一个符号
PopD(&OPD, &b);
PopD(&OPD, &a);
PopR(&OPR, &theta);
PushD(&OPD, Execute(a, theta, b));
}break;
case '=' : {
PopR(&OPR, &ch);
ch = str[index++];
}break;
case '<': {
PushR(&OPR, ch);
ch = str[index++];
}break;
}
}
}
return GetTopD(&OPD);
}
int main() {
printf("运算结果为:%d\n", EvaluateExp());
system("pause");
return 0;
}