第一次作业--四则运算
需求分析:
1.获取生成题目的数量;(该数值必须给定,否则程序出错)
2.控制生成四则运算中最大值的范围;(该数值必须给定,否则程序出错)
3.生成的题目中存在心如e1/e2的字表达式的姓氏,其结果需要化为真分数,其中真分数在输入输出时采用如下格式,真分数五分之三表示为3/5,真分数二又八分之三表示为2’3/8;
4.每道题目中出现的运算符个数不超过3个。
5.程序生成的题目不能重复,即任何两道题目不能通过有限次交换变换为同一道题目;
6. 程序应能支持一万道题目的生成。
7. 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计
设计思路:
1. 程序的主要实现功能部分在于随机生成运算符不超过3个的n道题目,运算式通过逆波兰计算出结果,生成的答案如果不是整数,将化成真分数表示;
2. 运算式的个数用count变量保存,至少有两个,如果随机产生count>2,之前的运算式变成其中一个操作数,即a+b,a->c+d;
3. 通过逆波兰将运算式化成后缀表达式,计算后缀表达式,将结果保存;
4. 如果得到不是整数的结果,需要化成分数的形式,由于结果是float类型,分子分母同时乘1000000,通过MaxY求得最大公约数,如果分子比分母大,分子除分母后强制转换int后 保存,分子c=c-num*d,然后就可以输出形如2’3/8的形式。
5. 用两个数组保存输入的答案跟正确答案,然后比较,正确计数器+1,并保存题号,错误同理;
实现语言:C++
代码说明:
1.主要界面
#include <stdio.h> #include <time.h> #include <stdlib.h> #include <string.h> #include<dos.h> #include "takeTest.h" int main() { int n,a,i,max,repeat,right=0,wrong=0; double percent; // float result[100]={0}; // printf("%f",getResult()); printf("请输入测试的题目数:"); scanf("%d",&n); printf("请输入测试的最大数:"); scanf("%d",&max); float ans[n],result[n]; int t[n],f[n]; printf("\n---随机生成%d道题目:\n",n); for(i=0; i<n; i++) { result[i]=takeTest(max,i); // right=right+a; } // printf("%f",result[i]); printf("\n---开始答题:\n"); for(int i=0; i<n; i++) { printf("第(%d)题:",i+1); scanf("%f",&ans[i]); } printf("\n---正确答案:\n"); for(int i=0; i<n; i++) { printf("(%d)小数:%g 真分数: ",i+1,result[i]); numden(result[i]); } for(int i=0,j=0,k=0; i<n; i++) { if(ans[i]==result[i]) { right++; t[j]=i+1; j++; } else { wrong++; f[k]=i+1; k++; } } printf("\n做对的题目有%d题,题号是:",right); for(int i=0; i<right; i++) { printf("%d、",t[i]); } printf("\n做错的题目有%d题,题号是:",wrong); for(int i=0; i<wrong; i++) { printf("%d、",f[i]); } printf("\n重复的题目有 题",repeat); }
2 、随机生成n道题目
#include<fstream> #include<iostream> #include<stdlib.h> #include<iomanip> #include<time.h> #include<cmath> #include<string> #include<stdio.h> #include "getResult.h" #include "safe.h" using namespace std; #define random() (rand()%100000) char create_symbol(int n) { int n1,j; char symbol[1]; j=random()%4; if(j==0) symbol[0]='+'; else if(j==1) symbol[0]='-'; else if(j==2) symbol[0]='*'; else symbol[0]='/'; return symbol[0]; } string int_string(int number) { int temp=abs(number); char str[200]; itoa(temp,str,10); string str_=str; return str_; } string combination(string str1,string str2,char k) { string equation; equation=str1+k+str2; return equation; } float takeTest(int max ,int i) { int num1,num2,count,n,change,range,j; string str_num1,str_num2,temp,exp; range=max; char symbol; ofstream fout; num1=random()%range+1; num2=random()%range+1; count=random()%3+2;// 设置运算式的长度 symbol=create_symbol(n); str_num1=int_string(num1); str_num2=int_string(num2); exp=combination(str_num1,str_num2,symbol); if(count>2) { for(count; count>2; count--) { symbol=create_symbol(n); str_num1=exp; change=random()%2; if(change==0) { str_num1='('+str_num1+')'; } symbol=create_symbol(n); num2=random()%range+1; str_num2=int_string(num2); change=random()%2; if(change==0) { temp=str_num1; str_num1=str_num2; str_num2=temp; } exp=combination(str_num1,str_num2,symbol); } } cout<<"第"<<i+1<<"题:"<<exp<<"="<<endl; // printf("%f",getResult(exp)); return getResult(exp); }
3. 通过逆波兰将运算式转化为后缀表达式,并且得出结果
#include<stdio.h> #include<math.h> #include<stdlib.h> #include <iostream> #include "numden.h" #include <cstring> using namespace std; char str[100]; char ex[100]; /*存储后缀表达式*/ void trans() { /*将算术表达式转化为后缀表达式*/ int max=100; char stack[max]; char ch; int sum,i,j,t,top=0; i=0; /*获取用户输入的表达式*/ // do { // i++; // scanf("%c",&str[i]); // } while(str[i]!='#' && i!=max); // strcpy(str, "(5+15)/10#"); sum=i; t=1; i=0; ch=str[i]; i++; while(ch!='#') { switch(ch) { case '(': top++; stack[top]=ch; break; case ')': while(stack[top]!='(') { ex[t]=stack[top]; top--; t++; } top--; break; case '+': case '-': while(top!=0&&stack[top]!='(') { ex[t]=stack[top]; top--; t++; } top++; stack[top]=ch; break; case '*': case '/': while(stack[top]=='*'||stack[top]=='/') { ex[t]=stack[top]; top--; t++; } top++; stack[top]=ch; break; case ' ': break; default: while(ch>='0'&&ch<='9') { ex[t]=ch; t++; ch=str[i]; i++; } i--; ex[t]='&'; t++; } ch=str[i]; i++; } while(top!=0) { ex[t]=stack[top]; t++; top--; } ex[t]='#'; } /*计算后缀表达式的值*/ float com() { int max=100; float stack[max],d; char ch; int t=1,top=0; ch=ex[t]; t++; while(ch!='#') { switch(ch) { case '+': stack[top-1]=stack[top-1]+stack[top]; top--; break; case '-': stack[top-1]=stack[top-1]-stack[top]; top--; break; case '*': stack[top-1]=stack[top-1]*stack[top]; top--; break; case '/': if(stack[top]!=0) stack[top-1]=stack[top-1]/stack[top]; else { printf("\n\t除零错误!\n"); exit(0); /*异常退出*/ } top--; break; default: d=0; while(ch>='0'&&ch<='9') { d=10*d+ch-'0'; ch=ex[t]; t++; } top++; stack[top]=d; } ch=ex[t]; t++; } return stack[top]; } float getResult(string s) { strncpy(str,s.c_str(),s.length()); str[s.length()] ='#'; trans(); for(int i=0; i<2; i++) printf(" ",ex[i]); // numden(com()); return com(); }
4. 得到的不是整数的结果需要化成真分数的形式
#include<stdio.h> #include<ctype.h> #include<math.h> int MaxY(int a,int b) ; void numden(float m) { int a,b=1000000,num; a=(int)(m*1000000); int max=MaxY(a,b); int c,d; c=a/max; d=b/max; if(m==(int)m) { printf("%d\n",int(m)); } else if(abs(c)>d) { num=(int)(c/d); c=c-num*d; printf("%d'%d/%d\n",num,abs(c),d); } else if(d==1) { printf("%d\n",c); } else printf("%d/%d\n",c,d); } int MaxY(int a,int b) { int min, max; int r; max=a>b?a:b; min=a<b?a:b; if(max%min==0) return abs(min); while(max%min!=0) { r=max%min; max=min; min=r; } return abs(min); }
运行结果:
PSP表格:
PSP2.1 | Personal Software Process Stages | estimated time | Actual time |
Planning | 计划 | 10 | 10 |
· Estimate | 估计这个任务需要多少时间 | 10 | 20 |
Development | 开发 | 20 | 30 |
· Analysis | 需求分析 (包括学习新技术) | 60 | 100 |
· Design Spec | 生成设计文档 | 20 | 20 |
· Design Review | 设计复审 | 10 | 30 |
· Coding Standard | 代码规范 | 10 | 10 |
· Design | 具体设计 | 30 | 40 |
· Coding | 具体编码 | 300 | 400 |
· Code Review | 代码复审 | 60 | 50 |
· Test | 测试(自我测试,修改代码,提交修改) | 10 | 10 |
Reporting | 报告 | 60 | 100 |
· | 测试报告 | 10 | 10 |
· | 计算工作量 | ||
· | 并提出过程改进计划 |
不足:
没有实现题目查重的功能;
代码仓库地址:
https://coding.net/u/Missyby/p/program1