首页 理论教育 C语言程序设计基础教程:认识函数,提高编程效率

C语言程序设计基础教程:认识函数,提高编程效率

时间:2023-10-27 理论教育 版权反馈
【摘要】:C语言中的函数相当于其他高级语言的子程序。可以说C 程序的全部工作都是由各式各样的函数完成的,所以也把C语言称为函数式语言。人们把这种函数称为库函数或标准库函数。每一种C语言编译系统都提供功能强大、内容丰富的库函数。作为C语言的程序设计者,应该好好利用库函数,以提高编程效率。例5.1任意输入三角形的三边的值给a、b 和c 变量,求三角形的面积。程序运行结果如图5.1所示。

C语言程序设计基础教程:认识函数,提高编程效率

任务描述

通过之前的学习,总结出用C语言编写程序本质上是编写函数。虽然在前面各章的程序中大都只有一个主函数main(),但实用程序往往由多个函数组成。函数是C语言程序的基本模块,通过对函数模块的调用实现特定的功能。C语言中的函数相当于其他高级语言的子程序。C语言不仅提供了极为丰富的库函数(提供了300 多个库函数),还允许用户定义自己的函数。用户可把自己的算法编成一个个相对独立的函数模块,然后用调用的方法来使用函数。可以说C 程序的全部工作都是由各式各样的函数完成的,所以也把C语言称为函数式语言。通过本项目的学习,希望能够学会自定义函数的编写并且掌握同一自定义函数的不同写法。

知识学习

(1)在程序设计世界中为什么要使用函数

功能比较多,规模比较大,把所有代码都写在main 函数中,就会使主函数变得庞杂、头绪不清,阅读和维护变得困难。有时程序中要多次实现某一功能,就需要多次重复编写实现此功能的程序代码,这使程序冗长,不精练。解决的方法是用模块化程序设计的思路。

计算机的函数主要是为了代码段重复利用,比如说你要用到一段同样的代码,使用这个代码的有很多地方,如果每用一次都要写一段这些代码的话很麻烦,把这些代码放到一个函数里面,以后要用到这些代码的时候就只需要调用这个函数名,有参数的话,同时传递不同的参数过去就可以了。

在设计一个较大的程序时,往往把它分为若干个程序模块,每一个模块包括一个或多个函数,每个函数实现一个特定的功能。C 程序可由一个主函数和若干个其他函数构成主函数调用其他函数,其他函数也可以互相调用同一个函数可以被一个或多个函数调用任意多次。

(2)函数的分类

在C语言中可从不同的角度对函数分类。

①从函数定义的角度看,函数可分为库函数和用户定义函数两种。

a.库函数:是由C 系统提供,用户无须定义,也不必在程序中作类型说明,只需在程序前包含有该函数原型的头文件即可在程序中直接调用。

标准库函数是由C 编译系统的函数库提供的,是系统的设计者事先将一些常用的独立的功能模块编写成通用函数,并将它们集中存放在系统的函数库中,供系统的使用者在设计应用程序时共享使用。人们把这种函数称为库函数或标准库函数。每一种C语言编译系统都提供功能强大、内容丰富的库函数。不同的C语言编译系统提供的库函数的数量和功能会有所不同,不过一些基本的函数是共同的。作为C语言的程序设计者,应该好好利用库函数,以提高编程效率

例5.1 任意输入三角形的三边的值给a、b 和c 变量,求三角形的面积。

程序运行结果如图5.1所示。

图5.1 程序运行结果

在调用标准库函数或库函数时应注意要使用编译预处理命令“#include",将包含该函数的声明信息的库文件名进行包含处理。例如#include<stdio.h>,该头文件包含了C语言所有的基本输入与输出函数,如scanf()、printf()等。例如#include <math.h >,该头文件中包含了sqrt()、fabs()、pow()、sin()等函数。再比如string.h、stdlib.h、windows.h、time.h 等都是常常用到的库函数,可参考附录。上述程序中的sqrt()函数就是标准库函数,它的功能是计算某数据对象的平方根并返回。

b.用户定义函数:由用户按需要编写的函数。对于用户自定义函数,不仅要在程序中定义函数本身,而且在主调函数模块中还必须对该被调函数进行类型说明,然后才能使用。

②C语言的函数兼有其他语言中的函数和过程两种功能,从这个角度看,又可把函数分为有返回值函数和无返回值函数两种。

a.有返回值函数:此类函数被调用执行完后将向调用处返回一个执行结果,称为函数返回值。如数学函数即属于此类函数。由用户定义的这种有返回函数值的函数,必须在函数定义和函数说明中明确返回值的类型。

b.无返回值函数:此类函数用于完成某项特定的处理任务,执行完成后不向调用处返回函数值。这类函数类似于其他语言的过程。由于函数无须返回值,用户在定义此类函数时可指定它的返回为“空类型”,空类型的说明符为“void”。

③从函数的形式上看,函数可以分为无参函数和有参函数。

a.无参函数:函数定义、函数说明及函数调用中均不带参数。主调函数和被调函数之间不进行参数传送。此类函数通常用来完成一组指定的功能,可以返回或不返回函数值。

b.有参函数:也称为带参函数。在函数定义及函数说明时都有参数,称为形式参数(简称为形参)。在函数调用时也必须给出参数,称为实际参数(简称为实参)。进行函数调用时,主调函数将实参的值传送给形参,供被调函数使用。注意,实参将值传递给形参是单向值传递。

(3)函数的参数

用户自定义函数是用户根据自己的需要编写的函数。可以分为3 种形式:无参数函数、有参数函数、空函数。

1)无参数函数

无参数函数在被调用时,主调函数无须传递任何数据给它,一般用来完成一定的操作。无参函数可以有返回值也可以无返回值。

无参数函数的定义形式:

其中,类型标识符和函数名称为函数首部。类型标识符指明了本函数返回值的类型,该类型标识符与前面介绍的各种说明符相同;函数名是由用户定义的标识符,函数名后有一个空括号,其中无参数,但括号不可少。

{}中的内容称为函数体。在函数体中,声明部分是对函数体内部所用到的变量或者数组等的说明。

在很多情况下都不要求无参函数有返回值,此时函数类型符可以写为void,也可不写。人们可以编写一个函数定义,例如输出类似游戏中的主菜单的自定义函数:

上述程序,只是借鉴main 函数的书写形式,将main 改为menu 作为主菜单函数名,其余格式保持不变。menu 函数是一个无参函数,当它被其他函数调用时,就会在运行界面上输出主菜单,并且可供用户可以进行选择。

例5.2 在main 函数中调用自定义menu 函数。

注意:由于1 ~7 后的输入、显示、查询、修改、删除、保存和读取等7 个功能还没有设计程序实现。所以以上程序暂时无法执行,在最后一项目中将会使用。

2)有参数函数

有参数函数

有参数函数的定义形式:

类型标识符函数名(形式参数列表)

有参函数比无参函数多了一个内容,即形式参数表列。在形参表中给出的参数称为形式参数,此类函数在被调用时,主调函数必须传递数据给这些函数的形式参数,同时在函数结束时返回结果供主调函数使用。它们可以是各种类型的变量,各参数之间用逗号间隔。在进行函数调用时,主调函数将赋予这些形式参数实际的值。形参既然是变量,必须在形参表中给出形参的类型说明。如下求任意2 个数值的最大值自定义函数:

此自定义函数首部表示该函数返回值是一个double 型的数据,其函数名是max,带2 个形参a 和b,且形参类型也是double 型。a 和b 变量的作用是接收从主调函数在调用时传递过来的数值。在{}中的函数体内部,当判断结束后将任意2 个数值的最大值由big 变量用于存放。函数最后利用return 函数实现将数据结果返回给主调函数,有返回值的函数中至少应该有一个return 语句。完整且可执行代码如下:

例5.3 任意输入2 个数值求最大值,要求将求最大值功能用自定义函数来实现。

程序运行结果如图5.2所示。

图5.2 程序运行结果

注意:有参函数,除了在函数定义的时候()内要指定形参类型、变量名等,还在调用函数的时候()内必须不能为空,需要书写实参。在实际使用的时候当执行到big=max(a,b);这行程序时,实际参数a 和b 将在调用max 函数时,将其值对位传递给自定义函数max 的形参a 和b 变量,当max 函数执行完求最大值之后,利用return 语句将最大值返回给主调函数中big 变量。最后输出最大值。

3)空函数

如果定义函数时只给出一对花括号{}而不给出其形式参数和函数体语句,则称该函数为“空函数”。如下的自定义函数:

空函数的作用:

①程序设计过程的需要。在设计模块时,对于一些细节问题或功能在以后需要时再加上。这样可在将来准备扩充的地方写上一个空函数,这样可使程序的结构清晰,可读性好,而且易于扩充。

②在C ++程序中,可以将基类中的虚函数定义为空函数,通过派生类去实例化,实现多态

(4)函数的参数分类

当自定义函数要完成某功能时,必须要已知数据才能完成其功能,这时就必须要有参数。函数的参数分为形参和实参两种。在调用有参函数时,主调函数和被调函数之间必须进行数据传递。在定义函数时函数名后圆括号中的变量名称为形式参数,简称形。在调用函数时函数名后圆括号中的参数称为实际参数,简称实参。主调函数把实参传给被调函数的形参,实现数据的传递。

形参出现在函数定义中,在整个函数体内都可以使用,离开该函数则不能使用。实参出现在主调函数中,进入被调函数后,实参变量也不能使用。形参和实参的功能是作数据传送。发生函数调用时,主调函数把实参的值传送给被调函数的形参,从而实现主调函数向被调函数的数据传送。

例如在例5.3 中:

①形式参数double max(double a,double b)在第2 行程序中,圆括弧内的a 和b 变量就是形式参数。

②实际参数big=max(a,b);在第15 行程序中,圆括弧内的a 和b 变量就是实际参数。

函数的形参和实参具有以下特点:

①形参变量只有在被调用时才分配内存单元,在调用结束时,立即释放所分配的内存单元。因此,形参只有在函数内部有效。函数调用结束返回主调函数后则不能再使用该形参变量。

②实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参.因此应预先用赋值、输入等办法使实参获得确定值。

③实参和形参在数量、数据类型、顺序上应尽量一致,否则可能会发生类型不匹配等错误

④函数调用中发生的数据传送是单向的,即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化。

说明:(www.xing528.com)

①在C语言中,当形参为简单变量时,实参与形参之间的数据传递是单向“值传递”,即将实参的值传给形参,而形参的值不能返回给实参。在内存中,实参与形参占用不同的存储单元

②实际上,在定义函数时,系统并没有给形参变量分配任何存储单元,但在调用函数时,系统会动态地给形参变量分配存储单元,并将对应的实参的值传给形参,调用结束后形参单元被释放,而实参占用的存储单元和值保持不变。

③在这种“值传递”情况下,在函数调用过程中,实参在把它的值传给形参后即完成它的使命,实参本身并不能把函数的操作结果带回来,此时一个函数只能通过函数名返回一个函数值。但是若实参是指针地址,则在函数内可以改变实参所指向或对应的存储单元的值(注意不是实参自身的值),从而达到带回函数操作结果的目的。

例5.4 任意输入2 个正整数,求这2 个数值之间所有正整数之和(包含本身)。要求将求和功能用自定义函数来实现,运行结果如图5.3所示。

图5.3 程序运行结果

说明:上述程序中定义了一个函数sum,该函数的功能是求解任意2 个正整数之间所有整数之和(包括本身)。在主函数中分别输入正整数给a 和b 并作为实参,在调用sum 函数的时候实参a 和b 对位传递给sum 函数的2 个形参x 和y(注意实参和形参可以同名,但是本质上算作不同变量,因为它们的作用域不同)。当在sum 函数中判断并计算出结果后,利用return语句将数据结果返回到main 函数中调用sum 函数处,并将返回值赋值给main 函数中变量s。最后程序输出结果。

(5)函数的返回值

通常情况下,人们都希望通过调用函数返回一个值。在C语言函数中,使用return 语句返回函数值。如果一个函数具有返回值,则这个函数体内必须含有至少一个return 语句,return后面的括号可以要也可以不要。如果一个函数没有返回值,则可以不要return 语句,也可以有return 语句,但return 后面不跟任何值。一个函数可以有不只一个return 语句,但只有先执行到的那个return 语句起作用。

return 语句的两种用法如下:

①return(返回值);

②return 返回值;

函数值的类型由定义函数时的类型标识符确定,若定义时不作类型说明,则默认为整型类型。如果函数值的定义类型与return 语句中表达式的值不一致,则以函数定义类型为准。

例5.4 任意输入2 个数值求最大值,要求将求最大值功能用自定义函数来实现。

①有返回值。

②无返回值。

注意:有返回值的函数中必须有return 语句,且函数名前必须有返回类型名。而无返回值的函数直接求得并输出结果,不需要返回值,函数名前必须有表示无返回值的void 关键字。有返回值的函数的优点是可以利用该函数的多次调用完成多个数据之间求最大值,可以减少代码的重复。无返回值的函数只是实现了2 个数值之间的求最大值并且输出,但该函数不能用于多个数据之间求最大值。

(6)函数的调用

函数调用的一般形式如下:

返回值类型函数名(实参列表);

①实参列表与定义函数时的形参列表应该一一对应, 即参数个数要相等, 参数类型要尽量一致或者赋值没有影响,参数顺序要相同。

②实参类型与形参类型不匹配时, 可能出现异常结果。和许多其他语言不同, C语言在实参和形参类型不一致时也尽力处理, C语言的“运行时错误”检查不多, 所以当类型不匹配时也不报告错误, 但是运行可能导致错误结果, 这就要求程序员自己认真检查确保消除类型匹配错误。

③实参可以是常量、变量或者表达式,但实参必须是有确定的值。

例5.5 当实参是常量、变量或者表达式时调用函数的实例,运行结果如图5.4所示。

图5.4 程序运行结果

说明:main 函数前后3 次调用sum 函数,将常量为实参1 和100,变量为实参a 和b,表达式为实参2 -1,101 -1 在各自调用sum 函数的时候将值传递给形参x 和y,计算出结果并返回值,在调用完函数之后输出结果。

在C语言中函数的调用形式一共分3 种:

①函数表达式:函数作为表达式中的一项出现在表达式中,以函数返回值参与表达式的运算。这种方式要求函数是有返回值的。例如下面程序中的:big=max(a,b);

big=max(big,c);

例5.6 任意输入3 个数值求最大值,要求利用2 个数值求最大值的自定义函数来实现。

程序运行结果如图5.5所示。

图5.5 程序运行结果

②函数语句:函数调用的一般形式加上分号即构成函数语句。这种方式一般要求函数是有无返回值的。例如下面程序中的:

max(a,b,c);

例5.7 任意输入3 个数值求最大值,将求最大值功能用自定义函数来实现,结果如图5.6所示。

图5.6 程序运行结果

③函数实参:函数作为另一个函数调用的实际参数出现。这种情况是把该函数的返回值作为实参进行传送,这种方式要求函数是有返回值的。例如下面程序中的:

图5.7 程序运行结果

(7)函数的声明

在一个函数中调用另外一个函数,被调用函数必须是已经存在的函数,可以是标准库函数或者是自定义函数。

当调用库函数时,应该在程序的开始处使用“#include”的预处理命令来完成对函数所属的头文件包含到主调函数中。例如:调用printf 和scanf 函数时,在程序开始处使用#include<stdio.h>。这种方式是直接到安装路径下的include 文件夹中寻找所需的头文件。

当库函数或者调用自定义函数时,该库函数不在原本安装路径下的include 文件夹中或者自定义函数和源文件不在一个文件夹中,此刻使用#incude"stdio.h"的写法。这种方式是先到源文件所在文件夹中寻找所需头文件,如果存在即刻包含到程序中;如果不存在再到安装路径下的include 文件夹中寻找所需的头文件。

当调用自定义函数时,且该函数和main 函数在同一个文件中时,则需要根据主调函数和被调函数在文件中的相对位置,决定是否要做出对被调函数的声明。

①如果被调函数在主调函数之前,不需做函数声明。本章到此之前的自定义函数都属于该情况。

②如果被调函数在主调函数之后,就必须要做函数声明。函数声明形式如下:

函数声明时可以不写参数名,因为编译系统只检查函数类型和参数类型,不检查参数名。也可以书写为:

double max(double ,double );

例5.9 任意输入3 个数值求最大值,要求自定义函数书写在主函数之下,对自定义函数使用函数声明,结果如图5.8所示。

图5.8 程序运行结果

任务总结

根据本任务的学习,自定义函数的书写主要目的是模块化设计思想。这样书写可以提高代码的重复使用率,减少源程序的代码。通过本任务的学习大家可以发现同一个功能的自定义函数可以书写为多种形式,并不是一成不变。希望大家通过课后练习掌握自定义函数不同的书写形式,达到灵活编程的目的。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈