数据结构课程设计四则运算表达式求值(C语言版)

时间:2023-03-08 17:49:32

  明人不说暗话,直接上百度网盘链接,输入提取码z3fy即可下载。

文件中包含程序,程序运行文件,设计报告和测试样例,应有尽有,欢迎小伙伴们在中下载使用。

本课程设计为四则运算表达式求值,用于带小括号的一定范围内正负数的四则运算标准(中缀)表达式的求值。
注意事项:
    1、请保证输入的四则表达式的合法性。输入的中缀表达式中只能含有英文符号“+”、“-”、“*”、“/”、“(”、“)”、“=”、数字“0”到“9”以及小数点“.”,输入“=”表示输入结束。例如9+(3-1)*3.567+10/2=,特别是请勿输入多余空格和中文左右括号。
    2、输入的中缀表达式默认限定长度是1001,可根据具体情况调整字符串数组的长度。
    3、请保证输入的操作数在double数据类型范围内,单个数字有效数字长度不可超过15位。本课程设计中操作数是C语言中的双精度浮点数类型。
    4、本课程设计中的运算数可以是负数,另外如果是正数可直接省略“+”号(也可带“+”号)。

 下面的程序正常运行需要在上面的百度网盘中下载相应文件,否则无法正常使用哦。

 /*本程序为四则运算表达式求值系统,用于计算带小括号的四则运算表达式求值。
具体算法:
先将字符串处理成操作单元(操作数或操作符),再利用栈根据四则运算
的运算法则进行计算,最后得出结果。*/ #include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h> const int Expmax_length = ;//表达式最大长度,可根据适当情况调整
struct Ope_unit
{//定义操作单元
int flag;//=1表示是操作数 =0表示是操作符 -1表示符号单元
char oper;//操作符
double real;//操作数,为双精度浮点数
}; void Display();//菜单
void Instru(); //使用说明
int Check(char Exp_arry[]);
void Evalua(); //先调用Conver操作单元化,再调用Calculate函数计算结果并输出
int Conver(struct Ope_unit Opeunit_arry[],char Exp_arry[]);//将字符串处理成操作单元
int Isoper(char ch);//判断合法字符(+ - * / ( ) =)
int Ope_Compar(char ope1,char ope2);//操作符运算优先级比较
double Calculate(struct Ope_unit Opeunit_arry[],int Opeunit_count,int &flag);//用栈计算表达式结果
double Four_arithm(double x,double y,char oper);//四则运算 int main()
{
int select;
while()
{
Display();
printf("请输入欲执行功能对应的数字:");
scanf("%d",&select);
printf("\n");
switch(select)
{
case : Evalua(); break;
case : Instru(); break;
case : return ;
default : printf("无该数字对应的功能,请重新输入\n");
system("pause");
}
}
return ;
} int Check(char Exp_arry[])
{//检查是否有非法字符,返回1表示不合法,0表示合法
int Explength=strlen(Exp_arry),i;
for(i=;i<Explength;i++)
{
if(!Isoper(Exp_arry[i]) && Exp_arry[i] != '.' && !isdigit(Exp_arry[i]))
return ;
if(isdigit(Exp_arry[i]))
{
int Dig_number=,Cur_positoin=i+;
while(isdigit(Exp_arry[Cur_positoin]) || Exp_arry[Cur_positoin]=='.')
{
Dig_number++;
Cur_positoin++;
}
if(Dig_number >= )//最多能够计算15位有效数字
return ;
}
}
return ;
} void Evalua()
{//先调用Conver函数将字符串操作单元化,再调用Calculate函数计算结果并输出
char Exp_arry[Expmax_length];
int flag=;//假设刚开始不合法,1表达式合法,0不合法
struct Ope_unit Opeunit_arry[Expmax_length]; getchar();//吃掉一个换行符
printf("请输入四则运算表达式,以=结尾:\n");
gets(Exp_arry);
flag=Check(Exp_arry);
if(flag)
printf("该表达式不合法!\n");
else
{
int Opeunit_count = Conver(Opeunit_arry,Exp_arry);
double ans = Calculate(Opeunit_arry,Opeunit_count,flag);
if(flag)
{
printf("计算结果为:\n");
printf("%s%lf\n",Exp_arry,ans);
}
else
printf("该表达式不合法!\n");
}
system("pause");
} int Conver(struct Ope_unit Opeunit_arry[],char Exp_arry[])
{//将字符串操作单元化
int Explength=strlen(Exp_arry);
int i,Opeunit_count=;
for(i=;i<Explength;i++)
{
if(Isoper(Exp_arry[i]))//是操作符
{
Opeunit_arry[Opeunit_count].flag=;
Opeunit_arry[Opeunit_count++].oper=Exp_arry[i];
}
else//是操作数
{
Opeunit_arry[Opeunit_count].flag=;
char temp[Expmax_length];
int k=;
for(; isdigit(Exp_arry[i]) || Exp_arry[i]=='.' ;i++)
{
temp[k++]=Exp_arry[i];
}
i--;
temp[k]='\0';
Opeunit_arry[Opeunit_count].real=atof(temp);//将字符转化为浮点数 //负数
if(Opeunit_count == && Opeunit_arry[Opeunit_count-].flag==
&& Opeunit_arry[Opeunit_count-].oper=='-')
{
Opeunit_arry[Opeunit_count-].flag = -;
Opeunit_arry[Opeunit_count].real *= -;
}// -9
if(Opeunit_count >= && Opeunit_arry[Opeunit_count-].flag==
&& Opeunit_arry[Opeunit_count-].oper=='-' && Opeunit_arry[Opeunit_count-].flag==
&& Opeunit_arry[Opeunit_count-].oper !=')')
{
Opeunit_arry[Opeunit_count-].flag = -;
Opeunit_arry[Opeunit_count].real *= -;
}// )-9 //正数
if(Opeunit_count == && Opeunit_arry[Opeunit_count-].flag==
&& Opeunit_arry[Opeunit_count-].oper=='+')
{
Opeunit_arry[Opeunit_count-].flag = -;
}// +9
if(Opeunit_count >= && Opeunit_arry[Opeunit_count-].flag==
&& Opeunit_arry[Opeunit_count-].oper=='+' && Opeunit_arry[Opeunit_count-].flag==
&& Opeunit_arry[Opeunit_count-].oper !=')')
{
Opeunit_arry[Opeunit_count-].flag = -;
}// )+9
Opeunit_count++;
}
}
/*for(i=0;i<Opeunit_count;i++)
{//查看各操作单元是否正确,1是操作数,0是操作符
if(Opeunit_arry[i].flag == 1)
printf("该单元是操作数为:%lf\n",Opeunit_arry[i].real);
else if(Opeunit_arry[i].flag == 0)
printf("该单元是操作符为:%c\n",Opeunit_arry[i].oper);
else
printf("该单元是负号符为:%c\n",Opeunit_arry[i].oper);
}*/
return Opeunit_count;
} double Calculate(struct Ope_unit Opeunit_arry[],int Opeunit_count,int &flag)
{//根据运算规则,利用栈进行计算
int i,dS_pointer=,oS_pointer=;//dS_pointer为操作数栈顶指示器,oS_pointer为操作符栈顶指示器
double Dig_stack[Expmax_length];//操作数栈(顺序存储结构)
char Ope_stack[Expmax_length];//操作符栈 for(i=;i<Opeunit_count-;i++)
{
if( Opeunit_arry[i].flag != - )
{
if(Opeunit_arry[i].flag)//是操作数
{
Dig_stack[dS_pointer++]=Opeunit_arry[i].real;//入操作数栈
//printf("%lf\n",Digit[dS_pointer-1]);
}
else//是操作符 + - * / ( )
{
//操作符栈为空或者左括号 入栈
if(oS_pointer== || Opeunit_arry[i].oper=='(')
{
Ope_stack[oS_pointer++]=Opeunit_arry[i].oper;
//printf("%oS_pointer\Ope_u_count",Operator[oS_pointer-1]);
}
else
{
if(Opeunit_arry[i].oper==')')//是右括号将运算符一直出栈,直到遇见左括号
{
oS_pointer--;//指向栈顶
dS_pointer--;//指向栈顶
while(Ope_stack[oS_pointer] != '(' && oS_pointer != )
{
Dig_stack[dS_pointer-] = Four_arithm(Dig_stack[dS_pointer-],Dig_stack[dS_pointer],
Ope_stack[oS_pointer--]);//oS_pointer--为操作符出栈 dS_pointer--;//前一个操作数出栈
//printf("操作数栈顶元素等于%lf\n",Digit[dS_pointer]);
}
oS_pointer--;//左括号出栈 oS_pointer++;//恢复指向栈顶之上
dS_pointer++;
}
else if(Ope_Compar(Opeunit_arry[i].oper,Ope_stack[oS_pointer-]))//和栈顶元素比较
{
Ope_stack[oS_pointer++]=Opeunit_arry[i].oper;
//printf("%oS_pointer\Ope_u_count",Operator[oS_pointer-1]);
}
else//运算符出栈,再将该操作符入栈
{
oS_pointer--;//指向栈顶
dS_pointer--;//指向栈顶
while(Ope_Compar(Opeunit_arry[i].oper,Ope_stack[oS_pointer])== && oS_pointer != -)
{//当前操作符比栈顶操作符优先级高
Dig_stack[dS_pointer-]=Four_arithm(Dig_stack[dS_pointer-],Dig_stack[dS_pointer],
Ope_stack[oS_pointer--]);
dS_pointer--;
//printf("操作数栈顶元素等于%lf\n",Digit[dS_pointer]);
}
oS_pointer++;//恢复指向栈顶之上
dS_pointer++;
Ope_stack[oS_pointer++]=Opeunit_arry[i].oper;
}
}
}
}
}
/*for(i=0;i<oS_pointer;i++)
printf("操作符栈%oS_pointer\Ope_u_count",Operator[i]);
for(i=0;i<dS_pointer;i++)
printf("操作数栈%lf\n",Digit[i]);*/
oS_pointer--;//指向栈顶元素
dS_pointer--;//指向栈顶元素
while(oS_pointer != -)
{
Dig_stack[dS_pointer-]=Four_arithm(Dig_stack[dS_pointer-],Dig_stack[dS_pointer],
Ope_stack[oS_pointer--]);//oS_pointer--为操作符出栈
dS_pointer--;//前一个操作数出栈
//printf("操作数栈顶元素为%lf\Ope_u_count",Digit[dS_pointer]);
}
//printf("%dS_pointer,%dS_pointer\n",oS_pointer,dS_pointer);
if(oS_pointer==- && dS_pointer==)
flag=;//为1表示表达式合法
return Dig_stack[];
} int Ope_Compar(char ope1,char ope2)
{//操作符运算优先级比较
char list[]={"(+-*/"};
int map[][]={//先行后列,行比列的运算级优先级低为0,高为1
// ( + - * /
/* ( */ ,,,,,
/* + */ ,,,,,
/* - */ ,,,,,
/* * */ ,,,,,
/* / */ ,,,, };
int i,j;
for(i=;i<;i++)
if(ope1==list[i]) break;
for(j=;j<;j++)
if(ope2==list[j]) break;
return map[i][j];
} double Four_arithm(double x,double y,char oper)
{//四则运算
switch(oper)//保证不含其它运算符
{
case '+': return x+y;
case '-': return x-y;
case '*': return x*y;
case '/': return x/y;//y不能为0
default : return ;
}
} int Isoper(char ch)
{//判断合法字符 + - * / ( ) =
if(ch=='+' || ch=='-' || ch=='*' || ch=='/' || ch=='(' || ch==')' || ch=='=')
return ;
return ;
} void Display()
{//打印菜单
system("cls");
printf("/******************************************************************************/\n");
printf("\t\t 欢迎使用本四则运算表达式求值系统\n");
printf("\n\t说明:建议请您先阅读使用说明,再输入相应的数字进行操作,谢谢配合!\n");
printf("\n\t\t1 四则运算表达式求值\n");
printf("\n\t\t2 使用说明\n");
printf("\n\t\t0 退出\n");
printf("/******************************************************************************/\n");
} void Instru()
{//打印使用说明
FILE *fp;
char ch;
if( ( fp=fopen("使用说明.txt","r") ) == NULL)
{
printf("文件打开失败!\n");
exit();
}
for(; (ch = fgetc(fp)) != EOF; )
putchar(ch);
fclose(fp);
printf("\n");
system("pause");
}