结对项目
一、Github地址
https://github.com/sunandsheep/PARTNER.git
结对成员:高嘉淳(3118005047),程囿阳(3118005046)
二、PSP表格
|
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
|
Planning |
计划 |
120 |
|
|
· Estimate |
· 估计这个任务需要多少时间 |
120 |
|
|
Development |
开发 |
1520 |
|
|
· Analysis |
· 需求分析 (包括学习新技术) |
180 |
|
|
· Design Spec |
· 生成设计文档 |
60 |
|
|
· Design Review |
· 设计复审 (和同事审核设计文档) |
120 |
|
|
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
20 |
|
|
· Design |
· 具体设计 |
120 |
|
|
· Coding |
· 具体编码 |
600 |
|
|
· Code Review |
· 代码复审 |
120 |
|
|
· Test |
· 测试(自我测试,修改代码,提交修改) |
300 |
|
|
Reporting |
报告 |
120 |
|
|
· Test Report |
· 测试报告 |
60 |
|
|
· Size Measurement |
· 计算工作量 |
30 |
|
|
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
30 |
|
|
合计 |
|
1760 |
|
三、效能分析
10000道题目,数值范围为20的分析
对给定题目文件和答案文件判断(10000道题目)
四、设计实现过程
1.解题流程:
由于对其他语言不太精通,故该程序通过C语言和C++混合实现。一开始按照计划确定了流程。跟着流程走,随后接触题目,我们二人都进行了需求的分析,并交换了彼此的意见。确定合作方式是分别对函数处理。然后确定代码风格规范,建立框架;各自实现需求,找时间讨论完善,发现一开始的框架并不良好,故重新构造。重复 写代码——测试——找BUG——讨论——写代码 之后完成了一些需求,最后进行效能分析并总结写报告。
2.需求分析:
需求1、2:生成题目的个数以及控制题目中数值的范围并不难解决;
需求3:不能产生负数一开始草草了事,后面才明白需要在计算过程中进行非负判断,并作出调整;
需求4:真分数的存在意味着在程序中进行判断真分数和自然数的区别,对数据进行细节处理。
需求5:运算符个数不超过3个,容易解决。该需求限制了题目创建的大小、难度,给定了边界,促进了其他需求的实现,提供了思路。
需求6:重复判断,是我认为很难的一个任务,一开始把该需求放一边,等其他需求大致完成了,才开始完成该需求。解决方法在于:对结果、运算符数量、运算顺序以及数字之间的比对的判断。
需求7:题目写入文件,一开始框架建立不好,一些变量的定义没能简单解决,效率低,导致浪费不少时间在重复工作上。后面随着程序的基本框架重构完成,使用了一种更简单高效的写入文件fopen()和fprintf()函数完成。
需求8:操作类似需求7,难度在于对答案的计算。
需求9:对所给的题目和答案进行判断,需要先从题目提取出各个参数,然后计算出答案,再和所给的答案进行比较。由于c语言没有数学的×, ÷符号,导致在提取这两个运算符的参数上面浪费了很多时间,后面把题目的×, ÷更改为*/后测试基本成功了。不过思路还是有些不清晰,导致debug也花了不少时间。
3.项目结构

五、代码说明
创建题目代码
1 //创建题目 2 void CreatQuestions(int number, int range) 3 { 4 int num_ope, num_fig, type_fig, t; 5 int figure[8], ans[3]; 6 char operate[3]; 7 8 srand(time(NULL)); //确保不是伪随机 9 title_num = 0; 10 11 FILE* question_file; //打开相应文件 12 FILE* answer_file; 13 if ((question_file = fopen("Exercise.txt", "a+")) == NULL) 14 { 15 printf("You can't open the file!\n"); 16 exit(1); 17 } 18 if ((answer_file = fopen("Answers.txt", "a+")) == NULL) 19 { 20 printf("You can't open the file!\n"); 21 exit(1); 22 } 23 24 while (number != title_num) 25 { 26 int i, rand1, tag_ope = 10; //tag_ope赋值10 27 num_ope = (rand() % 3) + 1; //确定运算符数 28 num_fig = num_ope + 1; //数字个数 是 运算符数+1 29 30 //数字为自然数时为1,真分数时下面代码会对相应分母赋值 31 figure[4] = figure[5] = figure[6] = figure[7] = 1; 32 33 //答案赋值,避免上次结果对这次进行影响 34 ans[0] = ans[1] = 0; ans[2] = 1; 35 36 //确定数字 37 for (i = 0; i < num_fig; i++) 38 { 39 figure[i] = rand() % range; 40 type_fig = rand() % 2; //0自然数,1真分数 41 if (type_fig == 1 && figure[i] != 0) //数字为真分数且分子不为0时 42 { 43 figure[i + 4] = rand() % range; 44 while (figure[i + 4] == 0 || figure[i] % figure[i + 4] == 0) //分母不能等于0且不组成自然数 45 { 46 figure[i + 4] = rand() % range; 47 } 48 t = gcd(figure[i], figure[i + 4]); //化简 49 figure[i] = figure[i] / t; 50 figure[i + 4] = figure[i + 4] / t; 51 } 52 } 53 54 //确定符号 55 for (i = 0; i < num_ope; i++) 56 { 57 rand1 = rand() % 4 + 1; 58 switch (rand1) 59 { 60 case 1: operate[i] = '+'; break; 61 case 2: operate[i] = '-'; break; 62 case 3: operate[i] = '*'; break; 63 case 4: operate[i] = '/'; break; 64 default:break; 65 } 66 } 67 68 //确定是否有括号及括号位置 69 if (num_fig == 3) //数字个数为3 70 { 71 //tag_ope = 12 表示前括号在第一个数字前,后括号在第二个数字后 72 rand1 = (rand() % 3 + 1) + (rand() % 3 + 1) * 10; 73 switch (rand1) 74 { 75 case 21: 76 case 12: tag_ope = 12; break; 77 case 32: 78 case 23: tag_ope = 23; break; 79 default: break; 80 }; 81 } 82 else if (num_fig == 4) 83 { 84 rand1 = (rand() % 4 + 1) + (rand() % 4 + 1) * 10; 85 switch (rand1) 86 { 87 case 12: tag_ope = 12; break; 88 case 13: tag_ope = 13; break; 89 case 23: tag_ope = 23; break; 90 case 24: tag_ope = 24; break; 91 case 34: tag_ope = 34; break; 92 default: break; 93 } 94 } 95 96 //判断创建的题目是否合法以及是否重复 97 if (CalAnswer(figure, operate, num_fig, num_ope, tag_ope, ans) == TRUE && JudgeRepeat(figure, operate, num_ope) == ERROR) 98 { 99 100 title_num++; 101 102 WriteFile(figure, operate, num_fig, num_ope, tag_ope, question_file); //题目写入文件 103 WriteAnswer(ans, answer_file); //答案写入文件 104 } 105 } 106 printf("全部题目生成成功,请查看txt文件"); 107 system("pause"); 108 }
计算顺序代码
1 //计算顺序 2 int Sequence(int figure[], char operate[], int num_fig, int num_ope, int tag_ope) 3 { 4 int sum = 0, j; 5 //sum = 231 表示先运算顺序为: 第2个运算符-->第3个运算符-->第1个运算符 6 7 if (tag_ope == 12 || tag_ope == 23 || tag_ope == 34 || tag_ope == 13 || tag_ope == 24) //如果有括号 8 { 9 for (j = tag_ope / 10 - 1; j < tag_ope % 10 - 1; j++) //j为相应序号 10 { 11 if (operate[j] == '*') 12 { 13 sum = sum * 10 + j + 1; 14 } 15 else if (operate[j] == '/') 16 { 17 sum = sum * 10 + j + 1; 18 } 19 } 20 for (j = tag_ope / 10 - 1; j < tag_ope % 10 - 1; j++) 21 { 22 if (operate[j] == '+') 23 { 24 sum = sum * 10 + j + 1; 25 } 26 else if (operate[j] == '-') 27 { 28 sum = sum * 10 + j + 1; 29 } 30 } 31 } 32 33 for (j = 0; j < num_ope; j++) //对所有运算符遍历 34 { 35 if (operate[j] == '*' && j + 1 != sum % 10 && j + 1 != sum / 10) //括号中运行过的不再放入 36 { 37 sum = sum * 10 + j + 1; 38 } 39 else if (operate[j] == '/' && j + 1 != sum % 10 && j + 1 != sum / 10) 40 { 41 sum = sum * 10 + j + 1; 42 } 43 } 44 for (j = 0; j < num_ope; j++) 45 { 46 if (operate[j] == '+' && j + 1 != sum % 10 && j + 1 != sum / 10) 47 { 48 sum = sum * 10 + j + 1; 49 } 50 else if (operate[j] == '-' && j + 1 != sum % 10 && j + 1 != sum / 10) 51 { 52 sum = sum * 10 + j + 1; 53 } 54 } 55 56 return sum; 57 }
重复判断代码
1 Status JudgeRepeat(int figure[],char operate[],int num_ope) 2 { 3 int n1,n2,n3,i, j, x, sum, m; 4 i = title_num; 5 6 sum = seq[i]; 7 m = pow(10, num_ope - 1); 8 9 //符号放入全局数组 10 for (j = 0; j < num_ope; j++) 11 { 12 x = sum / m - 1; 13 OPE[i][j] = operate[x]; 14 15 sum = sum % m; 16 m = m / 10; 17 } 18 19 //数据放入全局数组 20 switch (seq[i]) 21 { 22 case 1: Figure[i][0] = figure[0] * 1.0 / figure[4]; Figure[i][1] = figure[1] * 1.0 / figure[5]; break; 23 case 12: Figure[i][0] = figure[0] * 1.0 / figure[4]; Figure[i][1] = figure[1] * 1.0 / figure[5]; 24 Figure[i][2] = figure[2] * 1.0 / figure[6]; break; 25 case 21: Figure[i][0] = figure[1] * 1.0 / figure[5]; Figure[i][1] = figure[2] * 1.0 / figure[6]; 26 Figure[i][2] = figure[0] * 1.0 / figure[4]; break; 27 case 123:Figure[i][0] = figure[0] * 1.0 / figure[4]; Figure[i][1] = figure[1] * 1.0 / figure[5]; 28 Figure[i][2] = figure[2] * 1.0 / figure[6]; Figure[i][3] = figure[3] * 1.0 / figure[7]; break; 29 case 132:Figure[i][0] = figure[0] * 1.0 / figure[4]; Figure[i][1] = figure[1] * 1.0 / figure[5]; 30 Figure[i][2] = figure[2] * 1.0 / figure[6]; Figure[i][3] = figure[3] * 1.0 / figure[7]; break; 31 case 213:Figure[i][0] = figure[1] * 1.0 / figure[5]; Figure[i][1] = figure[2] * 1.0 / figure[6]; 32 Figure[i][2] = figure[0] * 1.0 / figure[4]; Figure[i][3] = figure[3] * 1.0 / figure[7]; break; 33 case 231:Figure[i][0] = figure[1] * 1.0 / figure[5]; Figure[i][1] = figure[2] * 1.0 / figure[6]; 34 Figure[i][2] = figure[3] * 1.0 / figure[7]; Figure[i][3] = figure[0] * 1.0 / figure[4]; break; 35 case 312:Figure[i][0] = figure[2] * 1.0 / figure[6]; Figure[i][1] = figure[3] * 1.0 / figure[7]; 36 Figure[i][2] = figure[0] * 1.0 / figure[4]; Figure[i][3] = figure[1] * 1.0 / figure[5]; break; 37 case 321:Figure[i][0] = figure[2] * 1.0 / figure[6]; Figure[i][1] = figure[3] * 1.0 / figure[7]; 38 Figure[i][2] = figure[1] * 1.0 / figure[5]; Figure[i][3] = figure[0] * 1.0 / figure[4]; break; 39 default: break; 40 } 41 42 //遍历全局数组,查询是否有重复的 43 for (n1 = 0; n1 < i; n1++) 44 { 45 xuhao = n1 + 1; 46 if (fabs(answer[i] - answer[n1]) < EPSILON && Num_ope[i] == Num_ope[n1]) //答案相等、运算符数相等 47 { 48 //按运算顺序,判断符号是否相等 49 for (n2 = 0; n2 < num_ope; n2++) 50 { 51 if (OPE[i][n2] != OPE[n1][n2]) break; 52 53 if(n2 == num_ope - 1) 54 { 55 //数字比对 56 for (n3 = 0; n3 < num_ope; n3++) 57 { 58 if (n3 == 0) 59 { 60 if (OPE[i][n3] == '-' || OPE[i][n3] == '/') 61 { 62 //对于第一次运算,‘-’和‘/’运算顺序不能交换,如果相同则进行下一个判断 63 if (fabs(Figure[i][n3] - Figure[n1][n3]) >= EPSILON || fabs(Figure[i][n3 + 1] - Figure[n1][n3 + 1]) >= EPSILON) 64 break; 65 } 66 else 67 { 68 //对于第一次运算,数据可交换,判断数据是否一致 69 if ((fabs(Figure[i][0] - Figure[n1][0]) < EPSILON && fabs(Figure[i][1] - Figure[n1][1]) < EPSILON) 70 || (fabs(Figure[i][0] - Figure[n1][1]) < EPSILON && fabs(Figure[i][1] - Figure[n1][0]) < EPSILON)) 71 { 72 //如果运算符数只有一个,则题目重复 73 if (num_ope == 1) { 74 printf("%.5f %.5f %.5f %.5f\n", Figure[i][0], Figure[i][1], Figure[n1][0], Figure[n1][1]); 75 printf("第%d题与第%d题重复\n", title_num + 1, xuhao); 76 printf("n3==0"); //判断重复测试是否成功的输出标志 77 return TRUE; //重复返回TRUE,不重复则进行下一个判断 78 } 79 } 80 else break; 81 } 82 83 } 84 85 if (n3 == 1) 86 { 87 if (seq[i] == 132 || seq[i] == 312) //特殊运算顺序处理 88 { 89 if (OPE[i][n3] == '-' || OPE[i][n3] == '/') 90 { 91 if (fabs(Figure[i][n3 + 1] - Figure[n1][n3 + 1]) >= EPSILON || fabs(Figure[i][n3 + 2] - Figure[n1][n3 + 2]) >= EPSILON) 92 break; 93 else { printf("n3==1.1\n"); return TRUE; } //所有数据对比完成相同,重复 94 } 95 else 96 { 97 //判断可交换时,是否数据相同 98 if ( 99 (fabs(Figure[i][n3 + 1] - Figure[n1][n3 + 1]) < EPSILON && fabs(Figure[i][n3 + 2] - Figure[n1][n3 + 2]) < EPSILON) 100 || 101 (fabs(Figure[i][n3 + 1] - Figure[n1][n3 + 2]) < EPSILON && fabs(Figure[i][n3 + 2] - Figure[n1][n3 + 1]) < EPSILON) 102 ) 103 { 104 printf("n3==1.2\n"); return TRUE; 105 } //所有数据比对全部相同,重复 106 else return ERROR; 107 } 108 } 109 else 110 { 111 //其他情况下,第一次运算的数字,第二次运算只涉及一个数字第一次被使用 112 if (fabs(Figure[i][n3 + 1] - Figure[n1][n3 + 1]) >= EPSILON) break; 113 } 114 } 115 116 if (n3 == 2) 117 { 118 if (fabs(Figure[i][n3 + 1] - Figure[n1][n3 + 1]) >= EPSILON) break; 119 else { printf("n3==3\n"); return TRUE; } 120 } 121 } 122 } 123 } 124 } 125 } 126 return ERROR; //答案不相等,不重复 127 }
对给定题目文件和答案文件判断的答案对比函数
1 //答案对比函数 2 void CompareAnswer() 3 { //解析题目参数 4 int cnum_ope, ctag_ope[3], i[2], fig_num[2], ope_num[2]; 5 int figure[8], ans[3]; 6 char operate[4]; 7 char answer_cal[6][20]; 8 //读取文件参数 9 char question_read[100]; 10 char answer_read[50]; 11 //结果参数 12 int correct_num = 0, wrong_num = 0, title_n = 1; 13 int correct_tn[10000], wrong_tn[10000]; 14 15 FILE* question_file; 16 FILE* answer_file; 17 FILE* Grade_file; 18 char exercise[20], answer[20]; 19 20 21 cout << "请输入练习题文件名" << endl; 22 cin >> exercise; 23 cout << "请输入答案文件名" << endl; 24 cin >> answer; 25 if ((question_file = fopen(exercise, "r")) == NULL) 26 { 27 printf("You can't open the file!\n"); 28 exit(1); 29 } 30 if ((answer_file = fopen(answer, "r")) == NULL) 31 { 32 printf("You can't open the file!\n"); 33 exit(1); 34 } 35 /* 36 if ((question_file = fopen("Exercise.txt", "r")) == NULL) 37 { 38 printf("You can't open the file!\n"); 39 exit(1); 40 } 41 if ((answer_file = fopen("Answers.txt", "r")) == NULL) 42 { 43 printf("You can't open the file!\n"); 44 exit(1); 45 } 46 */ 47 printf("开始处理\n"); 48 49 while (!feof(question_file)) 50 { 51 cout << "\n"; 52 fgets(question_read, 100, question_file); //将答案 53 fgets(answer_read, 50, answer_file); 54 printf("%s", question_read); 55 56 int change = -1; 57 ope_num[0] = 0, fig_num[0] = 0; 58 ctag_ope[0] = ctag_ope[2] = 0, ctag_ope[1] = 1, i[0] = 0; 59 for (int f = 0; f < 8; f++) { 60 figure[f] = 1; 61 } 62 //答案赋值,避免上次结果对这次进行影响 63 ans[0] = ans[1] = 0; ans[2] = 1; 64 65 //处理题目 66 for (*i = 8; question_read[i[0]] != '='; i[0]++) 67 { 68 change = ChangeNumber(question_read, i); //将字符转换为数字 69 70 CanShu(change, question_read, i, ctag_ope, fig_num, ope_num, figure, ans, operate); //得出参数 71 } 72 73 cnum_ope = *fig_num - 1; 74 ctag_ope[0] = ctag_ope[1] * 10 + ctag_ope[2]; 75 76 CalAnswer(figure, operate, *fig_num, cnum_ope, ctag_ope[0], ans); //利用参数计算答案 77 78 ChangeAnswer(ans, answer_cal); //把答案转化为字符串 79 cout << "计算出的答案:" << answer_cal[0] << endl; 80 81 //处理读出的答案字符串,将答案字符串读入数组 82 char ans_compare[20] = "0"; 83 int c = 0; 84 for (int j = 10; answer_read[j] != '\0'; j++) 85 { 86 if ((answer_read[j] >= '0' && answer_read[j] <= '9') || answer_read[j] == 39 || answer_read[j] == '/') 87 { 88 ans_compare[c] = answer_read[j]; 89 c++; 90 } 91 } 92 cout << "读取的答案:" << ans_compare << endl; 93 94 if (0 == strcmp(answer_cal[0], ans_compare)) //比较答案是否正确 95 { 96 correct_tn[correct_num] = title_n; 97 correct_num++; 98 } 99 else 100 { 101 wrong_tn[wrong_num] = title_n; 102 wrong_num++; 103 } 104 title_n++; 105 } 106 107 108 109 if ((Grade_file = fopen("Grade.txt", "a+")) == NULL) 110 { 111 printf("You can't open the file!\n"); 112 exit(1); 113 } 114 //统计正确、错误答案 115 fprintf(Grade_file, "Correct :%d", correct_num); 116 if (correct_num != 0) 117 fprintf(Grade_file, "("); 118 for (int correct = 0; correct < correct_num; correct++) 119 { 120 121 fprintf(Grade_file, "%d,", correct_tn[correct]); 122 if (correct + 1 == correct_num) 123 fprintf(Grade_file, ")\n"); 124 } 125 126 fprintf(Grade_file, "Wrong :%d", wrong_num); 127 if (wrong_num != 0) 128 fprintf(Grade_file, "("); 129 for (int wrong = 0; wrong < wrong_num; wrong++) 130 { 131 fprintf(Grade_file, "%d,", wrong_tn[wrong]); 132 if (wrong + 1 == wrong_num) 133 fprintf(Grade_file, ")\n"); 134 } 135 136 137 fclose(question_file); 138 fclose(answer_file); 139 140 }
写入文件代码
1 //题目放入文件 2 void WriteFile(int figure[], char operate[], int num_fig, int num_ope, int tag_ope, FILE* file) 3 { 4 if (file == NULL) return; 5 printf("生成了第 %d 道\n", title_num); 6 int i; 7 fprintf(file, "题目%d: ", title_num); 8 if (tag_ope != 10) //题目包含括号 9 { 10 for (i = 0; i < num_ope; i++) 11 { 12 if (i + 1 == tag_ope / 10) fprintf(file, "("); 13 if (figure[i + 4] != 1) fprintf(file, "%d/%d", figure[i], figure[i + 4]); //有分母则按真分数输出 14 else fprintf(file, "%d", figure[i]); 15 if (i + 1 == tag_ope % 10) fprintf(file, ")"); 16 if (operate[i] == '*') //输出运算符 17 fprintf(file, " × "); 18 else if (operate[i] == '/') 19 fprintf(file, " ÷ "); 20 else 21 fprintf(file, " %c ", operate[i]); 22 } 23 if (figure[i + 4] != 1) fprintf(file, "%d/%d", figure[i], figure[i + 4]); 24 else fprintf(file, "%d", figure[i]); 25 if (i + 1 == tag_ope % 10) fprintf(file, ")"); 26 } 27 else 28 { 29 for (i = 0; i < num_ope; i++) 30 { 31 if (figure[i + 4] != 1) fprintf(file, "%d/%d", figure[i], figure[i + 4]); 32 else fprintf(file, "%d", figure[i]); 33 34 if (operate[i] == '*') 35 fprintf(file, " × "); 36 else if (operate[i] == '/') 37 fprintf(file, " ÷ "); 38 else 39 fprintf(file, " %c ", operate[i]); 40 } 41 if (figure[i + 4] != 1) fprintf(file, "%d/%d", figure[i], figure[i + 4]); 42 else fprintf(file, "%d", figure[i]); 43 } 44 fprintf(file, " =\n"); 45 }
六、测试运行
(1)测试题目、答案写入文件


(2)10000道题目测试



(3)判断重复测试
10000道题目,由于反馈输出在命令控制器中不方便查找,所以另复制在记事本中查找,其中出现n3则表示出现重复

(4)对给定题目文件和答案文件进行判断
对创建题目后的答案文件进行5次修改后再进行判断(10000道题目)



七、PSP表格
|
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
|
Planning |
计划 |
120 |
120 |
|
· Estimate |
· 估计这个任务需要多少时间 |
120 |
120 |
|
Development |
开发 |
1520 |
2160 |
|
· Analysis |
· 需求分析 (包括学习新技术) |
180 |
210 |
|
· Design Spec |
· 生成设计文档 |
60 |
60 |
|
· Design Review |
· 设计复审 (和同事审核设计文档) |
120 |
150 |
|
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
20 |
10 |
|
· Design |
· 具体设计 |
120 |
100 |
|
· Coding |
· 具体编码 |
600 |
780 |
|
· Code Review |
· 代码复审 |
120 |
100 |
|
· Test |
· 测试(自我测试,修改代码,提交修改) |
300 |
750 |
|
Reporting |
报告 |
120 |
155 |
|
· Test Report |
· 测试报告 |
60 |
120 |
|
· Size Measurement |
· 计算工作量 |
30 |
25 |
|
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
30 |
10 |
|
合计 |
|
1760 |
2075 |
八、项目小结
1.第一次构建框架时准备不够充分,思考的不够全面,导致后面重构框架令一些已经写了的代码作废;
2.个人因为github和git操作不熟练,为求方便并没有通过git来实时更新,而是发代码文件给同伴,让其进行github的更新。
3.结对项目中我两通过腾讯会议进行讨论、交流,时刻更新代码进度。
4.预估时间不够准确,对需求的分析还有些不到位
5.在做需求9的之前显示×, ÷符号,但在需求9时因无法识别而耽误很久,写代码没有考虑好之后的函数引用,需要改正。
结伴感受:
高嘉淳:搭档程囿阳负责任、有上进心,帮助我测试代码、整理代码和debug,并进行代码的整理,让我在困惑时醒悟,很棒。
程囿阳:高大佬的算法非常厉害,思路清晰,写代码的效率很高,让我学习到了很多东西,深深的意识到了算法的重要性,是很棒的搭档。
浙公网安备 33010602011771号