直接用两个栈计算方法子程序流程图
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<math.h>
#include<stdbool.h>
#define MAXSIZE 100
#define FIGUREMAXSIZE 20
int level(char op);
double calcValue(double od1, double od2, char tempop);
bool isOp(char ch);
//方法一:用两个栈直接计算
double calcDirect(char str[])
{
struct //用结构体创建操作符栈
{
char data[MAXSIZE];//用来存放操作符
int top;
} op;
struct //用结构体创建值栈
{
double data[MAXSIZE];//用来存放操作数
int top;
} od;
op.top = -1;//初始化操作符栈,令下标为-1
od.top = -1;//初始化值栈
char ch;
char tempStr[FIGUREMAXSIZE];//存储临时数组存储子串
double tempData;//存储将子串转化成double类型的数
double od1, od2; //存储值栈依次pop出来的操作数
char tempop;//存储操作符
int length = strlen(str);//计算str数组的长度
int i = 0;//声明字符数组循环索引
int j = 0;//声明数值子串索引
while(i < length)
{
ch = str[i];
if((ch >= '0' && ch <= '9') || ch == '.') //若为数值或小数点
{
j = 0;
memset(tempStr, 0, FIGUREMAXSIZE);
tempData = 0;
while((ch >= '0' && ch <= '9') || ch == '.') //截取子串
{
tempStr[j++] = ch;//赋值给临时数组
ch = str[++i];
}
tempStr[j] = '\0';
tempData = atof(tempStr);//将子串转化成double类型的数
od.data[++od.top] = tempData; //入值栈
}
else if(isOp(ch))//若为操作符
{
if(op.top == -1) //如果栈为空,直接进栈
{
op.data[++op.top] = ch; //进栈操作
}
else if(ch == '(') //如果为(,直接进栈
{
op.data[++op.top] = ch; //进栈操作
}
else if(ch == ')') //如果为),一直出栈直到遇到(
{
while(level(op.data[op.top]) != -1) //若栈顶元素不为(,进入while循环
{
od2 = od.data[od.top--];
od1 = od.data[od.top];
tempop = op.data[op.top--];
od.data[od.top] = calcValue(od1, od2, tempop); //计算出结果后入值栈
if(op.top == -1)break; //如果操作符栈为空,跳出循环
}
op.top--;//左括号pop出来
}
//如果所扫描的操作符优先等级比栈顶元素高,直接进栈
else if(level(ch) > level(op.data[op.top]))
{
op.data[++op.top] = ch; //进栈操作
}
else
{
//如果所扫描的操作符优先等级没有栈顶元素高,
//一直出栈直到比栈顶元素优先级高
while(level(ch) <= level(op.data[op.top]))
{
od2 = od.data[od.top--];
od1 = od.data[od.top];
tempop = op.data[op.top--];
od.data[od.top] = calcValue(od1, od2, tempop); //计算出结果后入值栈
if(op.top == -1)break; //如果操作符栈为空,跳出循环
}
op.data[++op.top] = ch; //比栈顶元素优先级高,入操作符栈
}
i++;//str下标加1,向后扫描
}
else//输入有误
{
printf("输入的表达式有误\n");
return 0;
}
}
while(op.top != -1) //扫描结束后如果操作符栈不为空,出栈直至为空
{
od2 = od.data[od.top--];
od1 = od.data[od.top];
tempop = op.data[op.top--];
od.data[od.top] = calcValue(od1, od2, tempop); //计算结果后入值栈
}
return od.data[od.top];//将结束后值栈中的数pop出来,即为计算结果
}
//函数实现中缀转后缀,将存储数学表达式的数组str传参进来,exp存储后缀表达式
void transfer(char str[], char exp[])
{
struct
{
char data[MAXSIZE];//用来存放操作符
int top;//数组下标
} op; //用结构体创建操作符栈
op.top = -1; //给操作符栈初始化,令下标为-1
char ch;
int i = 0, j = 0, tempi = 0;
while(ch != '\0')
{
ch = str[i]; //取str数组的第i个元素赋值给ch
if((ch >= '0' && ch <= '9') || ch == '.') //对数值操作
{
tempi = i; //若ch为数字或小数点,将其下标值赋给临时下标tempi
//依次向后扫描str数组,若一直为数字,跳入while循环
while((ch >= '0' && ch <= '9') || ch == '.')
{
tempi++;
exp[j] = ch; //将数字存入exp数组中
j++;
ch = str[tempi]; //取str数组中下标为tempi的元素赋给ch
}
exp[j] = '#';
j++;//用#做分隔符,将数值分隔开
i = tempi; //跳出循环,将此时的tempi赋给i,继续向后扫描
}
//对操作符操作
else if(isOp(ch))
{
if(ch == '(') //如果为(,直接进栈
{
op.top++;
op.data[op.top] = ch; //进栈操作
}
else if(ch == ')')
{
//如果为),一直出栈直到遇到(
while(level(op.data[op.top]) != -1) //若栈顶元素不为(,进入while循环
{
exp[j] = op.data[op.top]; //操作符出栈,存入exp数组中
op.top--;
j++;
if(op.top == -1)break; //如果栈为空,跳出循环
}
op.top--;//左括号pop出来
}
else if(op.top == -1) //如果栈为空,直接进栈
{
op.top++;
op.data[op.top] = ch; //进栈操作
}
//如果所扫描的操作符优先等级比栈顶元素高,直接进栈
else if(level(ch) > level(op.data[op.top]))
{
op.top++;
op.data[op.top] = ch; //进栈操作
}
else
{
//如果所扫描的操作符优先等级没有栈顶元素高,
//一直出栈直到比栈顶元素优先级高
while(level(ch) <= level(op.data[op.top]))
{
exp[j] = op.data[op.top]; //出栈存入exp数组中
op.top--;
j++;
if(op.top == -1)break; //如果栈为空,跳出循环
}
op.top++;
op.data[op.top] = ch; //比栈顶元素优先级高,入栈
}
i++;//str下标加1,向后扫描
}
else//输入有误
{
printf("输入的表达式有误\n");
return;
}
}
while(op.top != -1) //扫描结束后如果操作符栈不为空,出栈直至为空
{
exp[j] = op.data[op.top]; //出栈存入exp数组中
op.top--;
j++;
}
exp[j] = '\0'; //赋\0结束exp字符数组
}
//方法二:先将中缀表达式转换成后缀表达式,再进行计算
double calcTransfer(char exp[])
{
struct //用结构体创建值栈
{
double data[MAXSIZE]; //存储数值
int top;
} od;
double d; //声明d变量存储数值
double od1, od2; //存储值栈依次pop出来的操作数
char ch;
char tempch[20]; //声明临时数组存储子串
int j = 0, t;
int length = strlen(exp); //计算exp数组的长度
od.top = -1; //初始化值栈,令下标为-1
while(j < length)
{
ch = exp[j]; //提取exp中第j个元素
if(!isOp(ch))
{
//如果为数字或小数点
d = 0;
t = 0;
while((ch >= '0' && ch <= '9') || ch == '.')
{
tempch[t] = ch;
t++;//依次存放到临时数组中
j++;
ch = exp[j];
}
tempch[t] = '\0'; //结束tempch数组
d = atof(tempch); //将子串转化成double类型的数
od.top++;
od.data[od.top] = d; //入值栈
}
else //若为操作符,从值栈中pop出两个数计算
{
od2 = od.data[od.top];
od.top--;//先出栈的赋给od2
od1 = od.data[od.top]; //后出栈的赋给od1
od.data[od.top] = calcValue(od1, od2, ch); //计算出结果后再入栈
}
j++;
}
return od.data[od.top];//将结束后值栈中的数pop出来,即为计算结果
}
bool isOp(char ch)
{
if(ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '%' || ch == '(' || ch == ')' || ch == '^')
return true;
return false;
}
int level(char op)//判断操作符优先等级
{
if(op == '+' || op == '-')//若为+、-,等级为1
return 1;
else if(op == '*' || op == '/' || op == '%')
return 2; //若为*、/、%,等级为2
else if(op == '^')
return 3; //若为^,等级为3
else if(op == '(')
return -1 ; //若为(,等级为-1
else
return -3; //其他等级为-3;
}
double calcValue(double od1, double od2, char tempop) //计算
{
switch(tempop) {
case '+':
return od1 + od2;//计算加法
case '-':
return od1 - od2;//计算减法
case '*':
return od1 * od2;//计算乘法
case '/':
return od1 / od2;//计算除法
case '%':
return fmod(od1, od2); //求余
case '^':
return pow(od1, od2);//指数
}
return 0;
}
int main()
{
char str[MAXSIZE], exp[MAXSIZE];//定义str数组存放数学表达式
printf("输入算术表达式:\n");
gets(str); //从控制台输入算数表达式
printf("表达式为:%s\n", str);
printf("直接计算结果为:%lf\n", calcDirect(str));
transfer(str, exp);
printf("后缀表达式为:%s\n", exp);
printf("后缀转换计算结果为:%lf\n", calcTransfer(exp));
return 0;
}