结对编程总结
结对编程总结
我(王靖翔)和我的搭档(张日勇)在个人项目上都采取了c++,所以在结对项目上,我们只能勇敢地踏入未知的领域-qT。这次结对开发基于桌面的应用程序,非web端的出题软件,是一次前所未有的挑战。我负责的是后端,搭档负责的是前端qt领域的设计。
我们通过讨论,决定以我搭档的个人项目作为结对开发的底层代码,因为他的代码是面向对象,而我的是纯面向过程。他出的题目特点鲜明,比较好通过代码计算出正确的答案,而我的就比较复杂,括号较多而繁琐。
首先我先研究他的个人项目,体会他的代码逻辑,并总结分析他的题目的特点,以便后面代码计算答案的时候可以精准切入。一开始,我百度到了一种算法,叫做逆波兰式的一种基于递归,在生成题目的同时也生成答案的算法。然后开始去研究,途中发现,如果采取逆波兰式的算法,那会对队友的代码几乎要进行原则上的重构,所以,我放弃了这种思维深度极大,改造及其复杂的算法,开始寻找新的算法。我考虑的第二种算法是基于栈的优先级来处理括号的方法,过了不长时间,也成功地能够解决带有括号计算的运算。但最终我没有选择栈的这种计算方法,因为我想,大家都是基于栈去做的应该很多,很多都是最后直接得到答案,我就想能不能有自己的特色。一般来说,特色一般在前端的设计上展现,所以我采取了最原始的对字符串拆解括号,提取字符串,输入输出流,转化数据类型,各种运算情况的分析,终于实现了带基本运算过程的算法,由于时间比较紧急,该算法的复用的效率有待商榷,这是很遗憾之处。下面是自己在处理运算的时候算法的一些代码的截图
#include <iostream> #include <sstream> #include <iomanip> #include <math.h> using namespace std; // 对式子里括号中的括号进行运算 string deleteBrackets(string topic) { for (int i = 0 ; i < topic.length()-1 ; i++) { //找到第一个左括号 if (topic[i] == '(') { for (int j = i + 1 ; j < topic.length() ; j++) { //找到第一个右括号 if(topic[j]==')') { // 去掉括号后括号的子算式 (1+2) -> 1+2 string topic_sub_formula(topic,i+1,j-(i+1)); // 计算括号里面的加法 if (topic_sub_formula.find('+') != string::npos) { // 左边的数字(字符串型) string left_num_string(topic_sub_formula , 0 , topic_sub_formula.find('+')-0); // 右边的数字(字符串型) string right_num_string(topic_sub_formula , topic_sub_formula.find('+') + 1 , j - (topic_sub_formula.find('+')+1)); // 左右边的数字(浮点型) double left_num_double , right_num_double; // 创建字符串型转为浮点型而设置的流 stringstream ss; ss << left_num_string; ss >> left_num_double; ss.clear(); ss << right_num_string; ss >> right_num_double; ss.clear(); // 计算 double add_result_double; string add_result_string; add_result_double = left_num_double + right_num_double; ss << add_result_double; ss >> add_result_string; ss.clear(); // 将子式的结果加到题目表达式中,形成新题目 string new_topic_left(topic,0,i-0); string new_topic_right(topic,j+1); topic = new_topic_left + add_result_string + new_topic_right; cout << topic << endl; // 中间答案 break; } //计算括号里面的减法 if (topic_sub_formula.find('-') != string::npos) { // 左边的数字(字符串型) string left_num_string(topic_sub_formula , 0 , topic_sub_formula.find('-')-0); // 右边的数字(字符串型) string right_num_string(topic_sub_formula , topic_sub_formula.find('-') + 1 , j - (topic_sub_formula.find('-')+1)); // 左右边的数字(浮点型) double left_num_double , right_num_double; // 创建字符串型转为浮点型而设置的流 stringstream ss; ss << left_num_string; ss >> left_num_double; ss.clear(); ss << right_num_string; ss >> right_num_double; ss.clear(); // 计算 double sub_result_double; string sub_result_string; sub_result_double = left_num_double - right_num_double; ss << sub_result_double; ss >> sub_result_string; ss.clear(); // 将子式的结果加到题目表达式中,形成新题目 string new_topic_left(topic,0,i-0); string new_topic_right(topic,j+1); topic = new_topic_left + sub_result_string + new_topic_right; // 如果计算的过程中产生了负数,就再负数的两头加上括号 if(sub_result_double < 0) { topic = new_topic_left + "("+sub_result_string+")" + new_topic_right; } cout << topic << endl; //中间答案 break; } //计算括号里面的乘法 if (topic_sub_formula.find('*') != string::npos) { // 左边的数字(字符串型) string left_num_string(topic_sub_formula , 0 , topic_sub_formula.find('*')-0); // 右边的数字(字符串型) string right_num_string(topic_sub_formula , topic_sub_formula.find('*') + 1 , j - (topic_sub_formula.find('*')+1)); // 左右边的数字(浮点型) double left_num_double , right_num_double; // 创建字符串型转为浮点型而设置的流 stringstream ss; ss << left_num_string; ss >> left_num_double; ss.clear(); ss << right_num_string; ss >> right_num_double; ss.clear(); // 计算 double mul_result_double; string mul_result_string; mul_result_double = left_num_double * right_num_double; ss << mul_result_double; ss >> mul_result_string; ss.clear(); // 将子式的结果加到题目表达式中,形成新题目 string new_topic_left(topic,0,i-0); string new_topic_right(topic,j+1); topic = new_topic_left + mul_result_string + new_topic_right; cout << topic << endl; //中间答案 break; } //计算括号里面的除法 if (topic_sub_formula.find('/') != string::npos) { // 左边的数字(字符串型) string left_num_string(topic_sub_formula , 0 , topic_sub_formula.find('/')-0); // 右边的数字(字符串型) string right_num_string(topic_sub_formula , topic_sub_formula.find('/') + 1 , j - (topic_sub_formula.find('/')+1)); // 左右边的数字(浮点型) double left_num_double , right_num_double; // 创建字符串型转为浮点型而设置的流 stringstream ss; ss << left_num_string; ss >> left_num_double; ss.clear(); ss << right_num_string; ss >> right_num_double; ss.clear(); // 计算 double div_result_double; string div_result_string; div_result_double = left_num_double / right_num_double ; ss << div_result_double; ss >> div_result_string; ss.clear(); // 将子式的结果加到题目表达式中,形成新题目 string new_topic_left(topic,0,i-0); string new_topic_right(topic,j+1); topic = new_topic_left + div_result_string + new_topic_right; cout << topic << endl; //中间答案 break; } //计算括号里面的平方 if (topic_sub_formula.find("^2") != string::npos) { // 平方的底数 (5^2) -> 5 string num_string(topic_sub_formula , 0 , topic_sub_formula.find("^2")-0); // 将字符串型的底数转换成数字而创建的流 stringstream ss; ss << num_string; int num_int; ss >> num_int; ss.clear(); // 平方的结果 int square_result_int; string square_result_string; square_result_int = num_int * num_int; // 结果转换成字符串 ss << square_result_int; ss >> square_result_string; ss.clear(); // 将平方的结果加入到题目中 string new_topic_left(topic,0,i-0); string new_topic_right(topic,j+1); topic = new_topic_left + square_result_string + new_topic_right; cout << topic << endl; //中间答案 break; } //计算括号里面的开方 if (topic_sub_formula.find("√") != string::npos) { // 得到根号下面的数字(字符串型) string num_string(topic_sub_formula , 2 , j-2); // 转出int型而创建的流 stringstream ss; ss << num_string; int num_int; ss >> num_int; ss.clear(); // 计算开方结果 int sqrt_result_int; string sqrt_result_string; sqrt_result_int = sqrt(num_int); ss << sqrt_result_int; ss >> sqrt_result_string; ss.clear(); // 将开方的结果加入到题目中 string new_topic_left(topic,0,i-0); string new_topic_right(topic,j+1); topic = new_topic_left + sqrt_result_string + new_topic_right; cout << topic << endl; //中间答案 break; } //计算括号里面的正弦 if (topic_sub_formula.find("sin") != string::npos) { // 将sin后的数字提取出来 string num_string(topic_sub_formula , 3 , j-3); stringstream ss; ss << num_string; int num_int; ss >> num_int; ss.clear(); double sin_result_double; string sin_result_string; // 三角函数知识 if (num_int >= 360) { num_int = num_int % 360; } switch (num_int){ case 0 : sin_result_double = 0; break; case 30 : sin_result_double = 0.5; break; case 45 : sin_result_double = 0.707; break; case 60 : sin_result_double = 0.866; break; case 90 : sin_result_double = 1; // break; case 120 : sin_result_double = 0.866; break; case 135 : sin_result_double = 0.707; break; case 150 : sin_result_double = 0.5; break; case 180 : sin_result_double = 0; break; case 210 : sin_result_double = -0.5; break; case 225 : sin_result_double = -0.707; break; case 240 : sin_result_double = -0.866; break; case 270 : sin_result_double = -1 ; break; case 300 : sin_result_double = -0.866; break; case 315 : sin_result_double = -0.707; break; case 330 : sin_result_double= -0.5; break; } ss << sin_result_double; ss >> sin_result_string; ss.clear(); string new_topic_left(topic,0,i-0); string new_topic_right(topic,j+1); topic = new_topic_left + sin_result_string + new_topic_right; // 如果值出现负号就加括号 if(sin_result_double < 0) { topic = new_topic_left + "("+sin_result_string+")" + new_topic_right; } cout << topic << endl; //中间答案 break; } //计算括号里面的余弦 if (topic_sub_formula.find("cos") != string::npos) { // 将cos后的数字提取出来 string num_string(topic_sub_formula , 3 , j-3); stringstream ss; ss << num_string; int num_int; ss >> num_int; ss.clear(); double cos_result_double; string cos_result_string; if (num_int >= 360) { num_int = num_int % 360; } switch (num_int) { case 0 : cos_result_double= 1; break; case 30 : cos_result_double= 0.866; break; case 45 : cos_result_double= 0.707; break; case 60 : cos_result_double= 0.5; break; case 90 : cos_result_double= 0; break; case 120 : cos_result_double = -0.5; break; case 135 : cos_result_double = -0.707; break; case 150 : cos_result_double = -0.866 ; break; case 180 : cos_result_double = -1 ; break; case 210 : cos_result_double= -0.866; break; case 225 : cos_result_double= -0.707; break; case 240 : cos_result_double= -0.5; break; case 270 : cos_result_double= 0; break; case 300 : cos_result_double= 0.5; break; case 315 : cos_result_double= 0.707; break; case 330 : cos_result_double= 0.866; break; } ss << cos_result_double; ss >> cos_result_string; ss.clear(); string new_topic_left(topic,0,i-0); string new_topic_right(topic,j+1); topic = new_topic_left + cos_result_string + new_topic_right; // 如果值出现负号就加括号 if(cos_result_double < 0) { topic = new_topic_left + "("+cos_result_string+")" + new_topic_right; } cout << topic << endl; //中间答案 break; } //计算括号里面的正切 if (topic_sub_formula.find("tan") != string::npos) { // 将tan后的数字提取出来 string num_string(topic_sub_formula , 3 , j-3); stringstream ss; ss << num_string; int num_int; ss >> num_int; ss.clear(); double tan_result_double; string tan_result_string; if (num_int >= 360) { num_int = num_int % 360; } switch (num_int) { case 0 : tan_result_double = 0; break; case 30 : tan_result_double = 0.577; break; case 45 : tan_result_double = 1; break; case 60 : tan_result_double = 1.732; break; case 120 : tan_result_double = -1.732; break; case 135 : tan_result_double = -1; break; case 150 : tan_result_double = -0.577; break; case 180 : tan_result_double = 0; break; case 210 : tan_result_double = 0.577; break; case 225 : tan_result_double = 1; break; case 240 : tan_result_double = 1.732; break; case 300 : tan_result_double = -1.732; break; case 315 : tan_result_double = -1; break; case 330 : tan_result_double = -0.577; break; } ss << tan_result_double; ss >> tan_result_string; ss.clear(); string new_topic_left(topic,0,i-0); string new_topic_right(topic,j+1); topic = new_topic_left + tan_result_string + new_topic_right; // 如果值出现负号就加括号 if(tan_result_double < 0) { topic = new_topic_left + "("+tan_result_string+")" + new_topic_right; } cout << topic << endl; //中间答案 break; } } } } } return topic; } //计算乘除 string calcMulDiv(string topic) { int i ; for(i = 0; i < topic.length()-1; i++) { if (topic[i]=='*' || topic[i] == '/' ) { if (topic[i+1] != '(' && topic[i-1] != ')') { //寻找后面一个不为数字和小数点的位置 for (int j = i+1 ; j < topic.length() ; j++) { if ((topic[j]-'0' < 0 || topic[j]-'0' > 9) && topic [j] != '.') { //再找一个前面不为数字和小数点的位置 //cout << j << endl; for (int k = i-1 ; k >= 0 ; k --) { if ((topic[k]-'0' < 0 || topic[k]-'0' > 9 ) && topic [k] != '.')// { //cout << k << endl; string left_num_string(topic , k+1 , i - (k+1)); string right_num_string(topic , i+1 , j - (i+1) ); double left_num_double , right_num_double; stringstream ss; ss << left_num_string; ss >> left_num_double; ss.clear(); ss << right_num_string; ss >> right_num_double; ss.clear(); double result_double; if (topic[i] == '*') { result_double = left_num_double * right_num_double ; } if (topic[i] == '/') { if(right_num_double == 0) { cout<<123<<endl; return ""; } result_double = left_num_double / right_num_double ; cout<<456<<endl; } string result_string; ss << result_double; ss >> result_string; ss.clear(); string new_topic_left(topic,0,k+1-0); string new_topic_right(topic,j); topic = new_topic_left + result_string + new_topic_right; i = 0; cout << topic <<endl; //中间答案 break; } if (k==0) { //cout << k << endl; string left_num_string(topic , k , i - (k)); string right_num_string(topic , i+1 , j - (i+1) ); double left_num_double , right_num_double; stringstream ss; ss << left_num_string; ss >> left_num_double; ss.clear(); ss << right_num_string; ss >> right_num_double; ss.clear(); double result_double; if (topic[i] == '*') { result_double = left_num_double * right_num_double ; } if (topic[i] == '/') { result_double = left_num_double / right_num_double ; } string result_string; ss << result_double; ss >> result_string; ss.clear(); string new_topic_right(topic,j); topic =result_string + new_topic_right; i = 0; cout << topic <<endl; //中间答案 break; } } break; } } } else// 5*(-49)+1 1+5*(-49) (-1)*(-1) 1+(-1)*(-1) (-1)*5 1+(-1)*5 { //cout<<123<<endl; if(topic[i-1] != ')' && topic[i+1] == '(')// 1+0.5*(-49) { //cout<<123<<endl; for (int j = i+1 ; j < topic.length() ; j++) { if(topic[j] == ')') { //cout << j <<endl; for(int k = i-1 ; k >= 0 ; k--) { if ((topic[k]-'0' < 0 || topic[k]-'0' > 9) && topic [k] != '.') { string left_num_string(topic , k+1 , i - (k+1)); //cout << left_num_string<<endl; string right_num_string(topic , i+3 , j - (i+3) ); //cout << right_num_string<<endl; double left_num_double , right_num_double; stringstream ss; ss << left_num_string; ss >> left_num_double; ss.clear(); ss << right_num_string; ss >> right_num_double; ss.clear(); double result_double; if (topic[i] == '*') { result_double = left_num_double * right_num_double ; result_double = -result_double; } if (topic[i] == '/') { result_double = left_num_double / right_num_double ; result_double = -result_double; } string result_string; ss << result_double; ss >> result_string; ss.clear(); string new_topic_left(topic,0,k+1-0); string new_topic_right(topic,j+1); topic = new_topic_left +"("+ result_string+ ")" + new_topic_right; cout << topic <<endl; i = 0; break; } if (k == 0)// 5*(-48) { string left_num_string(topic , k , i - (k)); string right_num_string(topic , i+3 , j-(i+3) ); double left_num_double , right_num_double; stringstream ss; ss << left_num_string; ss >> left_num_double; ss.clear(); ss << right_num_string; ss >> right_num_double; ss.clear(); double result_double; if (topic[i] == '*') { result_double = left_num_double * right_num_double ; result_double = -result_double; } if (topic[i] == '/') { result_double = left_num_double / right_num_double ; result_double = -result_double; } string result_string; ss << result_double; ss >> result_string; ss.clear(); string new_topic_right(topic,j+1); topic = "("+result_string+")" + new_topic_right; cout << topic << endl; i=0; break; } } break; } } } if(topic[i-1]==')'&&topic[i+1]=='(') //(-49)*(-49) 1+(-49)*(-49) { for (int j = i+1 ; j < topic.length() ; j++) { if(topic[j] == ')') { for(int k = i-1 ; k >= 0 ; k--) { if (topic[k]== '(') //1+(-49)*(-49) { string left_num_string(topic , k+2 , i-1 - (k+2)); cout << left_num_string<<endl; string right_num_string(topic , i+3 , j - (i+3) ); cout << right_num_string<<endl; double left_num_double , right_num_double; stringstream ss; ss << left_num_string; ss >> left_num_double; ss.clear(); ss << right_num_string; ss >> right_num_double; ss.clear(); double result_double; if (topic[i] == '*') { result_double = left_num_double * right_num_double ; //result_double = -result_double; } if (topic[i] == '/') { result_double = left_num_double / right_num_double ; //result_double = -result_double; } string result_string; ss << result_double; ss >> result_string; ss.clear(); string new_topic_left(topic,0,k-0); string new_topic_right(topic,j+1); topic = new_topic_left + result_string+ new_topic_right; cout << topic << endl; i = 0; break; } if (k==0)// (-49)*(-49) { string left_num_string(topic , k+2 , i-1 - (k+2)); string right_num_string(topic , i+3 , j-(i+3) ); double left_num_double , right_num_double; cout << left_num_string << " "<<right_num_string<<endl; stringstream ss; ss << left_num_string; ss >> left_num_double; ss.clear(); ss << right_num_string; ss >> right_num_double; ss.clear(); double result_double; if (topic[i] == '*') { result_double = left_num_double * right_num_double ; //result_double = -result_double; } if (topic[i] == '/') { result_double = left_num_double / right_num_double ; //result_double = -result_double; } string result_string; ss << result_double; ss >> result_string; ss.clear(); string new_topic_right(topic,j+1); topic = result_string + new_topic_right; cout << topic << endl; i=0; break; } } break; } } } if(topic[i-1] ==')' && topic[i+1] != '(') //(-49)*5+ 1+(-49)*5+ { for (int j = i+1 ; j < topic.length() ; j++) { if((topic[j]-'0' < 0 || topic[j]-'0' > 9) && topic [j] != '.') { for(int k = i-1 ; k >= 0 ; k--) { if (topic[k] == '(' && k != 0) //1+(-49)*5+ { string left_num_string(topic , k+2 , i-1 - (k+2)); cout << left_num_string << endl; string right_num_string(topic , i+1 , j - (i+1) ); cout << right_num_string << endl; double left_num_double , right_num_double; stringstream ss; ss << left_num_string; ss >> left_num_double; ss.clear(); ss << right_num_string; ss >> right_num_double; ss.clear(); double result_double; if (topic[i] == '*') { result_double = left_num_double * right_num_double ; result_double = -result_double; } if (topic[i] == '/') { result_double = left_num_double / right_num_double ; result_double = -result_double; } string result_string; ss << result_double; ss >> result_string; ss.clear(); string new_topic_left(topic,0,k-0); string new_topic_right(topic,j); topic = new_topic_left +"(" +result_string+")"+new_topic_right; cout << topic << endl; i = 0; break; } if (k == 0)// (-49)*5+ { string left_num_string(topic , k+2 , i-1 - (k+2)); string right_num_string(topic , i+1 , j-(i+1) ); double left_num_double , right_num_double; cout << left_num_string << " "<<right_num_string<<endl; stringstream ss; ss << left_num_string; ss >> left_num_double; ss.clear(); ss << right_num_string; ss >> right_num_double; ss.clear(); double result_double; if (topic[i] == '*') { result_double = left_num_double * right_num_double ; result_double = -result_double; } if (topic[i] == '/') { result_double = left_num_double / right_num_double ; result_double = -result_double; } string result_string; ss << result_double; ss >> result_string; ss.clear(); string new_topic_right(topic,j); topic = "("+result_string+")" + new_topic_right; cout << topic << endl; i=0; break; } } break; } } } } } } return topic; } //删除加减法前的括号 string dealwithBrackets(string topic) { for (int i = 0 ; i < topic.length() -1; i++) { if(topic[i] == '(' && i != 0) { for(int j = i+1 ; j < topic.length() ; j++) { if(topic[i-1] == '+') { if(topic[j] == ')') { string left(topic,0,i-1-0); //cout<<left<<endl; string middle(topic,i+1,j-(i+1)); //cout<<middle<<endl; string right(topic,j+1); //cout<<middle<<endl; topic = left + middle + right; i=0; break; } } if(topic[i-1] == '-') { if(topic[j] == ')') { string left(topic,0,i-1-0); //cout<<left<<endl; string middle(topic,i+2,j-(i+2)); //cout<<middle<<endl; string right(topic,j+1); //cout<<middle<<endl; topic = left +"+"+ middle + right; i=0; break; } } } } if(topic[0] == '(') { for(int j = i + 1 ; j < topic.length() ; j++) { if (topic[j] == ')') { string left(topic , 1 , j-1); string right(topic ,j+1); topic = left + right; i = 0; break; } } } } return topic; } string calcAddSub(string topic) { //用来求和的一个变量 double sum; for(int i = 0 ; i < topic.length() ; i++) { //第一位是数字的情况 if(i == 0 && (topic[i]-'0' >= 0 && topic[i]-'0' <= 9)) { for(int j = i+1 ; j < topic.length();j++) { if((topic[j]-'0' < 0 || topic[j]-'0' > 9) && topic [j] != '.') { string num_string(topic,i,j-i); stringstream ss; ss << num_string; double num_double; ss >> num_double; sum=sum+num_double; break; } } } // 负号开头的情况 if(topic[i]=='-') { for(int j=i+1; j <topic.length();j++) { if((topic[j]-'0' < 0 || topic[j]-'0' > 9) && topic [j] != '.') { string num_string(topic,i,j-i); //cout<<num_string<<endl; stringstream ss; ss << num_string; double num_double; ss >> num_double; sum=sum+num_double; break; } } } //正号开头的情况 if(topic[i]=='+') { for(int j=i+1; j <topic.length();j++) { if((topic[j]-'0' < 0 || topic[j]-'0' > 9) && topic [j] != '.') { string num_string(topic,i+1,j-(i+1)); //cout<<num_string<<endl; stringstream ss; ss << num_string; double num_double; ss >> num_double; sum=sum+num_double; break; } } } } stringstream ss; ss << sum; string sum_string; ss >> sum_string; return sum_string; } string getAnswer(string topic) { //去除括号后的题目 string no_brackets_topic = deleteBrackets(topic); // 去除除号后为0的特殊情况 if(no_brackets_topic.find("/0") != string::npos) { if(no_brackets_topic.find("/0.") == string::npos) { //cout << 123 << endl; return ""; } } // 先计算乘除 string no_mul_div_topic = calcMulDiv(no_brackets_topic); if(no_mul_div_topic=="") { return ""; } if (no_mul_div_topic.find('e') != string::npos) { return ""; } // 处理乘除过程中的括号 string s = dealwithBrackets(no_mul_div_topic); string final_answer = calcAddSub(s); return final_answer; } int main() { // 题目输入 string topic = "(sin60)*(sin30)+(6^2)*(√25)="; // 0 1 2 (-49)*5+(4-6)*(1-49)+50/(56-61)+(4-8)*(5-9)+(6-8)*2+(6-9)*3 string answer = getAnswer(topic); cout<<answer<<endl; }
个人项目转化成结对编程的时候,双方约定好了留函数接口,我将代码封装成多个功能函数,与搭档的接口对应。
最后,成功实现了软件的开发。
下面简单看下大致效果:







总结:
- 如何实现优雅的算法是一件难度很大的事情,简洁高效是我们应该追求的目标
- 如果有机会,一定会对自己的算法进行代码复用上的一种优化,提高自己代码的性能。
- 讨论是解决问题的好方法,合理的分工,团队合作也是项目能完成的重大因素。

浙公网安备 33010602011771号