标签:存在 pos 目录 新技术 简介 wro ade analysis VID
结对项目:四则运算表达式生成器(C语言)
GitHub:https://github.com/peter-ye-code/Question-Builder
合作者:叶学涛(3118005024)
温德华(3118005021)
四则运算表达式生成器的全部功能:
使用 -n 参数控制生成题目的个数,例如 Myapp.exe -n 10 将生成10个题目。
使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围,例如 Myapp.exe -r 10 将生成10以内(不包括10)的四则运算题目。该参数可以设置为1或其他自然数。该参数必须给定,否则程序报错并给出帮助信息。
生成的题目中计算过程不能产生负数,也就是说算术表达式中如果存在形如e1− e2的子表达式,那么e1≥ e2。
生成的题目中如果存在形如e1÷ e2的子表达式,那么其结果应是真分数。
每道题目中出现的运算符个数不超过3个。
程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。例如,23 + 45 = 和45 + 23 = 是重复的题目,6 × 8 = 和8 × 6 = 也是重复的题目。3+(2+1)和1+2+3这两个题目是重复的,由于+是左结合的,1+2+3等价于(1+2)+3,也就是3+(1+2),也就是3+(2+1)。但是1+2+3和3+2+1是不重复的两道题,因为1+2+3等价于(1+2)+3,而3+2+1等价于(3+2)+1,它们之间不能通过有限次交换变成同一个题目。
生成的题目存入执行程序的当前目录下的Exercises.txt文件。
在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件。
程序应能支持一万道题目的生成。
程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计,输入参数如下:Myapp.exe -e .txt -a .txt,统计结果输出到文件Grade.txt,格式如下:
Correct: 5 (1, 3, 5, 7, 9)
Wrong: 5 (2, 4, 6, 8, 10)
其中“:”后面的数字5表示对/错的题目的数量,括号内的是对/错题目的编号。为简单起见,假设输入的题目都是按照顺序编号的符合规范的题目。
未完成的功能:(4)功能中的真分数功能未能实现
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
30 |
40 |
· Estimate |
· 估计这个任务需要多少时间 |
30 |
40 |
Development |
开发 |
1150 |
1200 |
· Analysis |
· 需求分析 (包括学习新技术) |
200 |
250 |
· Design Spec |
· 生成设计文档 |
30 |
30 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
10 |
15 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
20 |
30 |
· Design |
· 具体设计 |
500 |
435 |
· Code Review |
· 代码复审 |
120 |
90 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
300 |
350 |
Reporting |
报告 |
60 |
70 |
· Test Report |
· 测试报告 |
20 |
25 |
· Size Measurement |
· 计算工作量 |
10 |
10 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
30 |
35 |
合计 |
1240 |
1310 |
采用随机法生成运算表达式,运算顺序则采用中缀表达式转后缀表达式,结果及运算数则使用栈来进行存取。
生成表达式
int CreatQuestion (int m,int digital_index,int *answer) { char str[250] = {‘0‘}; //定义一个字符数组存放算术表达式 int x, num, ran_num, j = 0; num = random_number( 3 );//生成随机运算符数目 //循环生成算术表达式 for ( int k = 0; k < num; k++ ) { ran_num = random_number ( m ); //生成一个参与表达式的数值,m是数值范围 (1~10) x = 1; while ( ran_num / x ) { x *= 10; } x /= 10;//x=10,x=1 while ( x )//x=10执行两次 { str[j++] = ran_num / x + ‘0‘;//将数字型转换为字符串型 ran_num = ran_num % x; x /= 10; } str[j++] = random_symbol(); //随机生成一个运算符 } //生成一个随机结尾数值 ran_num = random_number( m ); x = 1; while ( ran_num / x ) { x *= 10; } x /= 10; while ( x ) { str[j++] = ran_num / x + ‘0‘; ran_num = ran_num % x; x /= 10; } int result = Answer(str,digital_index); *answer = result; if(result>=0){ WriteQuestion(str,digital_index); WriteAnswer(digital_index,result); } }
计算答案
//生成答案模块 int Answer(char *str,int digital_index) { char* p =str; int num[100] = {0};//数字数组 char symbol[100] = {0};//运算符数组 int index = 0; //索引 char stack[100] = {0};//运算符栈 int stacki[100] = {0};//结果栈 int top = -1;//栈的索引 -1表示栈为空 int temp = 0;//正在拼写的数字 int flag = 0;//表示当前是否正在拼写数字 //中缀表达式转化为逆波兰表达式 //最后的结果就是得到两个数组,分别是num和symbol while(1){ if(*p>=‘0‘ && *p<=‘9‘)//读到了一个数字 { flag = 1; temp *= 10;//第一个为数字时temp=0,第二个为数字时才乘以10 temp += *p - ‘0‘;//0的ASCII值为48 } else//读到了一个符号,或字符串已经结束了 { if(flag)//拼写完1个数字先将数字输出 { num[index] = temp; symbol[index] = ‘!‘; index++; flag = temp =0;//重新置0 } if(!*p)//如果字符串已经结束 { //最终,将栈元素全部出栈 while(top>=0) symbol[index++]=stack[top--]; break;//跳出循环 } else// 字符串还未结束 { if(top == -1||*p == ‘(‘) //如果栈空时,或符号为左括号 stack[++top] = *p;//入栈 else if(*p == ‘)‘)//如果是右括号,出栈到左括号 { while(top>=0&&stack[top]!=‘(‘)//如果不为左括号。出栈 { symbol[index++]=stack[top--]; } --top;//如果为左括号,--top } else if(*p == ‘*‘||*p == ‘/‘)//如果新符号是乘除 { while(top>=0&&(stack[top]==‘*‘||stack[top]==‘/‘))//乘除出栈 { symbol[index++]=stack[top--]; } stack[++top] = *p;//新符号入栈 } else //如果新运算符是加减 { while(top>=0&&stack[top]!=‘(‘)//四则运算出栈 { symbol[index++]=stack[top--]; } stack[++top] = *p;//新符号入栈 } } } p++; } //逆波兰表达式求解 top =-1; int temp1 = 0; int temp2 = 0; for(int i =0;i<index;i++){ if(symbol[i]==‘!‘){//这时的i索引表示的是数字,数字入栈stacki stacki[++top] = num[i]; } //符号运算 else { temp1 = stacki[top--]; temp2 = stacki[top--]; switch (symbol[i]) { case ‘+‘: stacki[++top] = temp2 + temp1;//将结果入栈 break; case ‘-‘: stacki[++top] = temp2 - temp1;//后面减去前面 break; case ‘*‘: stacki[++top] = temp2 * temp1; break; case ‘/‘: stacki[++top] = temp2 / temp1; break; } } } //最终结果是stacki[0] int result = stacki[0]; // printf("%s=%d\n",str,result); // WriteAnswer(digital_index,result); return result; }
生成答案文件
void WriteQuestion(char *str,int digital_index){ int k=0; FILE *fp; fp=fopen("Exercises.txt","a");//若文件不存在则建立该文件,这里不能用w,要用a fprintf(fp,"%d:",digital_index); while(str[k]!=NULL){ if(str[k] == ‘+‘ ||str[k] == ‘-‘ ||str[k] == ‘*‘ ||str[k] == ‘/‘ || str[k] == ‘=‘){ fprintf(fp," %c ",str[k]); }else fprintf(fp,"%c",str[k]); k++; } fprintf(fp," =\n"); fclose(fp); }
生成题目文件
void WriteAnswer(int digital_index,int result){ FILE *fp; fp=fopen("Answers.txt","a");//若文件不存在则建立该文件,这里不能用w,要用a fprintf(fp,"%d:",digital_index); fprintf(fp,"%d\n",result); fclose(fp); }
检查答案并且生成报告文件
void CheckAnswer(char exercisefile[],char answerfile[]){ FILE *fp1,*fp2,*fp3; fp1=fopen("Answers.txt","r"); fp2=fopen(answerfile,"r"); fp3=fopen("Grade.txt","w"); int index=1; //题目序号 char correct_answer[30]={}; //存放正确答案 char answer[30]={}; //存放从答案文件取出的答案 int c_num=0,w_num=0; //用于计算对和错的总题数 int c_index[10000]={}; //用于储存对的和错的题号 int w_index[10000]={}; while(fgets(correct_answer,30,fp1)!=NULL && fgets(answer,30,fp2)!=NULL) { if(strcmp(correct_answer,answer)==0) //比较前n个字节的大小 { c_index[c_num++]=index; index++; } else if(strcmp(correct_answer,answer)!=0) { w_index[w_num++]=index; index++; } } fprintf(fp3,"Correct: %d (",c_num); for(int i=0;i<c_num;i++) { fprintf(fp3,"%d",c_index[i]); if(i!=c_num-1) fprintf(fp3,","); } fprintf(fp3,")\n"); fprintf(fp3,"Wrong: %d (",w_num); for(int i=0;i<w_num;i++) { fprintf(fp3,"%d",w_index[i]); if(i!=w_num-1) fprintf(fp3,","); } fprintf(fp3,")\n"); fclose(fp1); fclose(fp2); fclose(fp3); }
主函数
int main(int argc,char*argv[]){ if(argc<2){ printf("you must input argc!"); return 0; } srand((int)time(0));//设置rand()产生随机数时的随机数种子 FILE *fp1,*fp2; int n,r; if(!strcmp(argv[1],"-n") && !strcmp(argv[3],"-r")){//生成题目和答案 fp1=fopen("Exercises.txt","w"); fp2=fopen("Answers.txt","w"); fclose(fp1); fclose(fp2); n=atoi(argv[2]); r=atoi(argv[4]); int answer; int digital_index=1; while(digital_index<=n){ CreatQuestion(r,digital_index,&answer); if(answer>=0){ digital_index++; } } }else if(!strcmp(argv[1],"-e") && !strcmp(argv[3],"-a")){//检查答案 CheckAnswer(argv[2],argv[4]); } return 0; }
1、生成10道题目及答案文件
2、生成1W道题目及答案文件
3、检查文件的生成
标签:存在 pos 目录 新技术 简介 wro ade analysis VID
原文地址:https://www.cnblogs.com/wen328328/p/12700268.html