结对项目总结
经过3周的开发与测试工作,此次结对项目终于告一段落。
本次结对项目是基于上次的个人项目完成的。本质上来说,是将上回的计算功能模块化,再加入随机生成算式的功能模块,最后把他们附在界面上调用。
在这次结对编程过程中,我们主要完成了以下几点:
1、随机生成算式
2、能选择生成算式的长度
3、能够选择生成算式中数字的位数和精度
4、能够选择生成的括号数量(因为考虑到随机生成,所以控制的数量是括号的最大量而不是固定量)
本次试验是第一次和别人结对编程,因此没有一个详细的规划,所以在最后将其模块化时遇到了很大的困难。
除此之外,也感到了沟通的重要性,因为在代码编写的过程中,没能提前统一代码的规范和结构,结果在开始编写后遇到了很多问题,让进度不快反慢,有一种“单干反而更轻松”的想法。
附实验代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<stack>
using namespace std;
#define N 1000
int timer=0;
int ri,wr=0;
int chance=3;
char infix[N]; //中缀表达式(未分离,都在一个字符串里)
char infix2[N];
char expression[N][10]; //保存预处理过的表达式,也就是每个元素都分离过的表达式
char suffix[N][10]; //保存后缀表达式的操作数
int count;//表达式中元素的个数(一个完整到数字(可能不止一位数)或者符号)
int suffixLength;//后缀表达式的长度
struct fra{
char str[10];//为了在栈中记录符号,所以包括数字全部用char记录
double up;//分子
double down;//分母
};
int len = 0;
FILE *fp = fopen("1.txt", "r");
long answer;
fra answer1,answer2;
class cal{
private:
int level(char a){
switch(a){
case '#':return 0;
case '+':
case '-':return 1;
case '*':
case '/':return 2;
case '^':return 3;
default:break;
}
return -1;
}
int isDigital(char x){
if( (x>='0'&&x<='9') )
return 1;
return 0;
}
int isNumber(char *str){
int i;
for(i=0;str[i];i++){
if(isDigital(str[i])==0)return 0;
}
return 1;
}
/*************************************
预处理中缀表达式,把连续的字符分离成不同的元素,用字符串数组(expression[][])
保存,方便后面的计算,因为这里考虑了运算数可能不全是个位数
比如:(12+3)
在处理成后缀表达式时,是123+,容易产生歧义(1+23 ? 12+3)
*************************************/
void pretreatment(char *str){
int i,j,numberFlag;
char temp[3];
char number[10];
count=0;
numberFlag=0;
for(j=0,i=0;str[i];i++){
if(isDigital(str[i])==0){
if(numberFlag==1){
number[j]=0;
strcpy(expression[count++],number);
j=0;
numberFlag=0;
}
if(str[i]!=' '){
temp[0]=str[i];temp[1]=0;
strcpy(expression[count++],temp);
}
}
else {
numberFlag=1;
number[j++]=str[i];
}
}
// puts("分离后的表达式为");
// for(i=0;i<count;i++){
// printf("%s ",expression[i]);
// }puts("");
// puts("");
}
/*****************************************
中缀表达式 转 后缀表达式
遍历字符串,对于str[i]
str[i]是运算数(或者是字母代替的运算变量)输出;
str[i]是符号,有两种情况
(1),是右括号,栈顶元素输出,直到与str[i]匹配的左括号出栈(左括号不用输出打印)
(2),是运算符,判断str[i]与栈顶元素的优先级,str[i]优先级 不高于 栈顶符号,则栈
顶元素输出,直到栈空 或者 栈顶符号优先级低于str[i]
*****************************************/
void infix_to_suffix(char str[N][10]){
memset(suffix,0,sizeof(suffix));
suffixLength=0;
stack <char*> st;
int i=0;
char Mark[2]="#";
st.push(Mark);
do{
if(isNumber(str[i])==1)//运算数直接保存到后缀表达式中
strcpy(suffix[suffixLength++],str[i]);
else if(str[i][0]=='(') //是 左括号,直接入栈
st.push(str[i]);
else if(str[i][0]==')'){ //是 右括号,栈顶出栈,直到与其匹配的左括号出栈
while( strcmp(st.top(),"(")!=0 ){
char temp[10];
strcpy(temp,st.top());
strcpy(suffix[suffixLength++],temp);
st.pop();
}
st.pop();
}
else if( strcmp(st.top(),"(")==0 )//是 运算符,且栈顶是左括号,则该运算符直接入栈
st.push(str[i]);
else { //是 运算符,且栈顶元素优先级不小于运算符,则栈顶元素一直
//出栈,直到 栈空 或者 遇到一个优先级低于该运算符的元素
while( !st.empty() ){
char temp[10];
strcpy(temp,st.top());
if( level(str[i][0]) > level(temp[0]) )
break;
strcpy(suffix[suffixLength++],temp);
st.pop();
}
st.push(str[i]);
}
i++;
}while(str[i][0]!=0);
while( strcmp(st.top(),"#")!=0 ){ //将栈取空结束
char temp[10];
strcpy(temp,st.top());
strcpy(suffix[suffixLength++],temp);
st.pop();
}
// puts("后缀表达式为:");
// for(i=0;i<suffixLength;i++){
// printf("%s",suffix[i]);
// }puts("");
// puts("");
}
//////////////////////////////////////////////////
int gcd(int a,int b) { //最大公约数
if(b == 0)
return a;
else
return gcd(b,a % b);
}
void simplify(fra aaa){
int a=gcd(aaa.down,aaa.up);
aaa.up=aaa.up/a;
aaa.down=aaa.down/a;
// printf("%.1lf/%.1lf\n",aaa.up,aaa.down);
// puts("计算出后缀表达式的结果:");
/* if(aaa.down==1)
{
printf("%lf\n",aaa.up);
}
else
{
printf("%lf/%lf\n",aaa.up,aaa.down);
}
*/
if(timer==0)
{
answer1.up=aaa.up;
answer1.down=aaa.down;
timer++;
}
else
{
answer2.up=aaa.up;
answer2.down=aaa.down;
timer--;
}
// printf("%d\n%lf %lf\n%lf %lf\n",timer,answer1.up,answer1.down,answer2.up,answer2.down);
}
/**************************************
计算后缀表达式的值
**************************************/
fra kt[N];
int stackTop;
void getResult(char str[N][10]){
// fra fras[N];
stackTop=0;
/*这里要注意,内存的分配方案导致 i 的位置就在temp[9]旁边,然后strcpy()函数直接拷贝内存的话,在temp越界情况下会覆盖 i 的值*/
int i;
// double temp;
for(i=0;i<suffixLength;i++){
if(isNumber(str[i])==1){
// strcpy(kt[stackTop++].str,str[i]);
kt[stackTop].up=atof(str[i]);
kt[stackTop].down=1;
stackTop++;
}
else {
// char a[10],b[10];
fra na,nb,nc;
// strcpy(a,kt[stackTop-1].str);
na.up = kt[stackTop-1].up;
na.down=kt[stackTop-1].down;
//fras[stackTop-1].up=na;
//fras[stackTop-1].down=1;
stackTop--;
// strcpy(b,kt[stackTop-1].str);
nb.up = kt[stackTop-1].up;
nb.down=kt[stackTop-1].down;
//fras[stackTop-1].up=nb;
//fras[stackTop-1].down=1;
stackTop--;
if(str[i][0]=='+')
{
nc.down=nb.down*na.down;
nc.up=nb.up*na.down+na.up*nb.down;
}
else if(str[i][0]=='-')
{
nc.down=nb.down*na.down;
nc.up=nb.up*na.down-na.up*nb.down;
}
else if(str[i][0]=='*')
{
nc.up=nb.up*na.up;
nc.down=nb.down*na.down;
}
else if(str[i][0]=='/')
{
nc.down=nb.down*na.up;
nc.up=nb.up*na.down;
}
// sprintf(temp,"%lf",nc);
//strcpy(kt[stackTop++].str,temp);
kt[stackTop].down=nc.down;
kt[stackTop].up=nc.up;
stackTop++;
}
}
sprintf(kt[stackTop-1].str,"%lf",kt[stackTop-1].up/kt[stackTop-1].down);
//strcpy(kt[stackTop++],temp);
/* char as[N];
gets(as);
if(as==kt[stackTop-1].str)
puts(" right");
else{
puts("wrong");
}
*/
simplify(kt[stackTop-1]);
for(i=0;i<suffixLength;i++){
memset(infix,0,sizeof(infix));
memset(suffix,0,sizeof(suffix));
memset(expression,0,sizeof(expression));
}
}
// char szTest[1000] = {0};
void checkanswer()
{
// getchars();
// printf("%d/%d\n%d/%d",answer1.up,answer1.down,answer2.up,answer2.down);
if(answer1.up==answer2.up&&answer1.down==answer2.down)
{
printf("right\n");
ri++;
}
else{
printf("wrong");
if(answer1.down!=1)
{
printf("\nthe answer is %lf/%lf\n",answer1.up,answer1.down);
}
else{
printf("\nthe answer is %lf\n",answer1.up);
}wr++;
}
}
public:
void getanswer(char str[N]){
// gets
char temp[N];
strcpy(temp,str);
pretreatment( strcat(temp," ") );
infix_to_suffix(expression);
getResult(suffix);
checkanswer();
printf("正确回答%d题\n错误回答%d题\n",ri,wr);
}
void work(char str[N])
{
char temp[N];
// while(gets(infix)){
// getchars();
// while(z<3){
// if(!feof(fp))
// {
// memset(infix, 0, sizeof(infix));
// fgets(infix, sizeof(infix) - 1, fp); // 包含了\n
// printf("%s", infix);
// }
// getchars();
// printf("%s",str);
strcpy(temp,str);
pretreatment( strcat(temp," ") );
infix_to_suffix(expression);
getResult(suffix);
// getchars();
}
};
class tuxinghua{
private:
int kh;//括号总数
int stime;//左括号剩余可生成次数
int lef;
void fcheck(char str[N],int x){//符号检查
char fuhao[2];
// srand((unsigned)time(NULL));
if(x>=0&&x<=21)
{strcpy(fuhao,"+");}
else if(x>=22&&x<=43)
{strcpy(fuhao,"-");}
else if (x>=44&&x<=65)
{strcpy(fuhao,"*");}
else if (x>=66&&x<=87)
{strcpy(fuhao,"/");}
// else
// {printf("括号");}
strncat(str,fuhao,1);
}
void ncheck(char str[N],int x){//数字检查
char shuzi[2];
int as;
// Sleep(10);
// srand((unsigned)time(NULL));
for(int i=0;i<x;i++)
{
// int n=rand()%10;
as=rand()%10;
// printf("\n%d\n",rand()%100);
sprintf(shuzi, "%d", as);
strncat(str,shuzi,1);
}
}
void left(char str[N])
{
// int i=x;
char zuo[2];
int b=rand()%3;
if(b==1&&stime<=kh&&stime>=1){
strcpy(zuo,"(");
strncat(str,zuo,1);
// strncat(str,"(",2);
//kh--;
lef++;
stime--;
}
}
void right(char str[N]){
int b=rand()%5;
char zuo[2];
if(b==1&&lef>=1){
strcpy(zuo,")");
strncat(str,zuo,1);
// kh--;
lef--;
}
}
public:
int tgetchars(char str[N]){
if( gets(str))
return 1;
else
return 0;
}
int shengcheng(char str[N]){
int clen;
int max;
int a=0;
int f;
lef=0;
printf("输入长度(奇数)");
scanf("%d",&clen);
printf("数字取值范围(位数)");
scanf("%d",&max);
printf("最多括号个数");
scanf("%d",&kh);
stime=kh;
srand((unsigned)time(NULL));
while(1)
{
while(a<clen)
{
f=rand()%88;
if(a%2==0)
{
left(str);
ncheck(str,max);
}
else
{
right(str);
fcheck(str,f);
}
a++;
}
if(lef==0)
break;
else {
// printf("aa");
lef=0;
memset(infix,0,sizeof(infix));
a=0;
stime=kh;
continue;
}
}
return 1;
}
};
void main(){
cal ca;
tuxinghua x;
//char infix[N];
// getc a;
int z=0;
while(1){
x.shengcheng(infix);
printf("%s=\n",infix);
ca.work(infix);
// x.tgetchars(infix);
// gets(infix);
scanf("%s",&infix);
// printf("%s=\n",infix);
// ca.work(infix);
ca.getanswer(infix);
// z++;
}
}