Arithmatic项目修改总结

Arithmatic项目修改总结

github仓库 arithmatic3.0

一. 修改介绍

修改后类图

1.关于类的合并

可以发现相比右边(旧)的类,左边(新)的类少了很多,这是我这次大改的思路体现

1. equation类和calculatresult类

将原来的计算结果和算式初始放在一起,定为一个equation类,将所有的界面输出取出去,这个类的明确定义就是针对整数算式,外部函数为获取算式和获取结果

class equation                //算式及结果
{
public:
	void initequation();         //初始算式
	double result();             //获取答案 
	
private:
	void clean();
	void printf();            //输出算式
	double mid();
	double high();
	double low();

	int digit_num,
		bracket_num,
		k1 = 1,         //目前位于数字数组位置
		k2 = 0,         //目前位于符号数组位置
		flag = 0,      //是否已出括号
		bracket_a,     //括号a位置
	    bracket_b,     //括号b位置
	    m[30];         //算式数字

	double result_0;      //结果
	char sign,
	     n[30];        //算式符号

};

有了对这个类的明确定义之后,思路就清晰很多了,实现了对类的封装,这里没有get和set方法,因为用户只需要知道算式是什么,答案是什么就够了,而原来的思路关于单独将计算拿出来做一个类的方案,我认为也很好,但不适合我现在来用,一是因为分数的计算不用这种方法计算,二是因为不太会用数据结构的方法,所以导致要将算式存到两个数组里,这样的话传参就会很麻烦,不如将他们放在一起。

2. language类和interface类

interface类定义:处理界面。三个公有函数分别代表处理界面的三个部分,开始,中间,和结束

class Interface       //界面
{
public:
	int first();           //开始界面(包括语言)
	void mid(int, double );      //每一道题的结果
	void finally();         //统计错题数

private:
	string *initlanguage();
	void languagelist();

	int equation_num,
		correct,    //一共对了
		wrong;      //一共错了
	string *l,      //init后语言指针
	       lan[10];
	char name[10],
		 str[100],//内容 
	     strp[100];
};

interface类,除了算式的输出,其他的都方法都在这个类里,由于language的作业是新的作业,而按理来说language类是界面输出的前提,所以这次大改我就将language中的两个方法放进interface类李作为私有函数了,用户也不需要知道我怎么获取语言的。

3. Message类的删除

本次大改最重要的原因之一就是要去掉这个静态类

class Message            //  全局数据
{
public:
	Message();
	void clean();
	static int  s1[20],  //算式数字数组
		equation_num,   //算式个数
		wrong,
		correct,
		bracket_num,
		bracket_a,
		bracket_b,
		digit_num;     //算式数字个数
	static char s2[20], //算式符号数组
		s[10][200];//语言字符串
	static double result;//计算结果
};

这个类本来是原来的全局变量类,将它删掉至少花了我2/3的时间,将所有的变量删除,安州他们本应该所在的类放进去,处理了一大堆因为没有了这些随时都可以调用的变量的问题,这是本次大改最核心的部分,结果是显而易见的,修改后我觉得程序的封装已经很完美了。

2.关于类的封装

这次我在去掉所有全局和静态变量的过程中,还顺便对类进行系统化的封装,就像我上面的类图一样,当然有很多方法是有参数的,类图中只是想表达有这么个方法,我将所有的属性定为private不是因为我觉得这样很好看,而是因为在对类有了明确的定义后,不需要在其他的类中调用本类的属性,就像上课讲的一样,这个节目的表演者不需要知道下一个节目的信息。而所有的类只会在主函数中被实例化。

#include "equation.h"
#include "Fraction.h"
#include "Interface.h"
int main()
{
    Interface inter;
	double result;

	int n = inter.first();                  //多少题
	srand((unsigned(time(NULL))));
	for (int j = 0;j < n;j++)
	{
		int judge = rand() % 5;       //出现分数运算的几率,目前1/5
		if (judge != 0)
		{
		    equation equ;
			equ.initequation();       //初始化整数算式
			result=equ.result();      //计算并返回答案
		}
		else
		{
		    Fraction fra;
			fra.initFraction();       //初始化分数算式
			result=fra.result();      //计算并返回答案
		}
		int answer;
		cin >>answer;
		inter.mid(answer,result);     //当前答案结果输出
		cout << endl;
	}
	inter.finally();
	return 0;
}

这个是修改前主函数和修改后的对比

3.计算方法改进

  1. 这次改动最重要的部分就是关于equation类的修改,本来计算方法并不是这次修改的规划之一,但是由于在去掉全局变量的过程中有了新的灵感,所以也花了很久的时间进行改进,效果也是显而易见的,由原来的两个类11个成员函数(6个公有)260行到现在的一个类7个成员函数(2个公有)160行,可以说我完成了一次很大很大的进步,这次修改也为我留下了大量修改一个大程序的经验(下面会介绍)。
  2. 关于计算方法,本来是第一次作业我的队友佘岳昕负责写的,我不太想弄明白她到底是怎么实现(我想这就是github分工合作的目的吧),所以在这次修改之前没有仔细了解这样的方法,但这次迫于修改的要求,我花了很久的时间将他们之间的关系弄明白,并减少了一个函数,现在的计算方法可以说比远了更易懂,也更清楚,这里我用了3个成员函数low,mid,high,和名字一样,它们代表着运算级别,结果就利用三个函数的互相调用实现。我知道用栈的方法很简单,但现在我还不想用,一是因为现在还没有学,而是因为用这样的方法很锻炼做题的思路,三是因为它是真正我自己写的代码,我是最了解的,这样复杂的调用关系能弄明白,也是对我解题思维的提升。

    这是个很简略的图,具体实现还得看代码

修改中的经验和感想

1.同步修改

在修改计算方法的时候我找到了一种可以避免失误,提高精确程度的方法,同步修改。因为目的是要将原来的修改得更完善,而不是重新写一份,所以说有很多地方需要注意不能随便定义,先上图。

  1. 首先现将原来的equation类复制出来,添加主函数和输出函数,然后按照做题的思路将代码写正确,这时候不用去想类中该如何实现。
  2. 将源代码在复制粘贴出来一份,同样添加输出函数,主函数,然后按照已经调试正确的代码修改,这时同步修改源代码,将源代码的主函数进行修改,改的更适合调试这样能做到每一步都很精确,虽然有点慢,但总比一起修改,最后找不到是哪里错了强。

2.变量的设定

  1. 变量定义的时候都要尽量定为0,不要有-1,1之类的,这样会给以后的调试造成很大的麻烦,这次我在用同步修改的时候就遇到了这种情况,愣是着了一个小时,最后没办法将两个程序一起调试才找到问题。
  2. 关于循环使用一个变量或数组,最容易忘记的就是将他们初始化,所以针对他们我写了个clean的函数,专门负责初始化这些变量,写在for里面。当然,在写代码的时候就一定要对这些变量进行标注,要不然下一次打开就忘了他们是什么意思的了。
  3. 以类的思想设定变量,也就是属性,可以大大减少传参的使用,并可以进行完美的封装。
posted @ 2017-05-16 13:01  土豆、  阅读(427)  评论(1编辑  收藏  举报