“C语言程序:小学生算术自测”二次开发
(1)程序来源
该程序来源于室友大一下C语言期末大作业
(2)运行环境+运行结果截图
使用VS2022版本编译器完成代码运行



点击查看代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
int randomNumber(int w);
char randomSymbol();
int main()
{
int n, w, num;
printf("欢迎来到奶龙的口算乐园,我是奶龙!\n");
int count = 0;
char continueFlag;
do
{
printf("您想要练习几位数以内的口算?\n");
scanf("%d", &w);
printf("您想要练习多少道题?\n");
scanf("%d", &num);
printf("开始练习:\n");
////////////////////////////////////////////////////
int count = 0;
for (int i = 1; i <= num; i++)
{
char c = randomSymbol();
int num1 = randomNumber(w);
int num2 = randomNumber(w);
printf("%d %c %d = ", num1, c, num2);
////////////////////////////////////////////////////
int answer, REanswer;
if (c == '+')
REanswer = num1 + num2;
else REanswer = num1 - num2;
////////////////////////////////////////////////////
scanf("%d", &answer);
if (answer == REanswer)
{
printf(" √\n");
count++;
}
else printf(" ×\n");
}
printf("本轮结束,答对%d题,", count);
float c = (float)count;
float numm = (float)num;
float result = c / numm;
if (result >= 0.9)
printf("优秀\n");
else if (result < 0.9 && result >= 0.7)
printf("良好\n");
else if (result < 0.7 && result >= 0.5)
printf("不错\n");
else
printf("菜就多练\n\n\n");
printf("还要继续练习吗?(y/n):\n");
scanf(" %c", &continueFlag);
} while (continueFlag == 'y');
printf("\n\n结束练习\n");
return 0;
}
int randomNumber(int w)//生成0=max以内的随机数
{
int a;
static int firstCall = 1;
if (firstCall)
{
srand((unsigned int)time(NULL));
firstCall = 0;
}
int digit = pow(10, w);
a = rand() % (digit + 1);
return a;
}
char randomSymbol()
{
srand((unsigned int)time(NULL));
int a = rand() % (1 - 0 + 1) + 0;
if (a == 0)
return '+';
else return '-';
}
(3)主要问题与改进思路
整体程序较为完整,主要有以下问题。
1.程序主要针对小学生群体,所以在减法中不会出现负数结果,例如“5-8=-3”的结果。
2.随机数范围错误:randomNumber 中 pow(10, w) 返回浮点数,直接用于取模可能有精度问题
3.输入合法性未校验:用户输入非数字时,程序会进入死循环或异常状态。
改进思路:解决上述3个主要问题并对整个程序的细节方面进行优化,如:增加答题准确率功能。
(4)新代码
解决减法负数问题:
点击查看代码
char randomSymbol(int num1, int num2)
{
int a = rand() % 2; // 0=+, 1=-
if (a == 0)
{
return '+';
}
else
{
if (num1 < num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
return '-';
}
}
int num1 = randomNumber(w);
int num2 = randomNumber(w);
char c = randomSymbol(num1, num2);
2.随机数问题
点击查看代码
int randomNumber(int w)
{
static int firstCall = 1;
if (firstCall)
{
srand((unsigned int)time(NULL));
firstCall = 0;
}
int digit = 1;
for (int i = 0; i < w; i++)
{
digit *= 10;
}
a = rand() % (digit + 1);
return a;
}
3.输入字符校验
点击查看代码
int checkIntInput(int *input)
{
while (getchar() != '\n');
if (scanf("%d", input) != 1)
{
printf("输入错误!请输入数字!\n");
while (getchar() != '\n');
return 0;
}
return 1;
}
printf("您想要练习几位数以内的口算?\n");
while (!checkIntInput(&w) || w < 1 || w > 4)
{
printf("请输入1-4之间的数字!\n");
}
printf("您想要练习多少道题?\n");
while (!checkIntInput(&num) || num < 1 || num > 100)
{
printf("请输入1-100之间的数字!\n");
}
printf("%d %c %d = ", num1, c, num2);
while (!checkIntInput(&answer))
{
printf("答案输入错误!请输入数字:");
}
4.添加答题准确率
点击查看代码
float accuracy = result * 100; // 转换为百分比
printf("本轮结束,答对%d题,准确率:%.2f%%\n", count, accuracy); // 显示准确率
5.优化随机数种子
点击查看代码
int main()
{
srand((unsigned int)time(NULL));
int n, w, num;
}
(5)重构的软件测试截图



(6)总结
核心难点主要有三处:一是随机数相关的修复,原本用 pow 计算位数会有浮点数精度问题,得换成整数循环来算,而且重复初始化随机数种子会导致符号不随机,要调整成只在主函数开头初始化一次;二是减法防负数的处理,得反过来想,不能先随机符号再生成数字,而是先出数字,再根据两个数的大小调整符号,甚至交换数值,确保减法结果非负;三是输入校验,要考虑到用户可能输非数字的情况,花了不少时间。整个优化过程需要结合小学生口算的实际场景倒推,既要保证代码不出错,又要符合口算题的实际使用需求。

浙公网安备 33010602011771号