您的位置:首页 > 理论基础 > 数据结构算法

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

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

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

 下面的程序正常运行需要在本博客的文件中下在相应文件,否则无法正常使用哦。

1 /*本程序为四则运算表达式求值系统,用于计算带小括号的四则运算表达式求值。
2 具体算法:
3     先将字符串处理成操作单元(操作数或操作符),再利用栈根据四则运算
4 的运算法则进行计算,最后得出结果。*/
5
6 #include<stdio.h>
7 #include<ctype.h>
8 #include<stdlib.h>
9 #include<string.h>
10 #include<stdlib.h>
11 #include<ctype.h>
12
13 const int Expmax_length = 1001;//表达式最大长度,可根据适当情况调整
14 struct Ope_unit
15 {//定义操作单元
16     int    flag;//=1表示是操作数 =0表示是操作符 -1表示符号单元
17     char   oper;//操作符
18     double real;//操作数,为双精度浮点数
19 };
20
21 void Display();//菜单
22 void Instru(); //使用说明
23 int Check(char Exp_arry[]);
24 void Evalua(); //先调用Conver操作单元化,再调用Calculate函数计算结果并输出
25 int  Conver(struct Ope_unit Opeunit_arry[],char Exp_arry[]);//将字符串处理成操作单元
26 int  Isoper(char ch);//判断合法字符(+ - * / ( ) =)
27 int  Ope_Compar(char ope1,char ope2);//操作符运算优先级比较
28 double Calculate(struct Ope_unit Opeunit_arry[],int Opeunit_count,int &flag);//用栈计算表达式结果
29 double Four_arithm(double x,double y,char oper);//四则运算
30
31 int main()
32 {
33     int select;
34     while(1)
35     {
36         Display();
37         printf("请输入欲执行功能对应的数字:");
38         scanf("%d",&select);
39         printf("\n");
40         switch(select)
41         {
42             case   1: Evalua(); break;
43             case   2: Instru(); break;
44             case   0: return 0;
45             default : printf("无该数字对应的功能,请重新输入\n");
46                       system("pause");
47         }
48     }
49     return 0;
50 }
51
52 int Check(char Exp_arry[])
53 {//检查是否有非法字符,返回1表示不合法,0表示合法
54     int Explength=strlen(Exp_arry),i;
55     for(i=0;i<Explength;i++)
56     {
57         if(!Isoper(Exp_arry[i]) && Exp_arry[i] != '.' && !isdigit(Exp_arry[i]))
58         return 1;
59         if(isdigit(Exp_arry[i]))
60         {
61             int Dig_number=0,Cur_positoin=i+1;
62             while(isdigit(Exp_arry[Cur_positoin]) || Exp_arry[Cur_positoin]=='.')
63             {
64                 Dig_number++;
65                 Cur_positoin++;
66             }
67             if(Dig_number >= 16)//最多能够计算15位有效数字
68             return 1;
69         }
70     }
71     return 0;
72 }
73
74 void Evalua()
75 {//先调用Conver函数将字符串操作单元化,再调用Calculate函数计算结果并输出
76     char Exp_arry[Expmax_length];
77     int flag=0;//假设刚开始不合法,1表达式合法,0不合法
78     struct Ope_unit Opeunit_arry[Expmax_length];
79
80     getchar();//吃掉一个换行符
81     printf("请输入四则运算表达式,以=结尾:\n");
82     gets(Exp_arry);
83     flag=Check(Exp_arry);
84     if(flag)
85     printf("该表达式不合法!\n");
86     else
87     {
88         int Opeunit_count = Conver(Opeunit_arry,Exp_arry);
89         double        ans = Calculate(Opeunit_arry,Opeunit_count,flag);
90         if(flag)
91         {
92             printf("计算结果为:\n");
93             printf("%s%lf\n",Exp_arry,ans);
94         }
95         else
96         printf("该表达式不合法!\n");
97     }
98     system("pause");
99 }
100
101 int  Conver(struct Ope_unit Opeunit_arry[],char Exp_arry[])
102 {//将字符串操作单元化
103     int Explength=strlen(Exp_arry);
104     int i,Opeunit_count=0;
105     for(i=0;i<Explength;i++)
106     {
107         if(Isoper(Exp_arry[i]))//是操作符
108         {
109             Opeunit_arry[Opeunit_count].flag=0;
110             Opeunit_arry[Opeunit_count++].oper=Exp_arry[i];
111         }
112         else//是操作数
113         {
114             Opeunit_arry[Opeunit_count].flag=1;
115             char temp[Expmax_length];
116             int k=0;
117             for(; isdigit(Exp_arry[i]) || Exp_arry[i]=='.' ;i++)
118             {
119                 temp[k++]=Exp_arry[i];
120             }
121             i--;
122             temp[k]='\0';
123             Opeunit_arry[Opeunit_count].real=atof(temp);//将字符转化为浮点数
124
125             //负数
126             if(Opeunit_count == 1 && Opeunit_arry[Opeunit_count-1].flag==0
127             && Opeunit_arry[Opeunit_count-1].oper=='-')
128             {
129                 Opeunit_arry[Opeunit_count-1].flag = -1;
130                 Opeunit_arry[Opeunit_count].real  *= -1;
131             }// -9
132             if(Opeunit_count >= 2 && Opeunit_arry[Opeunit_count-1].flag==0
133             && Opeunit_arry[Opeunit_count-1].oper=='-' && Opeunit_arry[Opeunit_count-2].flag==0
134             && Opeunit_arry[Opeunit_count-2].oper !=')')
135             {
136                 Opeunit_arry[Opeunit_count-1].flag = -1;
137                 Opeunit_arry[Opeunit_count].real  *= -1;
138             }// )-9
139
140             //正数
141             if(Opeunit_count == 1 && Opeunit_arry[Opeunit_count-1].flag==0
142             && Opeunit_arry[Opeunit_count-1].oper=='+')
143             {
144                 Opeunit_arry[Opeunit_count-1].flag = -1;
145             }// +9
146             if(Opeunit_count >= 2 && Opeunit_arry[Opeunit_count-1].flag==0
147             && Opeunit_arry[Opeunit_count-1].oper=='+' && Opeunit_arry[Opeunit_count-2].flag==0
148             && Opeunit_arry[Opeunit_count-2].oper !=')')
149             {
150                 Opeunit_arry[Opeunit_count-1].flag = -1;
151             }// )+9
152             Opeunit_count++;
153         }
154     }
155     /*for(i=0;i<Opeunit_count;i++)
156     {//查看各操作单元是否正确,1是操作数,0是操作符
157         if(Opeunit_arry[i].flag == 1)
158         printf("该单元是操作数为:%lf\n",Opeunit_arry[i].real);
159         else if(Opeunit_arry[i].flag == 0)
160         printf("该单元是操作符为:%c\n",Opeunit_arry[i].oper);
161         else
162         printf("该单元是负号符为:%c\n",Opeunit_arry[i].oper);
163     }*/
164     return Opeunit_count;
165 }
166
167 double Calculate(struct Ope_unit Opeunit_arry[],int Opeunit_count,int &flag)
168 {//根据运算规则,利用栈进行计算
169     int i,dS_pointer=0,oS_pointer=0;//dS_pointer为操作数栈顶指示器,oS_pointer为操作符栈顶指示器
170     double Dig_stack[Expmax_length];//操作数栈(顺序存储结构)
171     char   Ope_stack[Expmax_length];//操作符栈
172
173     for(i=0;i<Opeunit_count-1;i++)
174     {
175         if( Opeunit_arry[i].flag != -1 )
176         {
177             if(Opeunit_arry[i].flag)//是操作数
178             {
179                 Dig_stack[dS_pointer++]=Opeunit_arry[i].real;//入操作数栈
180                 //printf("%lf\n",Digit[dS_pointer-1]);
181             }
182             else//是操作符 + - * / ( )
183             {
184                 //操作符栈为空或者左括号 入栈
185                 if(oS_pointer==0 || Opeunit_arry[i].oper=='(')
186                 {
187                     Ope_stack[oS_pointer++]=Opeunit_arry[i].oper;
188                     //printf("%oS_pointer\Ope_u_count",Operator[oS_pointer-1]);
189                 }
190                 else
191                 {
192                     if(Opeunit_arry[i].oper==')')//是右括号将运算符一直出栈,直到遇见左括号
193                     {
194                         oS_pointer--;//指向栈顶
195                         dS_pointer--;//指向栈顶
196                         while(Ope_stack[oS_pointer] != '(' && oS_pointer != 0)
197                         {
198                             Dig_stack[dS_pointer-1] = Four_arithm(Dig_stack[dS_pointer-1],Dig_stack[dS_pointer],
199                             Ope_stack[oS_pointer--]);//oS_pointer--为操作符出栈
200
201                             dS_pointer--;//前一个操作数出栈
202                             //printf("操作数栈顶元素等于%lf\n",Digit[dS_pointer]);
203                         }
204                         oS_pointer--;//左括号出栈
205
206                         oS_pointer++;//恢复指向栈顶之上
207                         dS_pointer++;
208                     }
209                     else if(Ope_Compar(Opeunit_arry[i].oper,Ope_stack[oS_pointer-1]))//和栈顶元素比较
210                      {
211                          Ope_stack[oS_pointer++]=Opeunit_arry[i].oper;
212                          //printf("%oS_pointer\Ope_u_count",Operator[oS_pointer-1]);
213                     }
214                      else//运算符出栈,再将该操作符入栈
215                      {
216                          oS_pointer--;//指向栈顶
217                          dS_pointer--;//指向栈顶
218                         while(Ope_Compar(Opeunit_arry[i].oper,Ope_stack[oS_pointer])==0 && oS_pointer != -1)
219                         {//当前操作符比栈顶操作符优先级高
220                             Dig_stack[dS_pointer-1]=Four_arithm(Dig_stack[dS_pointer-1],Dig_stack[dS_pointer],
221                             Ope_stack[oS_pointer--]);
222                             dS_pointer--;
223                             //printf("操作数栈顶元素等于%lf\n",Digit[dS_pointer]);
224                         }
225                         oS_pointer++;//恢复指向栈顶之上
226                         dS_pointer++;
227                         Ope_stack[oS_pointer++]=Opeunit_arry[i].oper;
228                     }
229                 }
230             }
231         }
232     }
233     /*for(i=0;i<oS_pointer;i++)
234         printf("操作符栈%oS_pointer\Ope_u_count",Operator[i]);
235     for(i=0;i<dS_pointer;i++)
236         printf("操作数栈%lf\n",Digit[i]);*/
237     oS_pointer--;//指向栈顶元素
238     dS_pointer--;//指向栈顶元素
239     while(oS_pointer != -1)
240     {
241         Dig_stack[dS_pointer-1]=Four_arithm(Dig_stack[dS_pointer-1],Dig_stack[dS_pointer],
242         Ope_stack[oS_pointer--]);//oS_pointer--为操作符出栈
243         dS_pointer--;//前一个操作数出栈
244         //printf("操作数栈顶元素为%lf\Ope_u_count",Digit[dS_pointer]);
245     }
246     //printf("%dS_pointer,%dS_pointer\n",oS_pointer,dS_pointer);
247     if(oS_pointer==-1 && dS_pointer==0)
248         flag=1;//为1表示表达式合法
249     return Dig_stack[0];
250 }
251
252 int  Ope_Compar(char ope1,char ope2)
253 {//操作符运算优先级比较
254     char list[]={"(+-*/"};
255     int map[5][5]={//先行后列,行比列的运算级优先级低为0,高为1
256     //        ( + - * /
257     /*  (  */ 1,0,0,0,0,
258     /*  +  */ 1,0,0,0,0,
259     /*  -  */ 1,0,0,0,0,
260     /*  *  */ 1,1,1,0,0,
261     /*  /  */ 1,1,1,0,0 };
262     int i,j;
263     for(i=0;i<5;i++)
264         if(ope1==list[i]) break;
265     for(j=0;j<5;j++)
266         if(ope2==list[j]) break;
267     return map[i][j];
268 }
269
270 double Four_arithm(double x,double y,char oper)
271 {//四则运算
272     switch(oper)//保证不含其它运算符
273     {
274         case '+': return x+y;
275         case '-': return x-y;
276         case '*': return x*y;
277         case '/': return x/y;//y不能为0
278         default : return 0;
279     }
280 }
281
282 int  Isoper(char ch)
283 {//判断合法字符  + - * / ( ) =
284     if(ch=='+' || ch=='-' || ch=='*' || ch=='/' || ch=='(' || ch==')' || ch=='=')
285         return 1;
286     return 0;
287 }
288
289 void Display()
290 {//打印菜单
291     system("cls");
292     printf("/******************************************************************************/\n");
293     printf("\t\t       欢迎使用本四则运算表达式求值系统\n");
294     printf("\n\t说明:建议请您先阅读使用说明,再输入相应的数字进行操作,谢谢配合!\n");
295     printf("\n\t\t1 四则运算表达式求值\n");
296     printf("\n\t\t2 使用说明\n");
297     printf("\n\t\t0 退出\n");
298     printf("/******************************************************************************/\n");
299 }
300
301 void Instru()
302 {//打印使用说明
303     FILE *fp;
304     char ch;
305     if( ( fp=fopen("使用说明.txt","r") ) == NULL)
306     {
307         printf("文件打开失败!\n");
308         exit(0);
309     }
310     for(; (ch = fgetc(fp)) != EOF; )
311         putchar(ch);
312     fclose(fp);
313     printf("\n");
314     system("pause");
315 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: