个人第2次作业----熟悉使用工具
个人信息
GIT地址 | https://github.com/ShangkangTang/AchaoCalculator/blob/master/ShankangTang/ConsoleApplication1/ConsoleApplication1/ConsoleApplication1.cpp |
---|---|
GIT用户名 | ShangkangTang |
学号后五位 | 22208 |
博客地址 | https://www.cnblogs.com/qiheideyue121382/ |
作业正文
part.1----配置环境及工具准备
想用C++来着,一点点不知不觉写完了也调试好了,发现还主要都是用的C/尴尬
① 编程环境准备
电脑中之前已经下载有VS 2017,便不需要额外下载了
Image
② github账号准备
之前的一个学期就一直有在使用github来存储平时的一些代码
Image
“fork”拷贝入自己的同名仓库中
③ 安装git
成功安装后选择一个文件打开“bash here”,输入以下指令,实现项目克隆到本地
Image
part.2----代码实现
###
① 题目要求
程序接收一个命令行参数 n,然后随机产生 n 道加减乘除(分别使用符号+-*/来表示)练习题,每个数字在 0 和 100 之间,运算符在 2 个 到 3 个之间。
由于阿超的孩子才上一年级,并不知道分数。所以软件所出的练习题在运算过程中不得出现非整数,比如不能出现 3÷5+2=2.6 这样的算式
练习题生成好后,将生成的n道题及其对应的正确答案输出到一个文件subject.txt中。
② 思路分析及代码实现
看到题目要求我的想法是每个式子整体由两个部分组成,其中第一部分是参与运算的三个数值、两个运算符,第二部分是”=”和运算结果。
第二部分比较简单,就单纯输出显示或者运算输出
而第一部分需要随机生成
随机生成三个运算数值
还要随机生成两个运算符(均是在“+-×/”中随机的一个)
后者可以依旧采用随机生成两个数值
然后替代成符号
(这里可以采用一个替代规则,还需要一个字符数组
作为“运算符库”)
两个运算符为了后面容易调用也采用一个字符数组
存储起来
按照以上说的,要用到多个数组,且要多次存储和调用其中数值,因此我想到采用一个结构体
,如下:
//定义记录每道算术题字符串形式及参与运算的数值的结构体
typedef struct question
{
int a[5];
char b[2];//用于记录运算符
char c[4];//运算符库
int d;//d为结果
}sums;
其中a用于存储随机生成的5个数值
随机生成函数如下
//随机生成5个数值,3个用于参与运算,2个用于生成运算符,均存于数组a中
int product(sums &L)
{
int i;
for (i = 0; i < 3; i++)
{
L.a[i] = rand() % 100 + 1;
}
for (; i < 5; i++)
{
L.a[i] = rand() % 3 + 0;
}
return 0;
}
借用数组最后两个元素a[3]和a[4]生成运算符并存储于字符数组中
//利用L.a数组最后两个数值生成运算符
int Operator(sums &L)
{
L.b[0] = L.c[L.a[3]];//随机生成运算符并存储于L.b
L.b[1] = L.c[L.a[4]];
return 0;
}
这下数值和运算符都已经大体具备了
仔细看题目要求,有一点要求,结果不许为小数,因此需要有一个判断函数,确保生成的式子运算后必须为整数,若为整数同时生成运算结果存储于L.d,以下代码
//判别运算式子是否符合要求,并运算
int Tell(sums &rl,int sum)
{
int e;
float g, h, f;
if (rl.b[0] == '/' || rl.b[1] == '/')
{
if (rl.b[0] == '/')
{
e = rl.a[0] / rl.a[1];
g = rl.a[0];
h = rl.a[1];
f = g / h;
if (e != f)
{
return 0;
}
}
else
{
e = rl.a[1] / rl.a[2];
g = rl.a[1];
h = rl.a[2];
f = g / h;
if (e != f)
{
return 0;
}
}
}
else
{
if (rl.a[3] == 0 && rl.a[4] == 0)
rl.d = rl.a[0] + rl.a[1] + rl.a[2];
else
if (rl.a[3] == 0 && rl.a[4] == 1)
rl.d = rl.a[0] + rl.a[1] - rl.a[2];
else
if (rl.a[3] == 0 && rl.a[4] == 2)
rl.d = rl.a[0] + rl.a[1] * rl.a[2];
else
if (rl.a[3] == 0 && rl.a[4] == 3)
rl.d = rl.a[0] + rl.a[1] / rl.a[2];
else
if (rl.a[3] == 1 && rl.a[4] == 0)
rl.d = rl.a[0] - rl.a[1] + rl.a[2];
else
if (rl.a[3] == 1 && rl.a[4] == 1)
rl.d = rl.a[0] - rl.a[1] - rl.a[2];
else
if (rl.a[3] == 1 && rl.a[4] == 2)
rl.d = rl.a[0] - rl.a[1] * rl.a[2];
else
if (rl.a[3] == 1 && rl.a[4] == 3)
rl.d = rl.a[0] - rl.a[1] / rl.a[2];
else
if (rl.a[3] == 2 && rl.a[4] == 0)
rl.d = rl.a[0] * rl.a[1] + rl.a[2];
else
if (rl.a[3] == 2 && rl.a[4] == 1)
rl.d = rl.a[0] * rl.a[1] - rl.a[2];
else
if (rl.a[3] == 2 && rl.a[4] == 2)
rl.d = rl.a[0] * rl.a[1] * rl.a[2];
else
if (rl.a[3] == 2 && rl.a[4] == 3)
rl.d = rl.a[0] * rl.a[1] / rl.a[2];
else
if (rl.a[3] == 3 && rl.a[4] == 0)
rl.d = rl.a[0] / rl.a[1] + rl.a[2];
else
if (rl.a[3] == 3 && rl.a[4] == 1)
rl.d = rl.a[0] / rl.a[1] - rl.a[2];
else
if (rl.a[3] == 3 && rl.a[4] == 2)
rl.d = rl.a[0] / rl.a[1] * rl.a[2];
else
if (rl.a[3] == 3 && rl.a[4] == 3)
rl.d = rl.a[0] / rl.a[1] / rl.a[2];
return 1;
}
return 0;
}
具体代码解释:由于小数只会产生于有“/”运算符参与的式子,所以只有在此情况判断是否返回0
然后即将编写主函数时,自然会想到结构体的初始化,初始化函数如下
//初始化结构体SUMS
int initList(sums &L)
{
int i;
for (i = 0; i < 6; i++)
{
L.a[i] = 0;
}
for (i = 0; i < 2; i++)
{
L.b[i] = 0;
}
L.d = 0;
L.c[0]= '+';
L.c[1]= '-';
L.c[2]='*';
L.c[3]= '/';
return 1;
}
然后是主函数部分,其中程序包括,输入算术题数目进行循环调用函数,以及存入文件subject.txt
int main()
{
sums rl;
FILE *wf;
errno_t w;
int i;
int sum;
w = fopen_s(&wf, "subject.txt", "w");
if (initList(rl) == 1)
cout << "请稍等" << endl;
cout << "请输入需要的算术题总数:" << endl;
cin >> sum;
cout << "*此程序用于算术题的自动生成*" << endl;
for (i = 0; i < sum; i++)
{
product(rl);
cout << "正在生成第" << i << "个运算式" << endl;
Operator(rl);//生成运算符并存储于rl.b
if (Tell(rl, sum) == 0)//调用函数Tell对整体式子进行判断是否符合要求,符合则进一步运算出结果
{
i--;
}
else
{
fprintf(wf, "%d ", rl.a[0]);
fprintf(wf, "%c ", rl.b[0]);
fprintf(wf, "%d ", rl.a[1]);
fprintf(wf, "%c ", rl.b[1]);
fprintf(wf, "%d", rl.a[2]);
fprintf(wf, "=");
fprintf(wf, "%d", rl.d);
fprintf(wf, "\n");
cout << "写入完毕" << endl;
initList(rl);
}
}
fclose(wf);
}
③ 运行展示
Image
Image
***part.3----测试
①单元测试
右键解决方案先创建单元测试项目
Image
为了对原来项目各个函数进行测试,需要引入原来项目
Image
对各个函数按顺序逐一测试,全部通过
Image
②回归测试
再次对原项目测试,仍无差错。
part4----代码提交
先试用git push 指令将本地代码上传
然后“new pull request”
最后点击“create pull request”
Image
part5----感想
本次作业的完成坎坷很多,但正如一句西方名言所说,“收获与磨难永成正比”,通过完成这个作业,也同时受益颇多。
一方面虽然之前一直在使用github,但都是在线建立仓库与文件,用来存储日常代码,这次之后才了解到了git的具体使用,但是各种git指令还不熟悉,需要在后续的使用中渐渐掌握。
代码方面这次的题目整体是比较简单的,没有花费过多时间,只是期间整形赋值给字符数组时遇到过问题,于是不得不改变原有显示、存储字符串的方案,采用字符输出。但后续代码编写能力还有待提高,尤其后面要努力提高对C++和正在学的python的掌握。
最大的收获还是了解了单元测试这方面吧,之前很少接触这个,非常感谢我们的课程能给我们一个机会去接触这些。