C语言博客作业03--函数
| 这个作业属于哪个班级 | C语言--网络2011/2012 |
| ---- | ---- | ---- |
| 这个作业的地址 | C博客作业03--函数 |
| 这个作业的目标 | 学习如何设计函数、C语言基本数据类型 |
| 姓名 | 胡旻轩 |
目录
0.展示PTA总分
1.本章学习总结
1.1 函数定义、调用、声明
1.2 全局、局部变量、静态局部变量
1.3 C数据类型及注意点
1.4 C运算符
学习体会
2.综合作业:小学生口算表达式自动生成系统
2.1.模块流程图
2.2.函数功能及全局变量介绍
2.2.1.全局变量
2.2.2 菜单相关函数
2.2.2 出题相关函数
2.3.运行结果截图,测试用例。
2.4.大作业中编程技巧总结
0.展示PTA总分
1.本章学习总结
1.1 函数定义、调用、声明
将代码段封装成函数的过程叫做函数定义。
函数定义时候,需要拥有返回值的类型,它可以是C语言中的任意数据类型,例如 int、float、char 等。在返回值类型之后带上函数名称,它是标识符的一种,命名规则和标识符相同。函数名后面的括号( )不能少。
大括号{}内部的内容主体是函数体,它是函数需要执行的代码,是函数的主体部分。即使只有一个语句,函数体也要由{ }包围。
如果函数有返回值,在函数体中使用 return 语句返回。return 出来的数据的类型要和我们定义的函数返回值类型一样。
在使用函数之前应该先声明,事先通知编译器该函数的类型:换句话说,一个声明即是描述一个函数的接口。声明至少应指明函数返回值的类型。同时,函数声明时,其()后一定要带上分号。
关于函数的调用:每一种函数都有它的作用,在需要使用时,直接进行调用就可以了。甚至可以在使用函数时在函数内再调用函数。
注意:强调一点,C语言不允许函数嵌套定义;也就是说,不能在一个函数中定义另外一个函数,必须在所有函数之外定义另外一个函数。main() 也是一个函数定义,也不能在 main() 函数内部定义新函数。
1.2 全局、局部变量、静态局部变量
关于函数局部变量及全局变量:
简单区分:
定义在函数之外的就是全局变量,这个变量所有函数都可以直接使用,并且共用同一个地址。任意函数修改了变量值,其他函数调用也会变。
定义在函数之内的就是局部变量,局部变量只属于该函数,其他函数即使定义了同样名字的变量,这两个变量也不同地址,互不相干。
比如:
int a;//这就是全局变量,作用域下所有函数共用
int main()
{
int b;//这就是局部变量,只在本函数有效,如果想在调用fun函数时让fun也使用该变量,需要把这个变量的地址作为参数传递过去。
printf("%d",b);
return 0;
}
注意:c语言中允许局部变量和全局变量同名,但是同名的局部变量会屏蔽全局变量,实际代码避免同名。
关于函数传值和传址:
如函数void fun(int a,int *b){..........};这里形参a 和*b,分别表示一个值和一个地址
所以在调用该函数时,比如:
int main()
{
int c,d;
fun(c,&d);//这里调用就对应上面形参类型,第一个参数传递了c的值(传值),第二个参数传递了d的地址(传址),这里c和&d,叫做实参。当fun函数运行时改变了a和b指向地址的值,对应main函数中c的值不变,d的值改变。
return 0;
}
顺带一说:局部变量,在函数运行结束后会自动释放,所以想把局部变量地址作为返回值,需要用malloc函数申请。
对静态局部变量的说明:
1) 静态局部变量属于静态存储类别,在静态存储区内分配存储单元。在程序整个运行期间 都不释放。而自动变量(即动态局部变量)属于动态存储类别,占动态存储空间,函数 调用结束后即释放。
2) 静态局部变量在编译时赋初值,即只赋初值一次;而对自动变量赋初值是在函数调用时 进行,每调用一次函数重新给一次初值,相当于执行一次赋值语句。
3) 如果在定义局部变量时不赋初值的话,则对静态局部变量来说,编译时自动赋初值 0(对 数值型变量)或空字符(对字符变量)。而对自动变量来说,如果不赋初值则它的值是 一个不确定的值。
1.3 C数据类型及注意点
- 每个数据类型特点及其相关知识的扩展。如浮点误差、字符型数据输入问题等等
- 返回值为整形用int
- 返回值为双精度用double
- 无返回值用void
- 整型:short<int<long<long long
- 浮点型:float<double
- 字符型:char
- 浮点误差处理:后+0.00001
1.4 C运算符
学习体会
其实再c的学习中,我们无时无刻都在运用着函数。同时,在合理的调用和通过自定义函数的方式,可以让我们的代码更加具有可读性和规范性。同时,一些需要重复的步骤,我们可以通过函数的自定义和调用来减少代码的书写量,并且通过头文件,主文件等等的分类,开始让我们的代码变得拥有向规范化的方向所靠近,逐步培养程序员的代码编写修养。同时,现在,我们必须要在必要的代码行旁边加上注释了,随着代码量增加和规范化,要是连自己的代码都无法明确区分,那么如何指望别人看得懂你的代码呢?
2.综合作业:小学生口算表达式自动生成系统
2.1.模块流程图
2.2.函数功能及全局变量介绍
2.2.1.全局变量
- 无全局变量
2.2.2 菜单相关函数
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<time.h>
#include"expression"
void OperateMenu()//游戏操作界面
{
char option;
int i;
int temp;
system("cls");//清屏
do
{
system("cls");
printf("******************************************\n");
printf("1.一年级口算\n");
printf("2.二年级口算\n");
printf("3.三年级口算\n");
printf("4.退出系统\n");
printf("******************************************\n");
printf("请输入您的选择:");
scanf(" %c", &option);
switch (option)
{
case '1':
system("cls");
GradeOneMenu();
//GradeOneMenu();
break;
case '2':
system("cls");
GradeTwoMenu();
break;
case '3':
system("cls");
GradeThreeMenu();
break;
case '4':
printf("\n谢谢您的参与!\n");
Sleep(500);
exit(0);
default:
printf("您输入不对,只能输入1,2,3,4,请重输!\n");
Sleep(500);
}
} while (!(option >= '1' && option <= '4'));
}
2.2.2 出题相关函数
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<time.h>
#include"QAQ.h"
void GradeOneMenu()//一年级
{
while (1)
{
system("cls");
printf("*********************一年级小朋友好!********************************\n");
printf("系统将随机生成一个口算式,如果您会做,则输入y,输入结果。\n");
printf("**如果您不想做,输入n退回主菜单。\n");
printf("***************************************************************\n");
/*1.生成操作数函数*/
/*2.生成随机运算符函数*/
/*3.根据年级判断生成的表达式是否合理的函数(选做)*/
/*4.生成表达式函数,并输出展示*/
printf("是否继续答题/n:");
char ch;
scanf("\n%c", &ch);
if (ch == 'n')
{
Sleep(500);
OperateMenu();
return;
}
if (ch == 'y')//选择答题
{
/*答题模块*/
int i, count = 0, right = 0;
printf("请输入你要写的题数:");
scanf("%d", &count);
for (i = 1; i <= count; i++)
{
char choose;
printf("如果你想退出打出e,若想继续请打回车\n");
scanf("%c", &choose);
choose = getchar();
if (choose == 'e')
{
break;
}
int num1, num2, answer, rightkey = 0;
char symbol;
srand((unsigned)time(NULL));
num1 = GetNumber(1);
num2 = GetNumber(1);
symbol = GetSymbol(1);
if (num1 < num2)
{
int temp;
temp = num1;
num1 = num2;
num2 = temp;
}
printf("%d%c%d=", num1, symbol, num2);
scanf("%d", &answer);
switch (symbol)
{
case '+':rightkey = num1 + num2; break;
case '-':rightkey = num1 - num2; break;
}
if (answer == rightkey)
{
right++;
printf("棒极了!!\n");
}
else
{
printf("┗|`O′|┛ 嗷~~,答错了");
printf("正确答案:%d\n", rightkey);
}
Sleep(1000);
system("cls");
}
double accuracy = 0;
if (i >= 2)
{
accuracy = right * 1.0 / count;
printf("正确率:%.2f\n", accuracy);
if (accuracy >= 0.9999)
{
printf("恭喜小朋友全对了,奖励一朵小红花!");
}
else if (accuracy > 0.6)
{
printf("优秀!");
}
else if (accuracy == 0.6)
{
printf("及格了!");
}
else if (accuracy < 0.6 && accuracy >= 0.0001)
{
printf("很遗憾,请再次努力!");
}
else
{
printf("需要多多练习了!");
}
Sleep(2000);
}
}
}
}
void GradeTwoMenu()//二年级
{
while (1)
{
system("cls");
printf("*********************二年级小朋友好!********************************\n");
printf("系统将随机生成一个口算式,如果您会做,则输入y,输入结果。\n");
printf("**如果您不想做,输入n退回主菜单。\n");
printf("***************************************************************\n");
/*1.生成操作数函数*/
/*2.生成随机运算符函数*/
/*3.根据年级判断生成的表达式是否合理的函数(选做)*/
/*4.生成表达式函数,并输出展示*/
printf("是否继续答题y/n:");
char ch;
scanf("\n%c", &ch);
if (ch == 'n')
{
Sleep(500);
OperateMenu();
return;
}
if (ch == 'y')//选择答题
{
/*答题模块*/
int i, count = 0, right = 0;
printf("请输入你要写的题数:");
scanf("%d", &count);
for (i = 1; i <= count; i++)
{
char choose;
printf("如果你想退出打出e,若想继续请打回车\n");
scanf("%c", &choose);
choose = getchar();
if (choose == 'e')
{
break;
}
int num1, num2, answer, rightkey = 0;
char symbol;
srand((unsigned)time(NULL));
symbol = GetSymbol(2);
if (symbol == '*')
{
num1 = GetNumber(1);
num2 = GetNumber(1);
}
else if (symbol == '/')
{
num2 = GetNumber(1);
num1 = GetNumber(1) * num2;
}
else
{
num1 = GetNumber(2);
num2 = GetNumber(2);
}
if (num1 < num2)
{
int temp;
temp = num1;
num1 = num2;
num2 = temp;
}
printf("%d%c%d=", num1, symbol, num2);
scanf("%d", &answer);
switch (symbol)
{
case '+':rightkey = num1 + num2; break;
case '-':rightkey = num1 - num2; break;
case'*':rightkey = num1 * num2; break;
case'/':rightkey = num1 / num2; break;
}
if (answer == rightkey)
{
right++;
printf("好样的,答对了!!\n");
}
else
{
printf("呜呜呜,答错了!");
printf("正确答案:%d\n", rightkey);
}
Sleep(1000);
system("cls");
}
double accuracy = 0;
if (i >= 2)
{
accuracy = right * 1.0 / count;
printf("正确率:%.2f\n", accuracy);
if (accuracy >= 0.9999)
{
printf("恭喜小朋友全对了,奖励一朵小红花!");
}
else if (accuracy > 0.6)
{
printf("优秀,可惜没有全对!");
}
else if (accuracy == 0.6)
{
printf("及格了!");
}
else if (accuracy < 0.6 && accuracy >= 0.0001)
{
printf("很遗憾,请再次努力!");
}
else
{
printf("需要多多练习了!");
}
Sleep(2000);
}
}
}
}
void GradeThreeMenu()//三年级
{
while (1)
{
system("cls");
printf("*********************三年级小朋友好!********************************\n");
printf("系统将随机生成一个口算式,如果您会做,则输入y,输入结果。\n");
printf("**如果您不想做,输入n退回主菜单。\n");
printf("***************************************************************\n");
/*1.生成操作数函数*/
/*2.生成随机运算符函数*/
/*3.根据年级判断生成的表达式是否合理的函数(选做)*/
/*4.生成表达式函数,并输出展示*/
printf("是否继续答题y/n:");
char ch;
scanf("\n%c", &ch);
if (ch == 'n')
{
Sleep(500);
OperateMenu();
return;
}
if (ch == 'y')//选择答题
{
/*答题模块*/
int i, count = 0, right = 0;
printf("请输入你要写的题数:");
scanf("%d", &count);
for (i = 1; i <= count; i++)
{
char choose;
printf("如果你想退出打出e,若想继续请打回车\n");
scanf("%c", &choose);
choose = getchar();
if (choose == 'e')break;
int num1, num2, answer, rightkey = 0;
char symbol;
srand((unsigned)time(NULL));
symbol = GetSymbol(2);
if (symbol == '/')
{
num2 = GetNumber(3);
num1 = GetNumber(2) * num2;
}
else
{
num1 = GetNumber(2);
num2 = GetNumber(2);
}
if (num1 < num2)
{
int temp;
temp = num1;
num1 = num2;
num2 = temp;
}
printf("%d%c%d=", num1, symbol, num2);
scanf("%d", &answer);
switch (symbol)
{
case '+':rightkey = num1 + num2; break;
case '-':rightkey = num1 - num2; break;
case'*':rightkey = num1 * num2; break;
case'/':rightkey = num1 / num2; break;
}
if (answer == rightkey)
{
right++;
printf("嘿嘿,答得真棒!!\n");
}
else
{
printf("这不应该啊!");
printf("正确答案:%d\n", rightkey);
}
Sleep(1000);
system("cls");
}
double accuracy = 0;
if (i >= 2)
{
accuracy = right * 1.0 / count;
printf("正确率:%.2f\n", accuracy);
if (accuracy >= 0.9999)
{
printf("恭喜小朋友全对了,奖励一朵小红花!");
}
else if (accuracy > 0.6)
{
printf("优秀,可惜没有全对!");
}
else if (accuracy == 0.6)
{
printf("及格了!");
}
else if (accuracy < 0.6 && accuracy >= 0.0001)
{
printf("很遗憾,请再次努力!");
}
else
{
printf("需要多多练习了!");
}
Sleep(2000);
}
}
}
}
2.3.运行结果截图,测试用例。
2.4.大作业中编程技巧总结
- srand函数:可通过修改种子将rand生成随机数变为真随机数。
- 通过随机数的调用产生适当额外增加一些趣味鼓励的话,使得程序变得生动。
- 第二点的方法来源于林丽老师的课堂派作业中的一道题目收到的启发。(截图如下)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人