小学数学练习
实验内容
编写一个帮助小学生练习数学的程序,帮助小学生练习 100 以内的四种数学运算:加、减、乘、除。
实验要求
a) 程序应先询问用户的 ID 号(ID 号包括两个大写字母和 4 位数字),例如:
请输入 用户 ID
号 :AB1234
程序应对输入的 ID 号验证,符合 ID 号要求的格式,然后程序提示三种选择:
(1)开始测试
(2)检查分数
(3)退出
b) 测试:该程序将给出 10 道数学题,例如: 12 * 3 =36 48 + 32 =80 „56 / 28 =2
主要仪器设备-台式或笔记本电脑
实验记录(写出实验内容中程序代码和运行结果)(可分栏或加页)
程序代码:
/*1. 小学数学练习
1.1【问题描述】
编写一个帮助小学生练习数学的程序,帮助小学生练习 100 以内的四种数学运算:加、减、乘、除。
1.2【基本要求】
a) 程序应先询问用户的 ID 号(ID 号包括两个大写字母和 4 位数字),例如:
请输入用户 ID 号:AB1234
程序应对输入的 ID 号验证,符合 ID 号要求的格式,然后程序提示三种选择:
(1)开始测试
(2)检查分数
(3)退出
b) 测试:该程序将给出 10 道数学题,例如:
12 * 3 =36
48 + 32 =80
56 / 28 =2
注意:
i)学生将依次回答每一个问题(在等于号后面给出答案),然后给出下一道题。
ii)试题应包含四种数学运算:加、减、乘、除,它们是随机产生的。相邻的问题应该是不同的操作,
每个操作必须至少出现一次。
iii)为每道题随机生成数字,但必须确保参与运算的数字和结果都小于 100 且大于零的整数。
iv)十道题做完后,记录学生完成这十道题所用的时间。
v)给每个学生一个分数。将该学生的 ID、成绩和使用时间保存到一个名为 record.txt 的文件中。
vi)在屏幕上输出以下信息:
问题 | 正确答案 | 你的答案
c) 成绩检查:从文件“record.txt”中列出该学生的所有历史成绩。例如:
你以前的记录是:
AB1234 80 150 秒
AB1234 50 182 秒
AB1234 90 98 秒*/
#include<string.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <stdlib.h>
#include <stdbool.h>
#include <windows.h>
#define IDNO_LENGTH 6
#define CALC_KIND 4
#define CALC_NUM 10
bool checkNo(char idCS[]);//验证ID
char getSignal();//获取运算符
int getResult(int,int,char);//结果
void takeTest();//列出题目
char str[100];
//main函数
int main(){while(1){printf("请输入用户ID号:");char idCS[IDNO_LENGTH];do{scanf("%s",&idCS);fflush(stdin);} while(checkNo(idCS)==false);printf("(1)开始测试\t\n(2)检查分数\n(3)退出\n");int choose;do{printf("请选择:");scanf("%d",&choose);fflush(stdin);} while(choose!=1 && choose!=2 && choose!=3);if(choose==1){FILE *fp=fopen("record.txt","a");fprintf(fp,"%s",idCS);fclose(fp);fflush(stdin);takeTest();}else if(choose==2){ //选择2 FILE *fp;char ch;if((fp=fopen("record.txt","rt+"))==NULL){ //打开文件并判断文件是否为空 printf("\n你还没做过题目测试");getchar();exit(1);}while(!feof(fp)){fgets(str,100,fp);if(feof(fp)){break;}char tmp[7];for(int i = 0;i<6;i++){tmp[i] = str[i];}if(!strcmp(tmp,idCS)){printf("%s",str);}}fclose(fp);}else{exit(0);}}
}
//获取随机运算符
char getSignal(){char signal[CALC_KIND]={'+','-','*','/'};srand((unsigned)time(NULL));return signal[rand()%4];
}//获取随机数
int random(double start, double end){return (int)(start+(end-start)*rand()/(RAND_MAX+ 1.0));
}
//运算
int getResult(int num1,int num2,char signal){int res;switch(signal){case '+':res=num1+num2;break;case '-':res=num1-num2;break;case '*':res=num1*num2;break;case '/':res=int(num1/num2);break;default:res=0;printf("运算符不符合规则\n");}return res;
}
//列出10道题
void takeTest(){int shu1[10];char fuhao[10];int shu2[10];int jieguo[10];int zhengjie[10];printf("开始答题,每道题10分,总共100分\n");clock_t startTime;startTime=clock();int index;int giveRes;int num1;int num2;int score=0;char signal;for(index=0;index<CALC_NUM;index++){srand((unsigned)time(NULL));if(index>=1){do{signal=getSignal();fuhao[index] = signal;}while(fuhao[index-1]==signal);}else{signal=getSignal();fuhao[index] = signal;}do{num1=random(0,100);num2=random(1,100);if(num1<num2&&(signal=='-'||signal=='/')){int d=num1;num1=num2;num2=d;}if(signal=='/')num1=(num1/num2)*num2;}while((num1+num2)>=100||num1*num2>=100);printf("%d%c%d=",num1,signal,num2);scanf("%d",&giveRes);fflush(stdin);shu1[index] = num1;shu2[index] = num2;jieguo[index] = giveRes;zhengjie[index] = getResult(num1,num2,signal);if(getResult(num1,num2,signal)==giveRes){printf("答案正确\n");score+=10;}else{printf("答案错误,正确答案为%d\n",getResult(num1,num2,signal));}}printf("总得分为%d\n",score);printf("解10道题用了%lf秒\n\n",(double)(clock()- startTime)/CLOCKS_PER_SEC);//遍历数组中的记录 printf("题目记录如下|您的答案|正确答案\n");for(int i=0;i<10;i++){printf("%3d%3c%3d=%7d%7d\n",shu1[i],fuhao[i],shu2[i],jieguo[i],zhengjie[i]);}FILE *fp = fopen("record.txt","a");fprintf(fp," 分数为%d",score);fprintf(fp," 时间为%lf秒\n",(double)(clock()- startTime)/CLOCKS_PER_SEC);fclose(fp);fflush(stdin);
}
//检测idCS是否合规则,合规则返回true
bool checkNo(char idCS[]){int index;bool flag;flag=true;for(index=0;index<IDNO_LENGTH;index++){if(index<2){if(isalpha(idCS[index])!=1){flag=false;printf("ID不符合规则,重新输入:");break;}}else{if(!isdigit(idCS[index]) || strlen(idCS) != 6){flag=false;printf("ID不符合规则,重新输入:");break;}}}return flag;
}
实验结果:
**
遇到的问题和解决方法
**
1. 如何验证账号是否符合规则?
由于题目要求的格式为AB1234这种前两个为大写英文字母,后为四个数字,在这里采用数组的方式,先将用户输入的账号传入指定的数组中。
这里可以用到的函数有isalpha,isdigit,strlen函数
isalpha是一种函数:判断字符是否为英文字母,若为英文字母,返回非0(小写字母为2,大写字母为1)。若不是字母,返回0。这里先判断前两个字符是否为大写字母。利用if语句,如果前两个字符不是大写的英文字母,则直接否定。
isdigit是计算机C(C++)语言中的一个函数,主要用于检查后四位参数是否为十进制数字字符。
Strlen函数用于计算给定字符串长度,只有当长度为6并且是标准格式时才会通过
用三个函数分别判断前两个字符与后4个数字是否合规
2. 如何保证相邻两次算数运算法则不同?
/* 初始化随机数发生器 */
用时间作为种子
char signal[CALC_KIND]={'+','-','*','/'};srand((unsigned)time(NULL));return signal[rand()%4];
在这段程序中,以时间参数为种子,随机在四个计算符号中选择,但是由于只有四个待选项,所以有时还是会出现这种情况,添加一个判断语句看他相邻两个符号是否相同,如果不同的话重新输入。
3. 如何确保运算结果及参数小于100?
因为100之内的数据之间的加减乘除中,只有加和乘才有可能使结果大于100,所以只需要控制加和乘的结果即可。故使用do{}while((num1+num2)>=100||num1*num2>=100);来循环判断,直到输出合适的数字
4. 如何将结果导入文件?
fflush会强迫将缓冲区内的数据写回参数stream 指定的文件中。
C 库函数 int fprintf(FILE *stream, const char *format, …) 发送格式化输出到流 stream 中
FILE *fp=fopen("record.txt","a");fprintf(fp,"用户id:%s",idCS);fclose(fp);fflush(stdin);
- 如何测定做题所用的时间?
startTime=clock();(double)(clock()- startTime)/CLOCKS_PER_SEC)
clock函数返回自程序启动起,处理器时钟所使用的时间。
6. 如何实现程序运行结束后,让其返回返回到最初的输入界面?
在主函数中使用一while循环,当程序返回值时,退出程序。
7.如何在用户读取答题记录时,让程序扫描文件读出特定的行,从而不显示其他人的信息,在这里所用方法是
while(!feof(fp)){fgets(str,100,fp);if(feof(fp)){break;}char tmp[7];for(int i = 0;i<6;i++){tmp[i] = str[i];}if(!strcmp(tmp,idCS)){printf("%s",str);}
}
feof用于判断是否达到文件末尾
fgets函数用于读取特定行的数据,将所读的数据前六个账号储存到新的数组中,然后对比已经输入的账号,如果相同,则打印输出。