1、函数的定义:
函数分为库函数和自定义函数
库函数:由C语言提供定义,编程时直接调用即可
如:scanf( )、printf( )
自定义函数:需要用户自己定义的函数
如:cylinder( )、fact( )
函数最常见的用途:实现一个计算,并可得到一个明确的计算结果
2、函数定义的一般类型:
函数类型 函数名(形式参数表)//函数首部
{
函数实现过程 //函数体
}
解释:
(1)函数类型:函数返回结果的类型,需与return语句中表达式的类型一致
如:int double……
(2)函数名:函数整体的称谓,需用一个合法的标识符来表示
如:cylinder fact
(3)形式参数表(形参表):给出函数计算所要用到的相关已知条件,其格式为:
类型1 形参1,类型2 形参2,类型3 形参3……
如:(int a,int b)
函数首部:double cylinder(double r,double h)
!!形参的值由主调函数给出!!
3、函数的调用:
调用标准库函数:只需要在程序的最前面用#include命令包含对应的头文件
调用自定义函数:程序中必须有与调用函数相对应的函数定义
函数被调用时,主函数停止执行,函数执行完返回主函数后,主函数才继续运行
先写一段代码来进行分析:
从中得到的启示:
(1)头文件中的函数定义要加分号,函数实现过程前的首部不用加分号!!唯一的区别!!
(2)库函数主体中定义的量要写入自定义函数中,其值也被赋予到了自定义函数中
(3)需要有返回变量来返回一个数值
2、函数调用的形式:
函数调用的一般形式:
函数名(实际参数表)
有两种形式:
1)赋值语句:volume = cylinder(radius,height);
2)输出时调用函数的实参:printf("%f",cylinder(radius,height));
3、参数传递:
函数定义时:
形参:位于其首部的参数;
如:double cylinder(double r,double h) 形参:r,h
实参:位于主调函数的参数;
如:volume = cylinder(radius,height); 实参:radius,height
函数调用时,实参的值会被赋给形参;
形参必须是变量,而实参可以是常量,变量或表达式
形参和实参可以同名,也可以不同名
4、函数结果返回:
返回形式如下:
return 表达式;
return的作用:
1)结束函数的运行
2)将计算结果返回主调函数
!!!return只能返回一个值!!!
5、函数原型声明:
函数应先定义后调用,一般格式为:
函数类型 函数名(参数表);
但函数首部不是语句,不能加分号!!!
//上分下不分
例2:
计算五边形的面积。将一个五边形分割成3个三角形,
输入这些三角形的7条边长,计算该五边形的面积。
要求定义和调用函数area(x,y,z)计算边长为x,y,z的三角形的面积
一些启示:
!!!主函数定义的变量名不能与自定义函数名称一致!!!
!!!自定义变量的类型一定要与自定义函数自定义变量的类型保持一致!!!
自定义函数的优点:
1)程序结构清晰,逻辑关系明确,程序可读性强;
2)解决相同或相似问题时不用重复编写代码,可通过调用函数来解决,减少代码量;
3)利用函数实现模块化编程,各模块功能相对独立,利用“各个击破”降低调试难度;
例4:!!!
使用函数求最大公约数。定义函数gcd(int m,int n),计算m和n的最大公约数。
//辗转相除法(欧几里得算法)
例5:!!!
使用函数判断素数。定义函数prime(m)判断m是否为素数,当m是素数时返回1,
否则返回0.素数就是只能被1和自己本身整除的数,1不是素数,2是素数。
6、不返回结果的函数:
返回结果的函数:起计算/判断作用,最终有一个函数结果返回
但在很多程序设计中,调用函数不是为了得到某个运算结果,而是要让它返回某些作用
不返回结果的函数定义:
void 函数名(形参表)//函数首部
{
函数实现过程 //函数体
}
此函数类型为void 函数中无return 其作用通常以屏幕输出等方式体现
!!!void不能省略,否则函数类型默认定义为int!!!
省略了return语句并不表示函数不能返回,当所有语句执行完毕后,
即遇到大括号时,函数自动返回主调函数。
!!!由于函数没有返回结果,所以函数调用不能出现在表达式中,通常以独立的调用语句方式呈现!!!
如:pyramid(n);
不返回值的自定义函数与返回值的自定义函数的区别:
唯一区别:函数类型为void!!!
例6:!!!
数字金字塔。输入一个正整数n,输出n行数字金字塔。
补充练习:
空心数字金字塔。本题要求实现一个函数,输入一个正整数n(1<=n<=9),输出n行的空心的数字金字塔。
要求定义和调用函数hollow_pyramid(n)打印出n行的空心的数字金字塔。
【左方空格】第一行4个,第二行3个,第三行2个,第四行1个
【中部空格】第一行无,第二行1个,第三行3个,第四行5个
7、局部变量与全局变量:
1)局部变量:
定义在函数的内部,它们的有效使用范围被局限于所在的函数内,
主调函数只有通过参数传递,才能把实参数据传递给函数使用,同样,行参的改变也不会影响实参变量。
优点:使用范围的有效,最大程度确保了各函数之间的独立性,避免函数之间相互干扰。
局部变量一般定义在函数或复合语句的开始处,不能定义在中间位置。
2)全局变量:
可以实现不同函数之间的数据交换。当一些变量需要被多个函数共同使用时,参数传递虽然是一个办法,
但需要通过函数调用才能实现,并且函数只能返回一个结果,使程序设计受到限制。
全局变量是定义在函数外而不属于任何函数的地方,作用范围是从定义开始到程序所在的文件结束,
对所有函数起作用。
例7:!!!
复数的运算。计算2个复数之和与之积,用函数实现2个复数之和与之积。运用全局变量。
调用的函数名称分别为:void complex_add(real1,imag1,real2,imag2) void complex_prod(real1,imag1,real2,imag2)
从中得到的启发:
定义全局变量时无形参表!!!
例8:
用函数进行财务现金记账。先输入类型(1收入,2支出,0结束),再输入操作金额,计算现金剩余额,经多次操作直到输入
操作类型为0时结束。要求定义并调用函数,其中现金收入与现金支出分别用不同函数实现。设变量cash保存现金余额值,
由于它被主函数、现金收入与现金支出函数共用,任意使用场合其意义都是明确和唯一的,因此定义其为全局变量。
定义和调用的函数分别为:income(number) expend(number) (无返回值函数)
8、变量生存周期和静态局部变量:
1)变量生存周期:变量从定义开始分配存储单元,到运行结束存储单元被回收,整个过程被称为变量生存周期。
自动变量定义形式是:
auto 类型名 变量名;
如:auto int x,y;
定义自动变量时,auto可以省略,其形式与普通变量完全相同。
变量的作用范围和生存周期不一样,要区分。
2)静态变量:
即静态局部变量。存放于静态存储区,不会像普通局部变量一样因为函数的调用结束而被系统回收,其生存周期会持续到程序结束。
一旦含有静态局部变量的函数被再次调用,则静态局部变量会被重新激活,上一次函数调用后的值仍然保存着,可供本次调用继续使用。
静态变量定义格式:
static 类型名 变量表
如:static double f = 1;
3)变量存储的内存分布:
静态存储区:全局变量,静态局部变量——相对稳定,管理较简单。
动态存储区:函数变量区,有各自的内存单元。
例9:
输入正整数n,输出1!-n!的值。要求定义并调用静态变量的函数fact_s(n)计算n!
从中得到的的启发:
静态局部变量一般为赋值表达式中的被赋值量!!!