四则运算表达式生成器(C语言)
2021-02-17 03:17
标签:存在 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,格式如下: 未完成的功能:(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 采用随机法生成运算表达式,运算顺序则采用中缀表达式转后缀表达式,结果及运算数则使用栈来进行存取。 生成表达式 计算答案 生成答案文件 生成题目文件 检查答案并且生成报告文件 主函数 1、生成10道题目及答案文件 2、生成1W道题目及答案文件
3、检查文件的生成
四则运算表达式生成器(C语言) 标签:存在 pos 目录 新技术 简介 wro ade analysis VID 原文地址:https://www.cnblogs.com/wen328328/p/12700268.html一、需求
Correct: 5 (1, 3, 5, 7, 9)
Wrong: 5 (2, 4, 6, 8, 10)
其中“:”后面的数字5表示对/错的题目的数量,括号内的是对/错题目的编号。为简单起见,假设输入的题目都是按照顺序编号的符合规范的题目。二、PSP表格
三、设计实现过程
1、设计思路
2、模块函数关系
四、主要代码
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 )
{
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
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
int main(int argc,char*argv[]){
if(argc2){
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_indexn){
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;
}
五、测试运行
六、经验及总结