| 这个作业属于哪个班级 | C语言--网络2011/2012 |
| ---- | ---- | ---- |
| 这个作业的地址 | C博客作业03--函数 |
| 这个作业的目标 | 学习如何设计函数、C语言基本数据类型 |

0.展示PTA总分



1.本章学习总结

1.1 函数定义、调用、声明

  • 函数的定义:函数类型 函数名 ( 形参表 ) //函数头
    {
    执行语句 //函数体
    return 语句 //结束函数,函数返回值
    }
  • 函数的调用:函数名( 实参 )
    * 注:若函数没有需要传入的参数,也需要圆括号来表示这是一个函数。
    * 注:函数在调用之前必须要先有定义
    * 注:一般调用之前要有函数的声明。若函数定义在调用地方的上面,则不进行声明,也能编译成功,但不推荐使用。
  • 函数的声明:函数类型 函数名 ( 参数表 );
    * 注:函数的声明即为函数头加上分号
  • 注意事项:
    • 函数的参数是单向传递的,两个函数中,相同变量名局部变量没有关系。

1.2 全局、局部变量、静态局部变量

  • 全局变量:
    • 在函数定义的变量,不属于任何一个函数
    • 作用范围:从定义开始,到源文件结束(在各个函数中均可使用)
  • 局部变量:
    • 1.在函数定义的变量,包含函数的形参
    • 2.在复合语句内定义的变量
  • 备注:
    • 若全局变量和局部变量同名局部变量优先
    • 在较大的程序中,过多地使用全局变量,可能导致不同函数之间的相互干扰
    • 尽量使用局部变量,避免不同函数间的相互干扰,提高代码质量
    • 全局变量适用于某些变量值其它函数共享的情况
  • 静态、动态变量
    • 动态变量:
      自动变量、普通局部变量
      * auto int number; 其中"auto"可省略
      * 动态变量若没有赋初值, 存储单元中将会是随机值
      * 函数调用时,定义变量,分配存储单元
      ——>函数调用结束收回存储单元
    • 静态变量:
      全局变量、静态局部变量
      * 静态局部变量:static int number;
      * 静态变量若没有赋初值,系统将自动赋0。(注意: 赋初值只在函数第一次调用时起作用,以后调用都按照前一次调用的值保留)
      * 从变量定义开始,到程序结束,始终存在。(注意:虽然始终存在,但是静态局部变量仍受到变量作用范围限制,不能作用于其它函数(包括主函数))

1.3 C数据类型及注意点

  • 无符号数据类型:没有符号位
  • 有符号数据类型:最左边一位表示符号位
  • 短整型: short (int) ———>2个字节
  • 整型: int ———>4个字节
  • 长整型: long int (备注:VS中long 仅有4个字节,而 long long 才有8个字节。输出时,printf("%lld",number);
  • 浮点型(实型):
    • 单精度浮点型: float ———>4个字节
    • 双精度浮点型: double ———>8个字节
  • 字符型:
    • 字符型:char ———>1个字节
  • 备注:
    • double 类型的表数范围比long long类型的
    • 实数类型的变量有浮点误差,所以实数一般直接判断相等,而是如判断number等于5:
      fabs(number - 5)<0.000001

--

  • 整数的表示
    • 十进制:0~9
      例如:99
    • 八进制:0~7,且首位为0
      例如:077
    • 十六进制:09,af,A~F,且首位为0X或0x
      例如:0x2ad
  • 实数的表示
    • 浮点表示:12.0 12. .12
    • 科学计数法:6.02-E27 1.2e+37 1E+5
      (指数只能整数E前要有数字
    • 指数型输入float(%e),double(%le)。指数型输出(%e)

--

  • 格式说明
    十进制 八进制 十六进制
    int %d %o %x
    long %ld %lo %lx
    unsigned %u %o %x
    unsigned long %lu %lo %lx

--


1.4 C运算符

  • 位运算符:
运算符 说明
& 按位与
^ 按位异或
~ 按位取反
<< 左移
>> 右移
  • 位运算符
    • &:按位与,一位为0,则为0;全部为1才为1;
    • |:按位或,全部为0,才为0;一位为1就为1;
    • ^:按位异或,(双目运算符),相同则为1,不同则为0;
    • ~:按位取反,就是取反
    • <<:左移,(双目运算符)(例子:number << 3),将数值向左移3位,空出的位用零填补
    • >>: 右移,(双目运算符)
    • 备注:
      * 左(右)移一位相当于乘(除以)2
      * 左(右)移动不改变原本操作数的数值
  • 算术运算符:
    • 单目:+、-、++、--
      同优先级时:结合(从右向左)

    • 双目:+、-、*、/、%
      同优先级时:结合(从左向右)、(加减优先级比乘除低)

    • 备注:
      * 单目运算符仅需要一个操作数
      * 双目运算符的两个操作数如果数据类型不同,将进行自动类型转换后再进行计算
      * % 的两个操作数都必须是整数
      * 赋值运算的优先级很低,从右向左

    • 其它运算符:sizeof()
      * 计算变量或数据类型的字节长度
      * sizeof(int)
      * int number;
      sizeof(number);

    • 复合运算符:

复合算术赋值运算符 复合位赋值运算符
+= &=
-= |=
*=
/=
%=
  • 逻辑运算符:&&、||、!
    • 优先级:!>&&>||
  • 逗号表达式:
    • 表达式1,表达式2,......,表达式n
      依次计算表达式1、2、3...... n 的值,并将表达式 n 的值作为逗号表达式的值
    • 逗号运算符的优先级最低结合(从左向右)


2.综合作业:小学生口算表达式自动生成系统

2.1.模块流程图






2.2.函数功能及全局变量介绍

  • /Menu/
    • void OperateMenu(); //游戏初始菜单
    • void GradeOneMenu(); //一年级菜单
    • void GradeTwoMenu(); //二年级菜单
    • void GradeThreeMenu(); //三年级菜单
    • void Encourage(double rate, int sumCount); //鼓励小朋友

  • /Calculation/
    • int RandomOperands(int grand); //随机操作数
    • char RandomOperator(int grand); //随机运算符
    • double FormulaAndAnswer(int grand); //生成算式

  • /Judgement/
    • double IsCorrect(int value1, int value2, char operate); //判断正确与否,计算正确率
    • void IsChallenge(double rate, int level); //小朋友的挑战题目


2.2.1.全局变量

int sumCount = 0; //做题数

int correctCount = 0; //正确回答的题数


2.2.2 菜单相关函数

void GradeOneMenu(); //一年级菜单

void GradeTwoMenu(); //二年级菜单

void GradeThreeMenu(); //三年级菜单

  • 功能:
    • 实现人机交互。输出菜单,用户可以输入答案,也可以选择是否继续答题。
    • 输出答题数、正答率,答题情况,增强用户的操作体验。
  • 思路
    • 输出是否答题界面,用户决定是否答题。
    • 若用户选择答题,则输出算式,并在用户答错后输出正确答案。
    • 若用户结束答题,计算并输出用户答题数、正答率。
    • 判断正答率是否高于80%,若高于,则邀请用户进行“挑战”。
    • 若用户意外输出不合法数值,请求用户重新输入。
    • 代码:


      --

void Encourage(double rate, int sumCount); //鼓励小朋友

  • 功能:
    • 根据小朋友的正答率、答题数,输出相应的随机语句。
    • 增强人机交互的感觉,提高用户体验。
  • 思路
    • 将正答率分为(0,60)、60、(60,90]、(90,100]四个范围,根据不同范围,输出不同的话语。
    • 若正答率为100,且答题数>9,则输出特殊的话语。
  • 代码:


2.2.2 出题相关函数

int RandomOperands(int grand); //随机操作数

char RandomOperator(int grand); //随机运算符

double FormulaAndAnswer(int grand); //生成算式

  • 功能:生成随机操作数、生成随机运算符、输出合理算式

  • 思路:
    随机操作数

    • 利用switch-case函数进入生成不同年级的操作数分支
    • 利用rand()函数生成随机操作数,返回操作数的值
      随机运算符
    • 利用rand()函数随机生成1~4的值
    • 根据switch-case进入不同年级分支
    • 进入后,再利用switch-case,根据随机生成的1~4选择运算符,返回运算符
      生成算式
    • 先判断是否是减法、除法
    • 如果是减法,判断操作数1是否大于操作数2,因为小朋友不会负数。若操作数1大于操作数2,则交换两个操作数
    • 如果是除法,判断是否能整除,若不能整除,再重新调用函数生成随机数,直到能够整除
    • 判断算式合理后,输出算式,同时将操作数、运算符传入判断正误的函数,得到正答率(正误判断函数中,定义全局变量总题数和全局变量正确答题数,每次均返回正答率,覆盖)
  • 代码:
    随机操作数:


    随机运算符:


    生成算式:

2.2.3 判断正误相关函数

double IsCorrect(int value1, int value2, char operate); //是否正确,计算正确率

  • 功能:判断用户输入的答案是否正确,若错误,则输出正确的答案
  • 思路:
    • 为避免调皮的小朋友输入字符而不是数字,采用字符型输入,再转化为数值
    • 若用户输入非法数值,输出错误提醒,让用户重新输入
    • 利用switch - case根据运算符进入不同的运算分支,得出正确答案
    • 将正确答案与用户的答案比对,若正确,则恭喜答对。并将正答数、总题数加1
    • 若答案不符,提示答错,输出正确答案。并将总题数加1
    • 因为总题数和正答数为全局变量,所以,计算正答率 rate,并返回。随着答题的进程,rate不断更新
  • 代码:


2.3.运行结果截图,测试用例

2.4.大作业中编程技巧总结

  • 睡眠函数的使用
#include <windows.h>      //头文件
Sleep(1000)               //1000为1000毫秒
  • 清屏函数的使用
#include <stdlib.h>       //头文件
system("cls");            //清屏
  • 将输入的字符型的数字,转化为整型的数字
while (1)
	{
		scanf("%c", &ch);

		if (ch >= '0' && ch <= '9')
		{
			ch = ch - '0';
			personNum = personNum * 10 + ch;
			flag = 1;
		}
		else
		{
			if (ch != '\n')
			{
				printf("输入有误,请输入数字\n");
				Sleep(1000);
				personNum = 0;
				flag = 0;
			}
		}

		if (ch == '\n' && flag == 1)
		{
			break;
		}
	}

  • 定义函数,利用switch-case,根据年级生成随机操作数、随机运算符