数据结构课程设计四则运算表达式求值(C语言版)
明人不说暗话,直接上百度网盘链接,输入提取码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");
}
数据结构课程设计四则运算表达式求值(C语言版)的更多相关文章
- 利用栈实现算术表达式求值(Java语言描述)
利用栈实现算术表达式求值(Java语言描述) 算术表达式求值是栈的典型应用,自己写栈,实现Java栈算术表达式求值,涉及栈,编译原理方面的知识.声明:部分代码参考自茫茫大海的专栏. 链栈的实现: pa ...
- 数据结构--栈的应用(表达式求值 nyoj 35)
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=35 题目: 表达式求值 时间限制:3000 ms | 内存限制:65535 KB描述 AC ...
- C语言之四则运算表达式求值(链栈)—支持浮点型数据,负数, 整型数据运算
运算符间的优先级关系: 链栈结构体定义: 数据域使用字符串长度为20的字符数组(故需要注意判断读取的字符串是运算符还是数值) 可支持浮点型数据,负数, 整型数据的运算 float EvaluateE ...
- 去空格的四则运算表达式求值-Java
笔记 package com.daidai.day4.demo1; import java.util.ArrayList; import java.util.Arrays; import java.u ...
- LeetCode150 逆波兰表达式求值
根据逆波兰表示法,求表达式的值. 有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说明: 整数除法只保留整数部分. 给定逆波兰表达式总是有效的.换句话说 ...
- 数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值
一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚, ...
- C++表达式求值(利用数据结构栈)
唉,刚刚用C++又又一次写了一个较完好的表达式求值程序,最后精简后程序还不到100行.这不经让我 想到了大一上学期刚学c语言时自己费了好大的劲,写了几百行并且功能还不是非常齐全(当时还不能计算有括号的 ...
- 表达式求值--数据结构C语言算法实现
这篇博客介绍的表达式求值是用C语言实现的,只使用了c++里面的引用. 数据结构课本上的一个例题,但是看起来很简单,实现却遇到了很多问题. 这个题需要构建两个栈,一个用来存储运算符OPTR, 一个用来存 ...
- 用Python3实现表达式求值
一.题目描述 请用 python3 编写一个计算器的控制台程序,支持加减乘除.乘方.括号.小数点,运算符优先级为括号>乘方>乘除>加减,同级别运算按照从左向右的顺序计算. 二.输入描 ...
随机推荐
- js数组操作-添加,删除
js 数组操作常用方法. push():在数组后面加入元素,并返回数组的长度 unshift():在数组前面加入元素,并返回数组的长度 pop()删除最后一个元素 shift()删除第一个元素 var ...
- Python第二十一天 fileinput模块
Python第二十一天 fileinput模块 fileinput模块 fileinput.input([files[, inplace[, backup[, bufsize[, mode[, ...
- Python 项目实践三(Web应用程序)第四篇
接着上节继续学习,本章将建立用户账户 Web应用程序的核心是让任何用户都能够注册账户并能够使用它,不管用户身处何方.在本章中,你将创建一些表单,让用户能够添加主题和条目,以及编辑既有的条目.你还将学习 ...
- C语言--解引用
昨天,在<C和指针>上面看到"解引用"这个名词,就好奇的去查了查. (下面是一个大一渣渣的理解,请各位朋友海涵,如果有漏洞或者补充希望前辈不吝指正.) 例: #incl ...
- Linux如何让进程在后台运行的三种方法详解
问题分析: 我们知道,当用户注销(logout)或者网络断开时,终端会收到 HUP(hangup)信号从而关闭其所有子进程.因此,我们的解决办法就有两种途径:要么让进程忽略 HUP 信号,要么让进程运 ...
- C# 给DateTime赋值正确方式
DateTime xxx = new DateTime(2007,1,1,21,21,21); string time = new DateTime(2007, 1, 1, 21, 21, 21).T ...
- Python day 7(1) 模块
一:模块 1 在Python中,一个.py文件就称之为一个模块(Module) 2 Python的好处,优点: a 提高了代码的可维护性 b 当一个模块编写完毕,就可以被其他地方引用.我们在编写程 ...
- MicroPython教程之TPYBoard开发板DIY红外寻迹小车
智能小车现在差不多是电子竞赛或者DIY中的主流了,寻迹,壁障,遥控什么的,相信大家也都见得很多了,这次就大家探讨一下寻迹小车的制作方法,不同于以往的是这次的程序不用C语言写,而是要使用python语言 ...
- table左边固定-底部横向滚动条
是日有需求,曾探讨过table表单头部.尾部固定不动,中间内容随着滚动条的滚动而变化. 整合资料之际,发现有很多表格,表单展现中,横向数据很多.很长,不方便查看. 则,横空霹雳出了,此款:table表 ...
- Java基础(五)-Java序列化与反序列化
.output_wrapper pre code { font-family: Consolas, Inconsolata, Courier, monospace; display: block !i ...