C语言博客作业03--函数
0.展示PTA总分
1.本章学习总结
1.1 学习内容总结
函数的作用
简化主函数,让代码更具有可读性,更简洁。因为一个函数可以实现某个功能而不被主函数限制,所以函数可以在其他程序上使用,具有高度的灵活性。
函数的结构
函数由首部和函数体构成。首部用来声明函数类型、定义实参。函数体用来实现函数功能。
函数的形参与实参
形参与实参类型必须一致。实参只会将数值传给形参,自身不会变化。
局部变量、全局变量、静态变量
局部变量只在定义它的函数内有效,但是在函数返回后失效。
全局变量在整个程序内有效。
静态变量未对其赋初值时,系统自动赋值0;每次静态变量被改变后,它的新值保存下来。
1.2 本章学习体会
函数的使用让原本繁琐、冗杂、重复的工作得以简化,同时也让我知道了结构化程序设计思想,让我对一个程序的设计有了更深入的认识。
代码量统计:1034行(每个程序减去两行大括号)
2. 综合作业—小学生口算表达式自动生成系统
本次作业的函数关系图
3.函数功能及全局变量介绍
3.1.全局变量
static int a[5];//a[4]用于存放答案
int flag = 0;//用于返回上一级的中转变量
int i;//循环用的变量
int n;//题目数
int j=0;//已做题目数
int answer;//用户答案
int ture = 0;//正确题目数
double accuracy;//正确率
int g;//年级
int c;//答题结束后,用户的选择
srand(time(0));//随机数函数
3.2.ListMenu()函数
//说明
printf("欢迎使用小学生口算表达式自动生成系统,本系统适用于一至三年级学生。\n");
printf("本程序保证所有答案均不为负数,所以输入-1可以返回上一级,但是在本级所做任何操作清零。\n");
printf("年级选择规则如下:\n");
printf("1.选择1、2、3年级为覆盖型出题,即二年级包含一年级题目,三年级包含一、二年级题目。\n");
printf("2.选择4、5为独立性出题,即只出二、三年级对应难度的题目。\n\n");
3.3. 其它函数
void problem(int a[],int g)//出题
{
int x;//题目类型
int c1;
int c2;
switch (g)
{
case 1:x = rand() % 6 + 1;break;
case 2:x = rand() % 16 + 1; break;
case 3:x = rand() % 23 + 1;break;
case 4:x = 7 + rand() % 10; break;
case 5:x = 17 + rand() % 7; break;
}
c1 = rand() % 2;
c2 = rand() % 2;
switch (x)
{
//一年级题目
case 1://20以内加减
a[1] = rand() % 20 + 1;
a[2] = rand() % 20 + 1;
swap(a);
type1(a, c1);
break;
case 2://20以内填括号
a[1] = rand() % 20 + 1;
a[2] = rand() % 20 + 1;
swap(a);
if (c1 == 0)
{
printf("%d+?=%d,?=", a[2], a[1]);
a[4] = a[1] - a[2];
}
else
{
printf("%d-?=%d,?=", a[1], a[2]);
a[4] = a[1] - a[2];
}
break;
case 3://整十加减一位数or两位数加减一位数
a[1] = (rand() % 9 + 1) * 10 + rand() % 10;
a[2] = rand() % 9 + 1;
type1(a, c1);
break;
case 4://整十加减整十
a[1] = (rand() % 9 + 1) * 10;
a[2] = (rand() % 9 + 1) * 10;
swap(a);
type1(a, c1);
break;
case 5://两位数加减整十
a[1] = (rand() % 9 + 1) * 10 + rand() % 10;
a[2] = rand() % (a[1] / 10) * 10;
type1(a, c1);
break;
case 6://100以内三位数连续加减
while (1)
{
a[1] = (rand() % 9 + 1) * 10 + rand() % 10;
a[2] = (rand() % 9 + 1) * 10 + rand() % 10;
a[3] = (rand() % 9 + 1) * 10 + rand() % 10;
if (c1 == 0 && c2 == 0)//a+b+c
{
printf("%d+%d+%d=", a[1], a[2], a[3]);
a[4] = a[1] + a[2] + a[3];
break;
}
if (c1 == 0 && c2 == 1)//a+b-c
{
a[4] = a[1] + a[2] - a[3];
if (a[4] < 0) continue;
printf("%d+%d-%d=", a[1], a[2], a[3]);
break;
}
if (c1 == 1 && c2 == 0)//a-b+c
{
a[4] = a[1] - a[2] + a[3];
if (a[4] < 0) continue;
printf("%d-%d+%d=", a[1], a[2], a[3]);
break;
}
if (c1 == 1 && c2 == 1)//a-b-c
{
a[4] = a[1] - a[2] - a[3];
if (a[4] < 0) continue;
printf("%d-%d-%d=", a[1], a[2], a[3]);
break;
}
}
break;
//二年级题目
case 7://两位数加减两位数or整十数减两位数
a[1] = (rand() % 9 + 1) * 10 + rand() % 10;
a[2] = (rand() % 9 + 1) * 10 + rand() % 10;
swap(a);
type1(a, c1);
break;
case 8://九九乘法or除法
a[1] = rand() % 9 + 1;
a[2] = rand() % 8 + 2;
a[3] = a[1] * a[2];
if (c1 == 0)
{
type4(a);
}
else
{
printf("%d/%d=", a[3], a[1]);
a[4] = a[2];
}
break;
case 9://整千加减法(和在一万内)
if (c1 == 0)
{
a[1] = (rand() % 5 + 1) * 1000;
a[2] = (rand() % 4 + 1) * 1000;
printf("%d+%d=", a[1], a[2]);
a[4] = a[1] + a[2];
}
else
{
a[1] = (rand() % 9 + 1) * 1000;
a[2] = (rand() % 8 + 1) * 1000;
printf("%d-%d=", a[1], a[2]);
a[4] = a[1] - a[2];
}
break;
case 10://整十加整十(进位)or整十减整十(退位)
type2(a, c1, 1);
break;
case 11://整百加整百(进位)or整百减整百(退位)
type2(a, c1, 10);
break;
case 12://尾数为0三位数加法(和在1000内)or尾数为0的减法
switch (c1)
{
case 0:
while (1)
{
a[1] = (rand() % 99 + 1) * 10;
a[2] = (rand() % 99 + 1) * 10;
if (a[1] + a[2] < 1000)
{
printf("%d+%d=", a[1], a[2]);
a[4] = a[1] + a[2];
break;
}
else { continue; }
}
break;
case 1:
while (1)
{
a[1] = (rand() % 99 + 1) * 10;
a[2] = (rand() % 99 + 1) * 10;
swap(a);
printf("%d-%d=", a[1], a[2]);
a[4] = a[1] - a[2];
break;
}
break;
}
break;
case 13://十以内整数连乘
a[1] = (rand() % 8 + 2);
a[2] = (rand() % 8 + 2);
a[3] = (rand() % 8 + 2);
printf("%d*%d*%d=", a[1], a[2], a[3]);
a[4] = a[1] * a[2] * a[3];
break;
case 14://十以内整数连除
a[1] = (rand() % 8 + 2);
a[2] = (rand() % 8 + 2);
a[3] = a[1] * a[2] * (rand() % 9 + 1);
printf("%d/%d/%d=", a[3], a[1], a[2]);
a[4] = a[3] / a[1] / a[2];
break;
case 15://10以内整数乘除混算
a[1] = (rand() % 8 + 2);
a[2] = (rand() % 8 + 2);
a[3] = a[1] * (rand() % 8 + 2);
printf("%d/%d*%d=", a[3], a[1], a[2]);
a[4] = a[3] / a[1] * a[2];
break;
case 16://含有小括号的混合运算
while (1)
{
a[1] = (rand() % 99 + 1);
a[2] = (rand() % 99 + 1);
a[3] = rand() % 8 + 2;
swap(a);
if (c1 == 0)
{
printf("(%d-%d)*%d=", a[1], a[2], a[3]);
a[4] = (a[1] - a[2]) * a[3];
break;
}
else
{
if ((a[1] - a[2]) % a[3] == 0)
{
printf("(%d-%d)/%d=", a[1], a[2], a[3]);
a[4] = (a[1] - a[2]) / a[3];
break;
}
else
{
continue;
}
}
}
break;
//三年级题目
case 17://三位数加减法
a[1] = (rand() % 999 + 1);
a[2] = (rand() % 999 + 1);
swap(a);
type1(a, c1);
break;
case 18://一位数乘以两位数or两位数乘以两位数
a[1] = (rand() % 99 + 1);
a[2] = rand() % 89 + 11;
type4(a);
break;
case 19://三位数乘以三位数or两位数乘以三位数or一位数乘以三位数
a[1] = (rand() % 999 + 1);
a[2] = rand() % 899 + 101;
type4(a);
break;
case 20://万以内加减法
a[1] = rand() % 9999 + 1;
a[2] = rand() % 9999 + 1;
swap(a);
type1(a, c1);
break;
case 21://两位数除以一位数
a[1] = rand() % 8 + 2;
a[2] = a[1]*(rand() % 9 + 1);
type3(a, 1);
break;
case 22://三位数除以一位数
a[1] = rand() % 8 + 2;
a[2] = a[1] * (rand() % 99 + 1);
type3(a, 10);
break;
case 23://百以内三数连减
a[1] = rand() % 99 + 1;
a[2] = rand() % 99 + 1;
a[3] = a[1]+a[2]+(rand() % 9 + 1);
printf("%d-%d-%d=", a[3], a[1], a[2]);
a[4] = a[3] - a[1] - a[2];
break;
}
}
void swap(int a[])//防止答案为负数
{
int t;
if (a[1] < a[2])
{
t = a[1];
a[1] = a[2];
a[2] = t;
}
}
void type1(int a[],int c1)//a[1]加减a[2]
{
if (c1 == 0)
{
printf("%d+%d=", a[1], a[2]);
a[4] = a[1] + a[2];
}
else
{
printf("%d-%d=", a[1], a[2]);
a[4] = a[1] - a[2];
}
}
void type2(int a[], int c1, int n)//整十(百)加整十(百) (进位)or整十(百)减整十(百) (退位)
{
switch (c1)
{
case 0:
while (1)
{
a[1] = (rand() % 9 + 1) * 10 * n;
a[2] = (rand() % 9 + 1) * 10 * n;
if (a[1] + a[2] >= 100 * n)
{
printf("%d+%d=", a[1], a[2]);
a[4] = a[1] + a[2];
break;
}
else { continue; }
}
break;
case 1:
while (1)
{
a[1] = (rand() % 9 + 1) * 10 * n + 100 * n;
a[2] = (rand() % 9 + 1) * 10 * n;
if (a[1] - a[2] < 100 * n)
{
printf("%d-%d=", a[1], a[2]);
a[4] = a[1] - a[2];
break;
}
else { continue; }
}
}
}
void type3(int a[], int n)//两(三)位数除以一位数
{
while (a[2] < 10*n)
{
a[2] = a[2] * 2;
}
printf("%d/%d=", a[2], a[1]);
a[4] = a[2] / a[1];
}
void type4(int a[])//a[1]*a[2]
{
printf("%d*%d=", a[1], a[2]);
a[4] = a[1] * a[2];
}
4.运行结果截图,测试用例。
一年级
二年级
三年级
5. 调试碰到问题及解决办法
Q1:当用户作答0题退出时,正确率计算异常。
A1:使用if语句让此情况下正确率直接赋值为0。
Q2:答案出现负数。
A2:对数据进行处理使得答案为正数,个别数据难以处理直接令其重新赋值。
6.大作业总结
在编写这个程序的过程中,让我知道了做题目和写程序的不同,一个程序除了本身功能要齐全外,还需要与用户进行沟通。因为这个程序功能较多,所以需要较大的思考量,对于自己的编程能力也有一个很大的提高。在年级选择的基础上,我添加了4、5这两个选项,用来专门出二、三年级的题目。