结对编程
1.结对编程作业要求:
小学老师要每周给同学出300道四则运算练习题。
这个程序有很多种实现方式:
C/C++
C#/VB.net/Java
Excel
Unix Shell
Emacs/Powershell/Vbscript
Perl
Python
两个运算符,100 以内的数字,不需要写答案。
需要检查答案是否正确,并且保证答案在 0..1000 之间
尽可能地多设置一些条件
请两位同学以结对编码(一个同学coding,另一个同学在旁边审核代码,之后再交换角色)的方式完成本次实验)
2.参与成员
本人:2352821
另一位:2352825
3.程序功能设计
首先我们实现了随机生成四则运算算式,三个数字与两个运算符,并且数字的范围均处于1-100之间。
并且在算式生成结束后,会进行结果检查,若本次生成答案超出了[0,1000]的范围,则重新生成当前算式。
由于乘除0对于结果的影响过大,可能导致计算难度大幅降低,故数字范围选择了1-100而非0-100
对于除法部分,考虑到可能产生小数,因此我们对于所有计算结果取两位小数计算
在以上基础功能之外,我们还设计了一些其它功能:
·单次题目产生量:
考虑到教师需要每周三百道题,而每天可能并不需要这么多,我们设置了一个变量size用于控制每次算式的生成量
代码中默认为10,更改此变量可以改变单次程序运行所产生的算式数量。
·答题功能:
在算式生成结束后,依次输入各个算式的答案,程序会将答案与生成算式时保存的答案进行比对。统计出错误数量和错误题号
在此基础上计算出正确率等信息,可以辅助教师批改,也可让学生全自动练习口算题。
在答题结束,并且展现完正确率等数据后,会列出所有算式的答案,老师可以根据答案批改作业,或者学生自行核对答案。
4.算法设计思路
本次作业我们采用了c++进行编写,核心思路是使用cpp内置的rand函数生成随机数,以此来产生算式。
定义了一个const int size常量,用于修改程序一次产生的算式量,所有数组和循环都调用了size。
在部分函数中使用传递引用的方式来传参,有效消减了程序大小和执行效率。
在核心的算式生成部分,首先我们使用了rand函数来生成三个数字,并且再生成两个1-4的整数,分别代指+、-、*、/
两个操作符数字分别记为t1和t2。
生成完后,首先调用judgeop函数,将1-4的整数t1t2转换为char类型的c1c2,为输出算式做准备。
然后调用createnum函数,使用随机数生成三个数字与两个操作符。
此后,调用check函数进行算式答案范围的检查,而check函数会调用calculate函数进行计算。
在calculate函数中,计算算式的算法如下:
·判断c1操作符是否为乘除,且c2为加减。若通过,则分类计算结果并返回。
·以上判断未通过,判断c2操作符是否为乘除,且c1为加减。若通过,计算结果并返回。
·以上判断均未通过,则代表算式中仅有加减/乘除,根据交换律,按顺序计算即可。
若check函数检查,算式答案超过了范围,则重新生成。check函数通过后,再次调用calculate函数,将算式的结果存入
一个大小为const size的数组内,以备之后的核验环节。
上方的过程全部结束之后,输出生成的若干个算式。
以上为算式生成部分,接下来是答题环节。根据上方生成的算式数量,用户输入对应的答案,存入一个数组内
全部输入完毕后,分别与预先存储的答案数组进行一一对比,并且统计出错题题号与错题量。
当比对发现某一题错误时,将预先定义的bool err[]数组的第n为改为false,用于标记。而当某一题正确时,correct技术+1。
在输出错误题号时,遍历err数组,若值为false,则输出数组下标+1,代表题号。使用correct/size来计算正确率
输出完毕后,遍历标准答案数组,输出所有参考答案,此后退出程序。
5.程序代码展示
点击查看代码
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <iomanip>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
char judgeop(char &cc1,char &cc2,int t);
float calculate(float a, float b, float c, char c1, char c2);
bool checkans(int aa,int bb,int cc,int t);
void createnum(int &aa,int &bb,int &cc,int &tt);
const int size = 10;
float calculate(float a, float b, float c, char c1, char c2) {//传入三个待计算数字与两个操作符
if ((c1 == '*' || c1 == '/') && (c2 == '+' || c2 == '-')) {
float temp;
switch (c1) {
case '*':
temp = a * b;
break;
case '/':
if (b == 0) {
cerr << "Error: Division by zero!" << endl;
return 0;
}
temp = a / b;
break;
default:
cerr << "Error: Invalid operator " << c1 << endl;
return 0;
}
switch (c2) {
case '+':
return temp + c;
case '-':
return temp - c;
default:
cerr << "Error: Invalid operator " << c2 << endl;
return 0;
}
} else if ((c2 == '*' || c2 == '/') && (c1 == '+' || c1 == '-')) {
float temp;
switch (c2) {
case '*':
temp = b * c;
break;
case '/':
if (c == 0) {
cerr << "Error: Division by zero!" << endl;
return 0;
}
temp = b / c;
break;
default:
cerr << "Error: Invalid operator " << c2 << endl;
return 0;
}
switch (c1) {
case '+':
return a + temp;
case '-':
return a - temp;
default:
cerr << "Error: Invalid operator " << c1 << endl;
return 0;
}
} else {
float temp1;
switch (c1) {
case '+':
temp1 = a + b;
break;
case '-':
temp1 = a - b;
break;
case '*':
temp1 = a * b;
break;
case '/':
if (b == 0) {
cerr << "Error: Division by zero!" << endl;
return 0;
}
temp1 = a / b;
break;
default:
cerr << "Error: Invalid operator " << c1 << endl;
return 0;
}
float temp2;
switch (c2) {
case '+':
temp2 = temp1 + c;
break;
case '-':
temp2 = temp1 - c;
break;
case '*':
temp2 = temp1 * c;
break;
case '/':
if (c == 0) {
cerr << "Error: Division by zero!" << endl;
return 0;
}
temp2 = temp1 / c;
break;
default:
cerr << "Error: Invalid operator " << c2 << endl;
return 0;
}
return temp2;
}
}
bool checkans(int aa,int bb,int cc,int t){//检查答案是否处于0-1000,传入三个数与符号t
char c1,c2;
judgeop(c1,c2,t);
float a,b,c;
a = aa;b = bb;c = cc;
float ans = calculate(a,b,c,c1,c2);
if (ans<=1000&&ans>=0)
return true;
else
return false;
}
void createnum(int &aa,int &bb,int &cc,int &tt)//创建表达式并输出
{
int a,b,c,t1,t2,t;
char c1,c2;
a = rand() % 100+1;
b = rand() % 100+1;
c = rand() % 100+1;//1-100
t1 = rand() % 4+1;//1-4,分别代表加减乘除
t2 = rand() % 4+1;
t = t1*10+t2;//合成为一个数
aa=a;bb=b;cc=c;tt=t;
}
char judgeop(char &cc1,char &cc2,int t){
int t1 = t/10;
int t2 = t%10;
char c1,c2;
char op[4] = {'+','-','*','/'};
switch(t1){
case 1:
c1 = '+';
break;
case 2:
c1 = '-';
break;
case 3:
c1 = '*';
break;
case 4:
c1 = '/';
break;
default:
break;
}
switch(t2){
case 1:
c2 = '+';
break;
case 2:
c2 = '-';
break;
case 3:
c2 = '*';
break;
case 4:
c2 = '/';
break;
default:
break;
}
cc1 = c1;
cc2 = c2;
}
void start(float (&an)[size],bool (&err)[size]){
cout<<"正在生成题目,本次生成题目量为:"<<size;
int i=0;
int a,b,c,t;
char c1,c2;
while(i<=size){
createnum(a,b,c,t);
if(checkans(a,b,c,t)){
judgeop(c1,c2,t);
cout<<i<<":";
cout<<a<<c1<<b<<c2<<c<<endl;
an[i] = calculate(a,b,c,c1,c2);
i++;
}
}
cout<<"请开始答题,题目答案保留两位小数,不同题目答案使用空格分割"<<endl;
float ans[size];
int correct = 0;
i=0;
while(i<size){
cin>>ans[i];
if(ans[i] == an[i]){
correct++;
}
else{
err[i] = false;
}
i++;
}
cout<<"答题结束,正在核对结果"<<endl;
float pct = (correct/size)*100;
cout<<"本次答题正确题目数为:"<<correct<<"题,正确率为"<< fixed << setprecision(2) << pct <<"%"<<endl;
cout<<"错误题号为:";
for(i=0;i<size;i++){
if(err[i]==false)
cout<<i+1<<" "<<endl;
}
cout<<"以下为答案列表"<<endl;
for(i=0;i<=size;i++){
cout << "第" <<i<<"题答案为:";
cout << fixed << setprecision(2) << answer[i] << endl;
}
}
int main(int argc, char** argv) {
srand((int)time(0));
float answer[size];
bool err[size] = {true};
start(answer,err);
return 0;
}
6.运行功能截图
算式生成部分(程序默认值10题)

修改算式生成量

答题功能与结果统计计算功能

7.结对编程体会
结对编程需要体会另一个人的编程思路,不同人的习惯不同编写、思考方式也略有不同。有时候写出一段代码,我自己可以很轻易的理解,但是需要让他人理解则需要费一番功夫。
但是在解释的过程中,我能够反思这段代码,发现一些潜在的问题,或者是产生一些新的理解。
因为coding风格的原因,在开始结对编程前最好规定一些两个人都认可的编写规范,例如格式,定义/传参方式等,这样可以减轻交流压力并且提高效率。
当一个人正思考代码实现时,另一个人可以从整体角度分析程序的结构,尽管存在一定程度的沟通成本,但是但收获的代码质量提升、知识快速积累和团队协作经验,
使得这成为了一种卓有价值的学习方式。

浙公网安备 33010602011771号