270 likes | 418 Views
函数. 目标. 描述 C 语言中的函数 掌握 C 语言中常见的内置函数 熟练掌握自定义函数的定义和调用 理解函数原型和函数的返回值 熟悉带参函数的调用 熟练使用数组作为函数参数 理解两种参数传递的方式:传值、引用. 系统函数. 函数的特点. 可以在同一个程序或其他程序中多次重复使用. 函数的特点. 可以在同一个程序或其他程序中多次重复使用 像一个黑匣子一样,我们不需要知道它的细节,只是给他数(参数)或不给他,从它那里取得一个结果(返回值),或者完成一个功能(没有返回值)。 就好象一个数学公式那样。. 系统函数的组成.
E N D
目标 • 描述 C 语言中的函数 • 掌握 C 语言中常见的内置函数 • 熟练掌握自定义函数的定义和调用 • 理解函数原型和函数的返回值 • 熟悉带参函数的调用 • 熟练使用数组作为函数参数 • 理解两种参数传递的方式:传值、引用
函数的特点 可以在同一个程序或其他程序中多次重复使用
函数的特点 • 可以在同一个程序或其他程序中多次重复使用 • 像一个黑匣子一样,我们不需要知道它的细节,只是给他数(参数)或不给他,从它那里取得一个结果(返回值),或者完成一个功能(没有返回值)。 • 就好象一个数学公式那样。
系统函数的组成 printf(“%d”,aa); 有两个参数,没有返回值,可以直接使用 ch=getchar(); 没有参数,返回值的类型为字符型,使用时要放在赋值语句的右边,将函数的返回值赋给一个同类型的变量。 putchar(ch); 一个参数,没有返回值 i=random(n); 一个参数,返回值的类型为数值型,
使用系统函数小结 • 使用#include将标准函数的头文件包含到我们的程序中。 • 要知道函数的参数有几个,都是什么类型的。 • 使用函数时,参数的个数和类型要一一对应。 • 要知道函数有没有返回值,返回值的类型是什么。 • 使用函数时,根据返回值的类型,使用方式不同。
举一个函数的简单例子 # include <stdio.h> void printstar()/*定义printstar函数,用于输出一行星号*/ { printf("* * * * * * * * * * * * * * * *\n"); } void print_message() /*定义print_message函数,输出文字信息*/ { printf("How do you do!\n"); } void main() { printstar();/*调用printstar函数*/ print_message();/*调用print_message函数*/ printstar();/*调用printstar函数*/ }
为什么使用自定义函数 void main() { :::::: x=x*x*x; y=y*y*y; z=z*z*z; ans1=x+y+z; a=a*a*a; b=b*b*b; c=c*c*c; ans2=a+b+c; ::::: } void main() { :::::: ans1=cube(x,y,z); ans2=cube(a,b,c); ::::: } int cube(int a,b,c) { int ans; ans=(a*a*a)+(b*b*b)+(c*c*c); return ans; } 重复多次的同一计算类型 ans 函数 主程序 函数可以把相对独立的某个功能抽象出来,使之成为程序中的一个独立实体。可以在同一个程序或其他程序中多次重复使用
函数机制的优点 • 使程序变得更简短而清晰 • 有利于程序维护 • 可以提高程序开发的效率 • 提高了代码的重用性
函数定义(函数功能的具体实现) double max(double x, double y) { if(x>y) return x; else return y; } 该函数名为max,它有两个double类型的参数,返回值为double类型。在函数体内有三条语句实现了求两个数中较大的数,并使用return语句将它返回。 函数的定义是独立于main函数的,要在main函数的外面。
函数调用 #include<stdio.h> void main() { float x,y,z; printf(“input x,y:”); scanf(“%f%f”,x,y); z=max(x,y); printf(“\nmax of x,y is:%f”,z); } double max(double x, double y) { if(x>y) return x; else return y; } • 通过在程序中使用函数名称,可以执行函数中包含的语句,这称为调用函数
形参和实参 • 函数参数用于函数之间的信息传递。 • 形式参数:定义函数时的参数,简称形参。 • 实际参数:调用函数时的参数,简称实参。 • 形参和实参名称可以相同也可以不同,但是他们占用的是不同的内存单元。 • 形参是变量。 • 实参可以是变量(必须已经赋值),也可以是常量。 • 调用时,将实参的值传给形参变量。 • 形参和实参的个数和数据类型要相同。 • 形参和实参有多个时,用逗号分隔。
函数形参和实参 void main ( ) { int x,y,z; . . . z=max ( x,y ); } max( int x, int y ) { . . . . . . } 实际参数 函数调用 函数定义 形式参数
传值调用 传值调用 void main() { int a = 0; //初始化a值为0 func(a); //调用函数func printf("%d",a); //输出a的结果 } //定义函数func void func(int a) { a = 10; //让参数a等于10 } 0 将会输出什么
调用函数 num1 num2 34 56 num1 var1 num2 var2 FF23 FF05 将变量num1的 值赋给形参val1 将变量num2的 值赋给形参val2 val1 调用后修改为35 调用后修改为57 val2 56 34 FFEA FF45 被调用函数 请输入两个数: _ 34 56 传值调用示例 递增前的值是34 和56 #include <stdio.h> void increment(int,int); void main() { int num1,num2; printf("\n 请输入两个数: "); scanf(" %d %d",&num1,&num2); printf("\n 递增前的值是 %d 和 %d\n", num1, num2); increment(num1,num2); printf("\n 递增后的值是 %d 和 %d\n", num1, num2); } void increment(int val1,int val2) { val1++; val2++; printf("\n 子函数中值 %d 和 %d\n", val1, val2); } 子函数中的值是35 和 57 递增后的值是34 和 56 34 56 34 56 57 35
函数返回值 • C语言中的 return语句用于向调用函数返回值,语法如下: return (<表达式>); • C语言中的函数至多可以返回一个值,不能返回多个值; • 返回值的数据类型必须与函数原型中返回值的数据类型匹配; • 当遇到 return语句时,函数执行将终止。程序控制流将立即返回调用函数; • 如果一个函数没有返回值,函数的类型为void。函数中则不用return语句。 • 调用函数时,如果有返回值,则以赋值语句的形式来调用, • 变量=函数名(实参列表); • 注:变量类型要同函数类型一致。 • 否则可以下面方法调用: • 函数名(实参列表); int divisibleCheck(int num) { if (num % 5 == 0) return 1; else return 0; }
#include <stdio.h> float count (int, int); void main() { . . . . . . } float count(int x,int y) { . . . } 对被调函数的声明和函数原型 • 遵循“先定义,后使用”的原则,被调函数必须出现在主调函数的前面。 • 如果被调函数出现在主调函数的后面,则应该在程序开始对被调用的函数作声明(给出原型说明)。 • 函数原型说明在形式上与函数头部类似,最后加一个分号。原型说明中参数表里的参数名可以不写(只写参数类型)。
函数嵌套调用和递归调用 void palindrome() { :::::::: reverse(); :::::::: } #include<stdio.h> void main() { ::::::::: palindrome(); :::::::: :::::::: } voidreverse() { :::::::::: :::::::::: } 从一个函数调用另一个函数称为函数的嵌套调用 在一个函数体内调用自身称为函数的递归调用
学生练习 • 自行完成题目: • 输入一个年份,判断是否是闰年,判断闰年用函数实现。 提示框架: main() { int year; int i; i=isrunnian(year); if (i==1) 输出是; else 输出不是 }
学生上机练习 • 写一个函数,求字符串中小写字母的个数,主函数中输入字符串,输出个数。
数组作为函数参数 • 在用数组作实参时,以传址方式调用函数,也就是说把实参数组的首地址赋给形参 • 实际上形参数组和实参数组为同一数组,共同拥有一段内存空间
数组作为参数示例1 #include <stdio.h> void invert(float[]); void main() { float aa[5]={12,13,14,15,16}; printf(“\n 原数组元素为:\n",N); for(i=0;i<5;i++) printf(“%6.2f",aa[i]); invert(aa); printf(“\n 倒置后的数组为:\n"); for(i=0;i<5;i++) printf("%6.2f ",aa[i]); printf("\n"); } void invert(float aa[5]) { int i,j; float temp; i=0,j=4; for(;i<j;i++,j--) { temp=aa[i]; aa[i]=aa[j]; aa[j]=temp; } } 问题描述: 通过函数实现将一维数组的各个元素倒置存放。
总结 2-1 • 函数是程序中的一个相对独立的单元或模块,程序在需要时可以任意多次地调用函数来完成特定功能 • 使用函数带来的好处: 程序更清晰、易维护、分模块方便设计与开发、提高代码的重用性 • C语言提供了极为丰富的内置函数,这些内置函数分门别类地放在不同的头文件中,要使用这些内置函数,只要在程序前包含相应的头文件即可
总结 2-2 • 自定义函数是用户在程序中根据需要而编写的函数 • 函数的结构包括:返回值类型、函数名、参数列表、函数体 • 函数原型说明以便向编译器指出该函数使用什么样的格式和语法 • 函数调用时程序控制流将转向被调函数,被调函数执行结束时,控制流返回主调函数 • return 语句用于向调用函数返回值
总结 2-1 • 根据变量的作用域可以将变量划分为:局部变量和全局变量 • 根据变量的存储类型(决定生存期)将变量划分为: 自动变量、寄存器变量、静态变量、外部变量 • 静态局部变量的生存期为整个源程序,但其作用域为定义该变量的函数 • 静态全局变量的生存期为整个源程序,其作用域为定义该变量的源文件
总结 2-2 • 采用传值调用方式时,在被调用函数中改变形参的值,只是改变其副本值,而不会影响调用函数中实参值 • 采用引用调用方式时,传递的是变量的地址值,这样在被调函数中,对形参的操作实际上操作的是实参本身 • 数组作为函数传递时,实际采用引用调用方式