此部分仅供笔者方便读代码而做的代码结构分析,若要看总结性的代码复审分析请从“1. General 开始看起”
0.1 变量结构
struct fraction 分数结构(其实包括了整数的结构)f={0,1,1}整数1
int mol 分子
int deo 分母
int i 整数部分(整数时代表整数,分数时代表带分数的整数部分)
struct dat 数字结构 : gap, first_num, my_answer[10000], your_answer[10000],level(d{0,f}整数1)
int type = 0整数,1真分数,2带分数
struct fraction d_val 分数结构
struct title 表达式结构 : my_title
int order[4] ?计数工具?
int num; 一个表达式中操作符的个数?
int op[4]; 操作符的数字表示
int kh[2]; 前括号在哪个数运算符前后
struct dat data[4]; 数字结构组,一个表达式中最多4个数字
struct dat result; 一个表达式的运算结果,是一个数字结构
int num_title 表达式个数
0.2 定义基本函数
虽然只有一行代码但简洁明了,注释的意思也非常明确,只有函数名可能有些不太合适,用的是拼音的缩写。
int gys(int x,int y)
分析同上
仅从这个函数上看,没有考虑到和处理分母为0的情况。(已处理小于0的情况)在约分后返回的过程中没有考虑到当分子分母一样时是个整数的情况,而且这里的dat结构中的type按照前文注释应该为1或2(真分数、带分数),0表示是整数。但是能在这个难度不小的题目下还能考虑到月份的情况是比较难得的。
struct fraction f={0,fz,fm};
struct dat re={0,f};
输入变量为分子1、分母1、分子2、分母2,局部变量V是2个分母的公倍数(但个人觉得这一步冗余了,反正最后要约分的),首先给这个想法点赞,依然是考虑到了约分的问题,很细心。但个人认为V这里应该加一下注释(程序本身的注释量偏少),之后的运算部分应该没什么逻辑错误,加法没有什么需要特别考虑的地方。然后就是变量名的问题,还是存在拼音简写命名的现象。
struct dat add(int a,int b,int c,int d) /定义加法函数/
{
int u1,u2,v=gbs(b,d),fz1,fm1;
u1=v/ba;
u2=v/dc;
fz1=u1+u2;
fm1=v;
return yuefen(fz1,fm1);
}
没有什么问题,乘法不需要考虑太多。
除了加法函数中出现的问题,减法程序还有一个问题是差为0的情况(差小于0的时候在约分函数中进行了处理)。
没有考虑除数为0的情况,其他应该没什么。
0.3 正文过程
给两个数和操作符,进行运算。
输入的限制范围和需要的表达式个数。中间调用了ceil函数(向上取整,这个函数我之前不知道,这次确实学到了)。
检验分母不能为0。为0时返回false。
输入一个表达式t,num是一个表达式中数字的个数,最多不超过3个。先把所有的符号移到temp数组中,o记录的是相应符号原来的优先级?判断是否有括号:这里判断title结构中的order是用来记录后括号位置的?这里暂时还没有看出来在这里程序用了一个循环,但是我认为不是太必要,直接用加减法就可以实现)
没太看懂,感觉应该是给出表达式的,算出结果的过程。但是没有注释我也只能猜,
这个函数是进行data结构中类型的转换,但是好像顺序反了。程序中是先判断分子对分母取余是否为0,为0再考虑分子除以分母是否为0;但个人认为顺序应该反过来,否则分子为0的情况会被归入真分数中(当然如果本身是这么设计的也可)
把数字打印出来
给一个表达式,将它打印出来,在每个数字被打印之前需要调用translation进行转换
ID是随机数?用来确定数字、括号位置?
1.1 程序的功效
能够生成规定数目、规定范围的四则运算表达式,并同时生成答案。同时能够分辨出分数中分子分母可约分的问题并化简到最简形式。但目前观测来看为实现的功能有:对做出的答案进行批改,以及实现真正的随机数。(短时间内生成的随机数多数重复)
1.2 代码结构
从结构上来讲整体还是比较好的。基本上所有的循环长度都不是很长,格式也是相当规范。但还是有一些问题,举例说明,在代码中间count函数中有一部分套用函数和结构太多,加上没有注释,确实认不太清要表达的内容。此外,这个程序和我的代码习惯还是很像的,比如左大括号换行打,所以阅读起来基本上没有语法上的障碍。但是该程序中用到了一些我不太熟悉的库函数,在复审的过程中也是受益匪浅。
re=operation(&(t->data[t->order[0]-1]),&(t->data[t->order[0]]),t->op[t->order[0]-1]);
1.3 代码风格
这里是我重点要说的内容,整个代码的格式缩进是非常符合要求的,整体代码的结构很好。我认为,问题有三点:第一,注释!注释!注释!注释不清而且多用拼音很容易造成误解和疑惑,代码很难看懂;第二,是整个程序的问题。这个其实有点挑刺了。也许是因为这个程序是用C写的,所以所有的程序都放在一个页面上,这样在查看函数调用的时候就很不方便,需要疯狂地使用滚动条;第三,就是对各种变量以及函数的命名,很多使用了拼音简写以及不明含义的英文名,这样的代码读起来会很不方便,这一点在前面的部分已经能体会到了。
然而还是要澄清一下,以上代码风格的描述已经是我鸡蛋里挑骨头了,程序整体上真的非常好,对库函数的运用非常娴熟老练。
2.1 输入是否符合标准
通过对部分代码的阅读,在每个函数中有很多可能出现的不符合输入标准的数据,但是在函数中基本上没有做相应的处理,而是在外面另外写了一个检测函数,确保输入的数据是合法的。个人认为还是在函数内对输入数据进行合法性判断比较好,因为当工程比较大时,在相应函数外的检测常常容易漏掉,造成不必要的损失。举例是减法函数中没有考虑差为0的情况,除法函数中除数为0的情况。
struct dat div(int a,int b,int c,int d) /*定义除法函数*/
{
int u1,u2;
u1=a*d;
u2=b*c;
return yuefen(u1,u2);
}
2.2 输出是否符合标准
输出基本上是符合标准的,目前没有发现输出不符合标准的情况。
2.3 对于无效参数的处理
我在程序中主要看到的无效参数处理有2种:第一种是计算或者随机的过程中产生了负数的现象,这中情况是通过一个函数将负数通过绝对值变成正数。第二种是出现了数字为0的情况,这种情况下是通过判断函数,当等于0时放弃这个数。
3.1 注释
整体来看注释的量比较少,注释主要集中在代码开始部分。除此之外,注释的风格不太一致。尤其开始结构定义部分有很多注释是用拼音写的(当然这其中有担心中文注释可能带来的问题),但对于一个工程来讲还是希望尽量把注释写清楚,多写一些有用的注释。这一点非常重要,本来想认认真真地把代码整体看一遍,但是看到一大半实在是看不下去了,没有注释各种的看不懂。
3.2 文档
本程序没有相应的文档说明,这个也不属于第一次作业的要求范畴,在此不做讨论。
4.1 是否有测试,测试是否好理解?
这个程序中没有测试的地方。
4.2 数组越界测试
从程序上看有可能面临数组越界的问题,但是并没有相应的测试,可能是时间太短了,并没有时间去进行测试。
总的来说,这个程序还是相当不错的,我在复审里面主要提的都是有问题的部分所以看前来我对这个程序的评价不高,然而事实并不是这样。我希望通过给同伴指出错误来使其进步,而优点实在太多我也不便一一列举,还是在之前说的,我是鸡蛋里挑骨头了。我觉得最重要的一点就是注释量和变量名的选取,这一点也是我自己可能存在的问题,以前一个人写代码并不能够意识到注释和文档的重要性,这一点在结对的时候总算能够重视起来了。