今天我们来学习函数,首先我们需要了解的是如下8个方向:
- 函数的概念
- 库函数
- 自定义函数
- 函数参数
- 函数调用
- 函数的嵌套调用和链式访问
- 函数的声明和定义
- 函数递归
话不多说我们即刻开始学习
函数是指一段可以直接被另一段程序或代码引用的程序或代码。也叫做子程序、(OOP中)方法。
一个较大的程序一般应分为若干个程序块,每一个模块用来实现一个特定的功能。所有的高级语言中都有子程序这个概念,用子程序实现模块的功能。在C语言中,子程序是由一个主函数和若干个函数构成的。由主函数调用其他函数,其他函数也可以互相调用。同一个函数可以被一个或多个函数调用任意多次。
库函数(Library function)是将函数封装入库,供用户使用的一种方式。方法是把一些常用到的函数编完放到一个文件里,供不同的人进行调用。调用的时候把它所在的文件名用#include<>加到里面就可以了。一般是放到lib文件里的。
2.1库函数的作用
IO函数 |
字符串操作函数 |
字符操作函数 |
内存操作函数 |
时间/日期函数 |
数学函数 |
其他库函数 |
strcat
char *strcat( char *strDestination, const char *strSource ); |
malloc
void *malloc( size_t size ); |
顺带一提的是使用库函数,必须包含#include对应的头文件。
2.3如何查找库函数
建议下载MSDN软件(MSDN(Microsoft Developer Network))
或者去www.cplusplus.com 查找
ret_type
fun_name
(
para1
,
*
)
{
statement
;
//
语句项
}
ret_type
返回类型
fun_name
函数名
para1
函数参数
|
让我们举个例子:
实现一个函数,判断一个数是不是素数。利用上面实现的函数打印100到200之间的素数。
/*
思路:
0. 函数原型设计
返回值:必须要有返回值,0表示不是素数,1表示是素数
1. 检测该数据是否为素数,方法参考前文。
*/
int is_prime(int n)
{
int i = 0;
for(i=2; i<=sqrt(n); i++)
{
if(0 == n%i)
{
return 0;
}
}
return 1;
}
库函数以及自定义函数组成我们c语言中的函数
1.形参:在定义函数时括号内指定的参数(变量名),称之为形参
2.实参:在调用函数时括号内传入的值(变量值),称之为实参
通过形参与实参在函数中位置来进行区分,两者区别如下:
一、主体不同
1、实参:在调用有参函数时,函数名后面括号中的参数为“实际参数”。
2、形参:不是实际存在变量,又称虚拟变量。
二、目的不同
1、实参:可以是常量、变量或表达式, 无论实参是何种类型的量,在进行函数调用时,都必须具有确定的值, 以便把这些值传送给形参。
2、形参:定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数。
三、特点不同
1、实参:在调用函数过程中,系统会把实参的值传递给被调用函数的形参。或者说,形参从实参得到一个值。该值在函数调用期间有效,可以参加该函数中的运算。
2、形参:形参的本质是一个名字,不占用内存空间。
5. 函数的调用
函数的调用分为2种:
5.1传值调用
就是把一个变量的值传递给函数的形式参数;
5.2引用调用
就是将变量的地址直接传入函数;
/*
思路:
0. 函数原型设计
返回值:必须要有返回值,返回结果为0说明不是闰年,为非0说明时闰年
参数:年份
1. 十年一闰百年不闰:即如果year能够被4整除,但是不能被100整除,则year是闰年
2. 每四百年再一闰:如果year能够被400整除,则year是闰年
具体实现:请参考以下代码
*/
int is_leap_year(int year)
{
if(((0 == year%4)&&(0!=year%100))||(0==year%400))
{
return 1;
}
else
{
return 0;
}
}
// 对以上代码进行简化
C语言中不允许作嵌套的函数定义。因此各函数之间是平行的,不存在上一级函数和下一级函数的问题。但是C语言允许在一个函数的定义中出现对另一个函数的调用。这样就出现了函数的嵌套调用。即在被调函数中又调用其它函数。这与其它语言的子程序嵌套的情形是类似的。其关系可表示如图。
例如
int func_1()
{
return 0;
}
int func_2()
{
func_1();
return 1;
}
#include<stdio.h>
#include<string.h>
int main()
{
/*int len = 0;
int len = strlen("abc");*/
printf("%d", strlen("abc"));
return 0;
}
把strlen("abc")作为printf函数的函数参数
“函数定义”是指对函数功能的确立,包括指定函数名,函数值类型、形参类型、函数体等,它是一个完整的、独立的函数单位。而“函数声明”的作用则是把函数的名字、函数类型以及形参类型、个数和顺序通知编译系统,以便在调用该函数时系统按此进行对照检查(例如函数名是否正确,实参与形参的类型和个数是否一致)。
在书写形式上,函数声明可以把函数头部复制过来,在后面加一个分号;而且在参数表中可以只写各个参数的类型名,而不必写参数名。
#ifndef __TEST_H__
#define __TEST_H__
//
函数的声明
int
Add
(
int
x
,
int
y
);
#endif
//__TEST_H__
|
#include "test.h"
//
函数
Add
的实现
int
Add
(
int
x
,
int
y
)
{
return
x
+
y
;
}
|
接下来则到了最重要的函数递归环节!!!
7. 函数递归
1.存在限制条件,当满足这个限制条件的时候,递归便不再继续。
2.每次递归调用之后越来越接近这个限制条件
|
练习
#include <stdio.h>
void
print
(
int
n
)
{
if
(
n
>
9
)
{
print
(
n
/
10
);
}
printf
(
"%d "
,
n
%
10
);
}
int
main
()
{
int
num
=
1234
;
print
(
num
);
return
0
;
}
|
运用递归则很好的实现此代码
7.2递归与迭代
常见与求阶乘以及第n个斐波那契数
这里我们选择求斐波那契数
int
count
=
0
;
//
全局变量
int
fib
(
int
n
)
{
if
(
n
==
3
)
count
++
;
if
(
n
<=
2
)
return
1
;
else
return
fib
(
n
-
1
)
+
fib
(
n
-
2
);
}
|
假如输出count是个超级大的值,我们可以
1.考虑将递归改为非递归
2.使用static对象替代nonstatic局部对象
以下是使用非递归的方法求斐波那契数
int fib(int n) { int result; int pre_result; int next_older_result; result = pre_result = 1; while (n > 2) { n -= 1; next_older_result = pre_result; pre_result = result; result = pre_result + next_older_result; } return result; } |
今天的函数知识就到此结束了,希望大家都能有所收获!