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

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

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

    本课程设计为四则运算表达式求值,用于带小括号的一定范围内正负数的四则运算标准(中缀)表达式的求值。
注意事项:
    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 }

 

posted @ 2018-01-24 23:17  Reqaw  阅读(7881)  评论(0编辑  收藏  举报