导图社区 C语言模块化程序设计
C语言模块化程序设计:函数的定义,分类以及标准案例,包含了模块化程序设计、函数的定义及分类、函数的嵌套调用等内容。
编辑于2021-07-29 21:39:38"重构人生的12条黄金法则:从拒绝平庸到活出独特自我首先打破认知枷锁,用‘反愿景’明确人生底线绝对自由等于混乱,平庸是最昂贵的代价接着用高标准重塑身份,让卓越成为习惯能力提升要聚焦实战,以生活为项目炼就深度通才每日推进关键任务,用持续创造撬动自由保持创业心态,把不确定性当跳板,用自我实验突破极限记住:所有努力只为活出不可复制的生命剧本,包括接纳过程中的重大失误。
在职场沟通场景中,日报的本质是「工作价值的结构化呈现工具」。 许多人之所以会陷入写作困境,核心矛盾并非表达能力不足,而是日常工作缺乏目标导向的思维框架与成果沉淀的行为模式。 这里我将尝试以麦肯锡式思维逻辑为底层框架,拆解从工作规划到日报输出的全流程方法论,帮助职场人建立「思考有模型、执行有标准、呈现有效率」的工作体系。
C 类的封装方法:类的定义,类的构造函数,成员函数,重载构造函数,析构函数,静态成员等详细案例解析和理论罗列。
社区模板帮助中心,点此进入>>
"重构人生的12条黄金法则:从拒绝平庸到活出独特自我首先打破认知枷锁,用‘反愿景’明确人生底线绝对自由等于混乱,平庸是最昂贵的代价接着用高标准重塑身份,让卓越成为习惯能力提升要聚焦实战,以生活为项目炼就深度通才每日推进关键任务,用持续创造撬动自由保持创业心态,把不确定性当跳板,用自我实验突破极限记住:所有努力只为活出不可复制的生命剧本,包括接纳过程中的重大失误。
在职场沟通场景中,日报的本质是「工作价值的结构化呈现工具」。 许多人之所以会陷入写作困境,核心矛盾并非表达能力不足,而是日常工作缺乏目标导向的思维框架与成果沉淀的行为模式。 这里我将尝试以麦肯锡式思维逻辑为底层框架,拆解从工作规划到日报输出的全流程方法论,帮助职场人建立「思考有模型、执行有标准、呈现有效率」的工作体系。
C 类的封装方法:类的定义,类的构造函数,成员函数,重载构造函数,析构函数,静态成员等详细案例解析和理论罗列。
C语言模块化程序设计
模块化程序设计
由来
一个较为复杂的程序系统往往需要若干个子系统
C 语言的子系统具体体现就是函数,通常将相对独立经常使用的功能抽象为函数。
有利于代码重用,可以提高开发效率,也便于分工合作以及修改维护。
举例
#include<stdio.h> #include<string.h> int main() { void printstar(); /*声明 printstar 函数*/ void print_message(); /*声明 print_message 函数*/ printstar(); /*调用 printstar 函数*/ print_message(); /*调用 print_message 函数*/ printstar(); /*调用 printstar 函数*/ return 0; } void printstar() /*定义 printstar 函数*/ { printf("**************\n"); } void print_message() /*定义 print_message 函数*/ { printf("how do you do!\n"); }
************** how do you do! **************
printstar 和 print_message 都是用户自定义的函数名,分别用来输出一排 “*” 号和一行文字信息。在定义这两个函数时指定函数的类型为 void,表示函数无类型,即无函数值,也就是说,执行这两个函数不会返回任何值到 main 函数。
在程序中,定义 printstar 和 print_message 函数的位置是在 main 函数后面,在这种情况下,应该在 main 函数之前或 main 函数中的开头部分,对以上两个函数进行“声明”。不声明也行,如把自定义的函数放到前面。
#include<stdio.h> #include<string.h> void printstar() /*定义 printstar 函数*/ { printf("**************\n"); } void print_message() /*定义 print_message 函数*/ { printf("how do you do!\n"); } int main() { // void printstar(); /*声明 printstar 函数*/ // void print_message(); /*声明 print_message 函数*/ printstar(); /*调用 printstar 函数*/ print_message(); /*调用 print_message 函数*/ printstar(); /*调用 printstar 函数*/ return 0; }
函数声明的作用是把有关函数的信息(函数名、函数类型、函数参数的个数与类型)通知编译系统,以便于在编译系统对程序进行编译时,在进行到 main 函数调用 printstar 和 print_message 时知道他们是函数而不是变量或其他对象。
函数的定义及分类
C 语言要求,在程序中用到的所有函数,必须“先定义,后使用”。
必须先按规范对它进行定义,指定他的名字、函数返回类型、函数实现的功能以及参数的个数和类型
定义无参函数
类型名 函数名(){ 函数体 }
类型名表示的是返回值的类型
void printstar (){ }
函数没有返回值所以定义为 void。
定义有参函数
类型名 函数名(形式参数列表){ 函数体 }
示例:求两个数的最大值
#include<stdio.h> int main() { int max(int x, int y); int a = 10; int b =20; int c; c = max(a, b); /*a, b是实参的值,调用max函数,传递a,b的值给max的形式参数*/ printf("c=%d\n", c); return 0; } int max(int x, int y) { int z; z = x > y ? x : y; return z; }
在上述函数调用过程中,主调函数和被调函数之间存在数据传递的关系。在定义函数的时候函数名后面括号中的变量名称为“形式参数”(简称“形参”)(上例中为 x 和 y),在调用语句 c=max(a,b); 中,a 和 b 称为“实际参数”(简称“实参”)。
调用过程
在定义函数中指定的形参,在未出现函数调用时,他们并不占内存中的存储单元。
在发生函数调用时,函数 max 的形参被临时分配内存单元;
将实参对应的值传递给形参。
在执行 max 函数期间,由于形参已经有值,就可以利用形参进行有关运算了
调用结束,形参单元被释放。注意:实参单元仍保持原值和存储单元,自始至终未发生变化。形参会临时占用内存存储单元,但是实参和形参在内存中占用的存储单元是不同的。
函数的分类
用户使用角度分类
库函数
用户自定义函数
函数的形式角度分类
无参函数
有参函数
函数的嵌套调用
可以嵌套调用,不能嵌套定义
C 语言的函数定义是互相平行、独立的,也就是说,在定义函数时,一个函数内不能定义另一个函数,也就是不能嵌套定义,但是可以嵌套调用函数,也就是说,在调用一个函数的过程中,又可以调用另一个函数。
示例1
执行 main 函数的开头部分; 遇到函数调用语句,调用 a 函数,流程转去 a 函数; 执行 a 函数的开头部分; 遇到函数调用语句,调用函数 b,流程转去函数 b; 执行 b 完成,返回 a 函数中调用 b 函数的位置继续执行 a 函数尚未执行的部分。直到 a 函数结束; 返回 main 函数中调用 a 函数的位置,继续执行剩余的 main 函数部分。
示例2
输入四个整数,找出其中最大的整数。
解题思路
本题目我们就是使用函数嵌套的方法来处理。 在 main 函数中调用 max4 函数,max4 函数的作用是找出 4 个数中的最大值。在 max4 中调用 max2 函数,max2 是用来找出两个数中的最大值,max4 多次调用 max2 函数来达到找出 4 个数中最大值的目的。
代码实现
#include<stdio.h> int main() { int max4(int a, int b, int c, int d); int a; int b; int c; int d; int max; printf("please enter 4 integer number:"); scanf("%d%d%d%d", &a, &b, &c,&d); max = max4(a, b, c, d); printf("max=%d\n", max); return 0; } int max4(int a, int b, int c, int d) { int max2(int a, int b); int m; m = max2(a, b); m = max2(m, c); m = max2(m, d); return m; } int max2(int a, int b) { if(a > b) { return a; } else { return b; } }
函数的递归调用
在调用一个函数的过程中又出现直接或间接的调用该函数本身,称为函数的递归调用。
递归函数的两个要素为递归表达式和递归出口。
示例
用递归的方法求 n 的阶乘。
解题思路
n!=1*2*3*4...*(n-1)*n。采用递归的公式可表示为:
代码实现
#include<stdio.h> int main() { int fac(int n); int n; int y; printf("Please enter an integer number:"); scanf("%d", &n); if(n < 0) { printf("data error!"); } else { y = fac(n); printf("%d! = %d\n", n, y); } return 0; } int fac(int n) { int f; if(n == 0 || n == 1) { f = 1; } else { f = fac(n-1)*n; } return f; }
数组与函数
数组元素作为函数实参 【值传递】
数组元素可以作为函数实参,不能作为函数形参。因为形参是在函数被调用时临时分配的存储单元,不可能作为一个数组元素单独分配存储单元(数组是一个整体,在内存中占连续的一段存储单元)。在用数组元素作为函数实参时,把实参的值传给形参,是“值传递”的方式。
示例
输入 10 个数,要求输出其中值最大的元素和该数是第几个数。
解题思路
可以定义一个长度为 10 的数组。设计一个函数 max,用来求两个数中的大者。在主函数中定义一个变量 m,m 的初值为 a[0],每次调用 max 函数后的返回值存放在 m 中。用打擂台算法,将数组元素 a[1] 到 a[9] 与 m 比较,最后的到的 m 就是最大值。
代码实现
#include<stdio.h> int main() { int max(int x, int y); int a[10]; int m; int n; int i; printf("Please enter 10 integer number:"); for(i = 0; i < 10; i++) { scanf("%d", &a[i]); } printf("\n"); for(i =1, m = a[0], n =0; i < 10; i++) { if(max(m, a[i]) > m) { m = a[i]; n = i; } } printf("The largest number is %d\n it is the %dth number \n", m, n+1); return 0; } int max(int x, int y) { return (x > y ? x : y); }
数组名作为函数参数 【地址传递】
除了可以用数组元素作为函数的参数外,还可以用数组名做函数参数(包括实参和形参)。应当注意的是:用数组元素作为实参时,向形参变量传递的是数组所对应数组元素的值,而用数组名做函数实参时,向形参(数组名或指针变量)传递的是数组首元素的地址
示例
有一个一维数组 score,内放 10 个学生成绩,求平均成绩。
解题思路
用一个函数 average 来求平均成绩,不用数组元素作为函数实参,而是用数组名作为函数的实参,形参也用数组名。在 average 函数中引用各数组的元素,求平均成绩并返回 main 函数。
代码实现
#include<stdio.h> int main() { float average(float array[10]); float scores[10]; float aver; int i; printf("please enter 10 scores:"); for(i = 0; i < 10; i++) { scanf("%f", &scores[i]); } printf("\n"); aver = average(scores); printf("average score is %5.2f\n", aver); return 0; } float average(float array[10]) { int i; float aver; float sum = 0; for(i = 0; i < 10; i++) { sum = sum + array[i]; } aver = sum / 10; return aver; }
注意:用数组名作为函数参数, 应该在主调函数和被调用函数分 别定义数组,例如 array 是形参 的数组名,score 是实参数组名, 分别在其所在函数中定义。