软件工程——结对作业(2)

一、项目选题

   本次作业要求两个人合作完成,驾驶员和导航员角色自定。在小学四则运算自动生成程序和电梯调度问题中,我们选择了四则运算题目。

二、题目要求

①能够自动生成四则运算练习题
②可以定制题目数量
③用户可以选择运算符
④用户设置最大数(如十以内、百以内等)
⑤用户选择是否有括号、是否有小数
⑥用户选择输出方式(如输出到文件、打印机等)
⑦最好能提供图形用户界面(根据自己能力选做,以完成上述功能为主)

三、角色选定

  • 驾驶员:王成成
    • 任务
      (1)能够完成全部代码工作,程序基本实现全部要求功能,并将代码上传至coding.net或者GitHub代码托管系统中。
      (2)能够对导航员在本次编程工作中起到的作用给出客观评价。
  • 领航员:耿蝶芮
    • 任务
      (1)能够辅助驾驶员完成全部代码工作,并且为关键函数选用合适的覆盖标准设计测试用例,并编写代码进行单元自动测试。
      (2)能够根据上次作业的代码检查表对驾驶员的本次工作进行评价。

四、代码上传

五、程序设计
  四则运算问题,关键是能够自动生成算数表达式。在这部分中,我们整体代码采用C++和结构体进行设计。而针对页面显示结构,我们则采用了html以及js进行设计。我们给出表达式的组数、表达式中涉及到的数据的大小范围以及数据类型。除此之外,还要考虑到生成的表达式是否含有括号、具体包含哪些运算符等。因此,我们在代码中进行了详细分析设计,并且进行了重构,从而使得代码整洁、可修改性强。
1、结构体设计

struct data
{
    int num[10001];
    float num1[10001];
}p[10001];

2、主函数
  在主函数中,我们主要针对一些必要要求进行了判断,并依据此在其各个子函数中进行处理。对于运算符的选择,我们依据学生的要求进行设计,通过设定字符串数组来完成运算符的选择。

int main()
{
	int NUM,Num,Max;
	int parentheses,print_yes_no,decimal;
	char op_operator[5];
	cout<<"----------------------------------------------------------\n";
	cout<<"请输入共有多少组运算表达式:";
	cin>>NUM;
	cout<<"----------------------------------------------------------\n";
	cout<<"请输入运算数的最大值,以保证所有计算数据都在该数字以内: ";
	cin>>Max;
	cout<<"----------------------------------------------------------\n";
	cout<<"请输入有无括号(1代表有括号、0代表无括号): ";
	cin>>parentheses;
	cout<<"----------------------------------------------------------\n";
	cout<<"请输入是否将结果存到文件中(1代表存放、0代表不存放): ";
	cin>>print_yes_no;
	cout<<"----------------------------------------------------------\n";
	cout<<"请选择输入是小数还是整数(1代表整数、0代表小数):";
    cin>>decimal;
    cout<<"----------------------------------------------------------\n";
    cout<<"请选择输入的运算符:";
	cin>>op_operator;
	cout<<"----------------------------------------------------------\n";
    Num=-1;
    while(1)
    {
        if(Num<2||Num>8)
            Num=int(rand()%10);//定义每个表达式有多少个参与运算的实数
        else
            break;
    }
	if(parentheses==1)
        Have_parentheses(NUM,Max,Num,print_yes_no,op_operator,decimal);
    else if(parentheses==0)
        No_parentheses(NUM,Max,Num,print_yes_no,op_operator,decimal);
	system("pause");
	return 0;
}

3、括号处理
  对于表达式中是否含有括号的问题,我们分为两部分:有括号形式和无括号形式。在程序中,我们利用了随机数生成函数进行处理。
(1)无括号形式的表达式

void No_parentheses(int NUM,int Max,int Num,int print_yes_no,char op_operator[],int decimal)//无括号的运算形式
{
    int i,j,len;
    int op;
    len=strlen(op_operator);
    ofstream outfile;
    outfile.open("a.txt");
    for(i=0;i<NUM;i++)
    {
        for(j=0;j<Num;j++)
        {
            op=int(rand()%len);
            if(decimal==1)
            {
                p[i].num[j]=rand()%Max+1;
                p[i].num[j+1]=rand()%Max+1;
            }
            if(decimal==0)
            {
                p[i].num1[j]=rand()%Max*0.3;
                p[i].num1[j+1]=rand()%Max*0.7;
            }
            if(j<Num-1)
            {
                if(decimal==1)
                {
                    cout<<p[i].num[j]<<" "<<op_operator[op]<<" ";
                    if(print_yes_no==1)
                         outfile<<p[i].num[j]<<" "<<op_operator[op]<<" ";
                }
                else
                {
                    cout<<setprecision(1)<<std::fixed<<p[i].num1[j]<<" "<<op_operator[op]<<" ";
                    if(print_yes_no==1)
                        outfile<<setprecision(1)<<std::fixed<<p[i].num1[j]<<" "<<op_operator[op]<<" ";
                }
            }
            if(j==Num-1)
            {
                if(decimal==1)
                {
                    cout<<p[i].num[j]<<" ";
                    if(print_yes_no==1)
                        outfile<<p[i].num[j]<<" ";
                }
                else
                {
                    cout<<setprecision(1)<<std::fixed<<p[i].num1[j];
                    if(print_yes_no==1)
                        outfile<<setprecision(1)<<std::fixed<<p[i].num1[j];
                }
            }
        }
        cout<<"= "<<"\n";
        if(print_yes_no==1)
            outfile<<"= "<<"\n";
    }
    outfile.close();
}

(2)有括号形式的表达式

void Have_parentheses(int NUM,int Max,int Num,int print_yes_no,char op_operator[],int decimal)//带括号的运算
{
    int flag1=0,flag2=0;
    int k1,k2;
    int op;
    int i,j,len;
    len=strlen(op_operator);
    ofstream outfile;
    outfile.open("a.txt");
    for(i=0;i<NUM;i++)
    {
        k1=-1;
        k2=-1;
        while(1)
        {
            if(k1>k2||k2-k1<2||k2>Num)
            {
                k1=int(rand()%(Num-1));
                k2=int(rand()%(Num-1));
            }
            else
                break;
        }
        for(j=0;j<Num;j++)
        {
            op=int(rand()%len);
            if(decimal==1)
            {
                p[i].num[j]=rand()%Max+1;
                p[i].num[j+1]=rand()%Max+1;
            }
            if(decimal==0)
            {
                p[i].num1[j]=rand()%Max*0.3;
                p[i].num1[j+1]=rand()%Max*0.7;
            }
            if(j<Num-1)
            {
                if(j==k1)
                {
                    if(decimal==1)
                    {
                        cout<<"("<<p[i].num[j]<<" "<<op_operator[op]<<" ";
                        flag1=1;
                        if(print_yes_no==1)
                            outfile<<"("<<p[i].num[j]<<" "<<op_operator[op]<<" ";
                    }
                    else
                    {
                        cout<<"("<<setprecision(1)<<std::fixed<<p[i].num1[j]<<" "<<op_operator[op]<<" ";
                        flag1=1;
                        if(print_yes_no==1)
                            outfile<<"("<<setprecision(1)<<std::fixed<<p[i].num1[j]<<" "<<op_operator[op]<<" ";
                    }
                }
                else if(j==k2)
                {
                    if(decimal==1)
                    {
                        cout<<p[i].num[j]<<")"<<" "<<op_operator[op]<<" ";
                        flag2=1;
                        if(print_yes_no==1)
                            outfile<<p[i].num[j]<<")"<<" "<<op_operator[op]<<" ";
                    }
                    else
                    {
                        cout<<setprecision(1)<<std::fixed<<p[i].num1[j]<<")"<<" "<<op_operator[op]<<" ";
                        flag2=1;
                        if(print_yes_no==1)
                            outfile<<setprecision(1)<<std::fixed<<p[i].num1[j]<<")"<<" "<<op_operator[op]<<" ";
                    }
                }
                else
                {
                    if(decimal==1)
                    {
                        cout<<p[i].num[j]<<" "<<op_operator[op]<<" ";
                        if(print_yes_no==1)
                            outfile<<p[i].num[j]<<" "<<op_operator[op]<<" ";
                    }
                    else
                    {
                        cout<<setprecision(1)<<std::fixed<<p[i].num1[j]<<" "<<op_operator[op]<<" ";
                        if(print_yes_no==1)
                            outfile<<setprecision(1)<<std::fixed<<p[i].num1[j]<<" "<<op_operator[op]<<" ";
                    }
                }
            }
            else
            {
                if(flag1==1&&flag2==0)
                {
                    if(decimal==1)
                    {
                        cout<<p[i].num[j]<<")"<<" ";
                        if(print_yes_no==1)
                            outfile<<p[i].num[j]<<")"<<" ";
                    }
                    else
                    {
                        cout<<setprecision(1)<<std::fixed<<p[i].num1[j]<<')';
                        if(print_yes_no==1)
                            outfile<<setprecision(1)<<std::fixed<<p[i].num1[j]<<')';
                    }
                }
                else
                {
                    if(decimal==1)
                    {
                        cout<<p[i].num[j]<<" ";
                        if(print_yes_no==1)
                            outfile<<p[i].num[j]<<" ";
                    }
                    else
                    {
                        cout<<setprecision(1)<<std::fixed<<p[i].num1[j];
                        if(print_yes_no==1)
                            outfile<<setprecision(1)<<std::fixed<<p[i].num1[j];
                    }
                }
            }
        }
       cout<<"= "<<"\n";
       if(print_yes_no==1)
            outfile<<"= "<<"\n";
    }
    outfile.close();
}

六、界面设计
1、对于界面的设计,我们采用了html以及js等技术,大体上实现了四则运算的显示界面。实现代码如下:

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8">
		<form method="post">
			运算表达式组数:<input type='text' id="NUM" size="15" maxlength="10"/><br /><br />
			运算数据最大值:<input type='text' id="Max" size="15" maxlength="10"/><br /><br />
			表达式有无括号:
			<input type="radio"  name="gender1" value="有括号"/>有括号
			<input type="radio"  name="gender1" value="无括号"/>无括号
			<br />
			<br />
			数据的数据类型:
			<select id="datatype">
				<option value=0>整数</option>
				<option value=1>小数</option>
			</select>
			<br />
			<br />
			运算操作符:
			<input type="checkbox" name="gender2" value="+"/>+
			<input type="checkbox" name="gender2" value="-"/>-
			<input type="checkbox" name="gender2" value="*"/>*
			<input type="checkbox" name="gender2" value="/"/>/
		</form>
		<textarea name="textContent" cols="80" rows="15" id="textContent"></textarea> <br />
		<form>
			<input type="button" id="Button" value="Done!">
		</form>
		<script>
			window.onload = init;
			var p=[];
			function Have_parentheses(NUM,Max,Num,print_yes_no,op_operator,decimal)
			{
    			var flag1=0;
    			var flag2=0;
    			var k1;
    			var k2;
    			var op;
    			var i;
    			var j;
    			var len;
    			len=op_operator.length;
    			var s="";
    			p=new Array();
    			for(i=0;i<NUM;i++)
    			{
       			 	k1=-1;
        			k2=-1;
        			while(1)
        			{
            			if(k1>k2||k2-k1<2||k2>Num)
            			{
                			k1=Math.floor(Math.random()*(Num-1));
                			k2=Math.floor(Math.random()*(Num-1));
            			}
            			else
                			break;
        			}
        			var num=new Array();
        			for(j=0;j<Num+1;j++){
        			num.push(j);
	    			}
        			p.push(num);
        			for(j=0;j<Num;j++)
       			 	{
            			op=Math.random()*len;
            			if(decimal==0){
            			p[i][j]=Math.floor(Math.random()*Max+1);
            			p[i][j+1]=Math.floor(Math.random()*Max+1);
						}	
						else{
            			p[i][j]=(Math.random()*Max+1).toFixed(2);
            			p[i][j+1]=(Math.random()*Max+1).toFixed(2);
						}	
            			if(j<Num-1)
            			{
            			    if(j==k1)
                			{
					 			flag1=1;
								s+="(";
								s+=p[i][j].toString();
								s+=" ";
								var num=Math.floor(Math.random()*len);
								s+=op_operator[num];
								s+=" ";
                			}
                			else if(j==k2)
                			{
								flag2=1;
								s+=p[i][j].toString();
								s+=")";
								s+=" ";
								var num=Math.floor(Math.random()*len);
								s+=op_operator[num];
								s+=" ";
                			}
                			else
                			{
								var num=Math.floor(Math.random()*len);
                    			s+=p[i][j].toString();s+=" ";s+=op_operator[num];s+=" ";
                			}
           				}
            			else
           				{
                			if(flag1==1&&flag2==0)
                			{
                    			s+=p[i][j].toString();s+=")";s+=" ";
                			}
                			else
                			{
                    			s+=p[i][j].toString();s+=" ";
                			}
            			} 
            			console.log(s);
        			}
        		s+="=  \n ";
    			}
    			var output = document.getElementById("textContent");
				output.value=s;
		    }

			function No_parentheses(NUM,Max,Num,print_yes_no,op_operator,decimal)
			{
				var flag1=0;
    			var flag2=0;
    			var k1;
    			var k2;
    			var op;
    			var i;
    			var j;
    			var len;
    			len=op_operator.length;
    			var s="";
    			p=new Array();
    			for(i=0;i<NUM;i++)
    			{
        			k1=-1;
        			k2=-1;
        			while(1)
        			{
            			if(k1>k2||k2-k1<2||k2>Num)
            			{
            	    		k1=Math.random()*5;
            	    		k2=Math.random()*5;
            			}
            			else
            	    		break;
        			}
        			var num=new Array();
        			for(j=0;j<Num+1;j++){
        				num.push(j);
	   	 			}
        			p.push(num);
  
        			for(j=0;j<Num;j++)
        			{
            			op=Math.random()*len;
           				if(decimal==0){
            				p[i][j]=Math.floor(Math.random()*Max+1);
            				p[i][j+1]=Math.floor(Math.random()*Max+1);
						}	
						else{
            				p[i][j]=(Math.random()*Max+1).toFixed(2);
            				p[i][j+1]=(Math.random()*Max+1).toFixed(2);
						}	
            			if(j<Num-1)
            			{
                			if(j==k1)
                			{
								s+=p[i][j].toString();
								s+=" ";
								var num=Math.floor(Math.random()*len);
								s+=op_operator[num];
								s+=" ";
                			}	
                			else if(j==k2)
                			{	
								s+=p[i][j].toString();
								s+=" ";
								var num=Math.floor(Math.random()*len);
								s+=op_operator[num];
								s+=" ";
                			}
                			else
                			{
								var num=Math.floor(Math.random()*len);
                    			s+=p[i][j].toString();s+=" ";s+=op_operator[num];s+=" ";
                			}	
            			}
            			else
            			{
                			if(flag1==1&&flag2==0)
                			{
                    			s+=p[i][j].toString();s+=" ";
                			}
                			else
                			{
                    			s+=p[i][j].toString();s+=" ";
                			}	
            			} 
            			console.log(s);
        			}
        			s+="=  \n ";
    			}
    			var output = document.getElementById("textContent");
				output.value=s;
			}

			function handleButton(){
				var input1=document.getElementById("NUM");
				var input2=document.getElementById("Max");
				var input3=document.getElementsByName("gender1");
				var select =document.getElementById("datatype");
				var value = select.value;
				var input4 = document.getElementsByName("gender2");
	
				var NUM,Num=-1,Max,parentheses,print_yes_no,decimal;
				var op_operator=[];
				NUM=input1.value;
				while(1)
    			{
        			if(Num<2||Num>8)
            			Num=Math.floor(Math.random()*10);		//定义每个表达式有多少个参与运算的实数
        			else
            			break;
    			}
    			Max=input2.value;
    			parentheses=-1;
    			if(input3[0].checked)
    				parentheses=1;
    			if(input3[1].checked)
    				parentheses=0;
    				print_yes_no=0;
    			if(value==1)
    				decimal=1;
    			else
    				decimal=0;
    			if(input4[0].checked)
    				op_operator.push('+');
    			if(input4[1].checked)
    				op_operator.push('-');
    			if(input4[2].checked)
    				op_operator.push('*');
    			if(input4[3].checked)
    				op_operator.push('/');
				if(parentheses==1){	//有括号
        			Have_parentheses(NUM,Max,Num,print_yes_no,op_operator,decimal);
			}
    		else if(parentheses==0){//无括号
        		No_parentheses(NUM,Max,Num,print_yes_no,op_operator,decimal);
				}
			}

			function init() {
				var Button = document.getElementById("Button");
				Button.onclick = handleButton;
			}
		</script>
	</head>
	<body>
	</body>
<html>

2、针对不同的选择条件,我们选择几种形式,并给出如下页面显示结果。
(1)选择单操作符进行表达式的生成,包括整数、小数、有无括号的形式。


(2)选择多操作符进行表达式的生成,包括整数、小数、有无括号的形式。



七、总结
  本次结对作业,我和耿蝶芮同学配合十分默契。我担任驾驶员的角色,主要负责代码的编写、重构、修复以及界面的设计工作。而耿蝶芮同学作为领航员,非常负责地对编写的代码进行检查,并提出意见,从而充分满足要求。在配合的过程中,耿蝶芮同学尽职尽责、一直在不断监督,生怕出现一些问题。而我在编写 过程中也遇到了一些问题,尤其是将运算表达式填充到文件中时。最后经过查找资料,并且不断修改,发现导致问题出现的原因在于频繁地开关文件。经过修改之后,问题得以解决。同时,耿蝶芮同学对于代码质量以及代码规范要求很高,具有较好的风格,所以我们也遇到了一些其他的小问题,不过好在最后得以解决。在合作的过程中,我们发现了彼此的优缺点,取其精华,去其糟粕,非常成功地完成了本次作业。通过这次合作,使我们能够更好理解到底什么是合作,这个过程是非常享受的。我们为着同一个目标一起努力,不断向对方学习,不断交流思想。我相信这次经历对未来的团队合作也会有很大益处。最后还是感谢我的伙伴——耿耿!

posted @ 2019-05-06 21:43  wangchengcheng  阅读(223)  评论(0)    收藏  举报