C语言程序设计-第5章全解
华中科技大学计算机学院C语言课程组 C语言与程序设计The C Programming Language 第5章 函数与程序结构 结构化编程和C程序的一般结构 函数的机制,包括函数定义、函数声明、函数调用、变量的存储类型、参数数目可变的函数等。 5.1 C程序的一般结构 5.1.1 结构化程序设计 结构化编程是一种解决问题的策略,它包括如下2条编程标准: (1) 程序中的控制流应该尽可能简单。 (2) 应该自顶向下地设计程序结构。 自顶向下设计也称为逐步细化,即把一个问题按功能分解为若干子问题,如果子问题还较复杂,可将其继续分解,直到分解成为容易求解的子问题为止。分解而来的每个子问题被称为模块,C中提供的函数机制完成每个模块的编程任务,即用函数编写由分解而来的子问题的代码。 5.1.2 蒙特卡罗模拟:猜数游戏 模拟算法是最基本的算法,例如,编程实现抛硬币、掷骰子和玩牌等现实世界中的随机事件要用模拟算法。在程序设计中,可使用随机数函数来模拟现实中不可预测情况,这称为蒙特卡罗模拟。随机数以其不确定性和偶然性等特点在很多地方都有具体的用处。比如,软件测试中,用于产生具有普遍意义的测试数据,在加密系统中产生密钥,在网络中生成验证码等。 在C语言中,用rand函数生成随机数,该函数称为随机数发生器,该发生器从称为种子(一个无符号整型数)的初始值开始用确定的算法产生随机数。显然,通过种子产生第一个随机数后,后续的随机序列也就是确定的了,这种依靠计算机内部算法产生的“随机”数称为伪随机数。由此可见,随机数的产生依赖于种子,为了使程序在反复运行时能产生不同的随机数,必须改变这个种子的值,这称为初始化随机数发生器,由函数srand来实现。 【例5.1】 编写一个猜数的游戏程序 在这个游戏中,计算机产生一个1到1000之间的随机数,并把该数作为要猜的数。玩游戏者输入所猜的数,如果猜得不正确,继续猜直到正确为止,同时计算游戏者猜数的次数。为了帮助游戏者一步一步得到正确答案,程序会不断地发出信息“Too high”或“Too low”。最后,程序向游戏者显示游戏结果。 自顶向下的分解问题: 既然是一个游戏程序,就应该允许玩家反复玩多次,直到不想玩为止。同时,将玩一次游戏的任务分解成以下两个子任务: (1)计算机产生一个1到1000的随机数供游戏者猜测; (2)游戏者猜数,直至猜对。 主程序结构 do { 计算机产生一个1到1000的随机数 游戏者猜数,直至猜对 继续玩吗 } while (继续); 自顶向下的分解子任务(1) ① 调用标准库函数rand产生一个随机数; ② 将这个随机数限制在1~1000之间。 利用函数,可以实现程序的模块化,把程序中常用的一些算法或操作编成通用的函数,以供随时调用,大大简化主函数的流程,使程序设计简单和直观,提高程序的易读性和可维护性。 把任务1设计成一个独立的函数,用函数GetNum(void) 来实现. 函数 int GetNum(void) /**************************************************************** 函数名称:GetNum 函数功能:产生一个1到MAX_NUMBER之间的随机数,供游戏者猜测。 函数参数:无 函数返回值:返回产生的随机数 ****************************************************************/ int GetNum(void) /* 注意:后面无分号 */ { /* 函数开始的标志 */ int x; printf("A magic number between 1 and %d has been chosen.\n", MAX_NUMBER); x=rand(); /* 调用标准库函数rand产生一个随机数 */ x= x % MAX_NUMBER + 1;/* 将这个随机数限制在1~MAX_NUMBER之间 */ return(x); /* 返回这个随机数给调用者,*/ } /* 函数结束的标志 */ 在函数的顶端用“/*……*/”格式包含的部分是函数头部注释,包括函数名称、函数功能、函数参数、函数返回值等内容,如有必要还可增加作者、创建日期、修改记录(备注)等相关项目。虽然函数头部注释在语法上不是必需的,但可以提高程序的质量和可维护性,在程序设计时要遵从这一编程规范。 GetNum是函数名,其后的vo