四则运算表达的达成

需求分析

此次四则运算的要求如下:

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、输入答案并对比

不一样则输出正确答案并记错误一次。

测试程序

程序问题

随机生成算式较为复杂,我原本想要随机生成一个奇数数字作为字符串长度,在按照数字..符号..数字..符号..数字这样的顺序逐次生成算式。但是因为括号难以达成随机化,所以未能完成。

而且在验证答案时我选择的是将输入的答案,作为字符串,通过程序进行处理,再次进行计算,并把生成的答案存在一个结构体内,与原有的结构体答案进行对比。以此来判断对错,这样必然使程序的预算量变大。

除此之外图形化界面也没有制作。

原文地址:https://www.cnblogs.com/13070036dj/p/5296295.html