四则运算表达的达成
需求分析
此次四则运算的要求如下:
1.由txt文档中逐行导入算式,算式中实型用分数形式表示。
2.算式中应涵盖加减乘除括号,真假分数,以及长度大于10的超长算式。
3.判断用户输入算式的值是否正确,如正确则提示,错误则显示正确答案。
程序设计
将四则运算的求解拆分成如下问题:
1、读入中缀表达式算式
2、中缀表达式转后缀
3、后缀表达式求值
4、对结果进行化简
5、输入答案并对比
程序实现
前三步在上学期数据结构课程中已经完成,此处只大概说明原理
1、读入中缀表达式算式
从txt分行读取数据,因为每次计算都是一行,所以在循环中文件不关闭,循环结束才关闭。
int getchars() { // VC++6.0 if(NULL == fp) { printf("failed to open dos.txt\n"); return 0; } if(!feof(fp)) { memset(infix, 0, sizeof(infix)); fscanf(fp,"%s",infix); // 包含了\n printf("\n%s\n", infix); return 1; }
在此处进行预处理,将多位数字和各位数字区分,防止产生歧义
void pretreatment(char *str){ int i,j,numberFlag; char temp[3]; char number[10]; count=0; numberFlag=0; for(j=0,i=0;str[i];i++){ if(isDigital(str[i])==0){ if(numberFlag==1){ number[j]=0; strcpy(expression[count++],number); j=0; numberFlag=0; } if(str[i]!=' '){ temp[0]=str[i];temp[1]=0; strcpy(expression[count++],temp); } } else { numberFlag=1; number[j++]=str[i]; } }
2、中缀表达式转后缀
根据符号不同,进行不同的压栈和出栈操作,得出后缀表达式
3、后缀表达式求值
从栈中取字符,根据取出符号的不同,将取出的数进行相应的运算再入栈保存
在此步骤中考虑到本次程序要求结果保存成为分数,而上学期则没有要求,所以应当对数据的格式进行修改。建立结构体以方便记录数字的分子和分母。
struct fra{ char str[10];//为了在栈中记录符号,所以包括数字全部用char记录 double up;//分子 double down;//分母 };
这样在计算结果时,读到同样的符号时,只需要改变计算的方法,就可以在程序不需要大的改动的前提下,增加分数,如下改动:
if(str[i][0]=='+') { nc.down=nb.down*na.down; nc.up=nb.up*na.down+na.up*nb.down; } else if(str[i][0]=='-') { nc.down=nb.down*na.down; nc.up=nb.up*na.down-na.up*nb.down; } else if(str[i][0]=='*') { nc.up=nb.up*na.up; nc.down=nb.down*na.down; } else if(str[i][0]=='/') { nc.down=nb.down*na.up; nc.up=nb.up*na.down; }
4、对结果进行化简
int gcd(int a,int b) { //最大公约数 if(b == 0) return a; else return gcd(b,a % b); }
求出答案分子、分母的最大公约数并分别用分子、分母除以该数。
5、输入答案并对比
不一样则输出正确答案并记错误一次。
测试程序
程序问题
随机生成算式较为复杂,我原本想要随机生成一个奇数数字作为字符串长度,在按照数字..符号..数字..符号..数字这样的顺序逐次生成算式。但是因为括号难以达成随机化,所以未能完成。
而且在验证答案时我选择的是将输入的答案,作为字符串,通过程序进行处理,再次进行计算,并把生成的答案存在一个结构体内,与原有的结构体答案进行对比。以此来判断对错,这样必然使程序的预算量变大。
除此之外图形化界面也没有制作。