数据结构课程设计——四则运算表达式求值(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 }
欢迎交流,共同进步——