--函数--

今天我们来学习函数,首先我们需要了解的是如下8个方向:

  1. 函数的概念
  2. 库函数
  3. 自定义函数
  4. 函数参数
  5. 函数调用
  6. 函数的嵌套调用和链式访问
  7. 函数的声明和定义
  8. 函数递归

 

话不多说我们即刻开始学习

 

 

1. 函数的概念

  函数是指一段可以直接被另一段程序或代码引用的程序或代码。也叫做子程序、(OOP中)方法。

  一个较大的程序一般应分为若干个程序块,每一个模块用来实现一个特定的功能。所有的高级语言中都有子程序这个概念,用子程序实现模块的功能。在C语言中,子程序是由一个主函数和若干个函数构成的。由主函数调用其他函数,其他函数也可以互相调用。同一个函数可以被一个或多个函数调用任意多次。

2. 库函数

  库函数(Library function)是将函数封装入库,供用户使用的一种方式。方法是把一些常用到的函数编完放到一个文件里,供不同的人进行调用。调用的时候把它所在的文件名用#include<>加到里面就可以了。一般是放到lib文件里的。

2.1库函数的作用

  为了支持可移植性和提高程序的效率,所以 C 语言的基础库中提供了一系列类似的库函数,方便程序员
进行软件开发。
2.2常见库函数
  常见库函数可分为以下几种:
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 查找

2.2 自定义函数
  顾名思义即为自己设计定义的函数,能满足我们个人需求
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语言中的函数

4. 函数的参数
  函数的参数分为两种:

1.形参:在定义函数时括号内指定的参数(变量名),称之为形参

真实传给函数的参数,叫实参。
实参可以是:常量、变量、表达式、函数等

2.实参:在调用函数时括号内传入的值(变量值),称之为实参

形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中才实例化(分配内
存单
元),所以叫形式参数。形式参数当函数调用完成之后就自动销毁了。因此形式参数只在函数中有
效。

通过形参与实参在函数中位置来进行区分,两者区别如下:

一、主体不同

1、实参:在调用有参函数时,函数名后面括号中的参数为“实际参数”。

2、形参:不是实际存在变量,又称虚拟变量

二、目的不同

1、实参:可以是常量、变量或表达式, 无论实参是何种类型的量,在进行函数调用时,都必须具有确定的值, 以便把这些值传送给形参。

2、形参:定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数

三、特点不同

1、实参:在调用函数过程中,系统会把实参的值传递给被调用函数的形参。或者说,形参从实参得到一个值。该值在函数调用期间有效,可以参加该函数中的运算。

2、形参:形参的本质是一个名字,不占用内存空间

 5. 函数的调用

函数的调用分为2种:

5.1传值调用

  就是把一个变量的值传递给函数的形式参数;

5.2引用调用

  就是将变量的地址直接传入函数;

举例
实现函数判断year是不是润年
/*
思路:
  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;
	}
}
 
 
// 对以上代码进行简化
6. 函数的嵌套调用和链式访问
6.1嵌套调用
  嵌套调用就是某个函数调用另外一个函数(即函数嵌套允许在一个函数中调用另外一个函数)。

 C语言中不允许作嵌套的函数定义。因此各函数之间是平行的,不存在上一级函数和下一级函数的问题。但是C语言允许在一个函数的定义中出现对另一个函数的调用。这样就出现了函数的嵌套调用。即在被调函数中又调用其它函数。这与其它语言的子程序嵌套的情形是类似的。其关系可表示如图。

例如

int func_1()
{
return 0;
}

int func_2()
{
func_1();
return 1;
} 
为简单嵌套运用,相当于循环调用
6.2 链式访问
即把一个函数的返回值作为另外一个函数的参数。
#include<stdio.h>
#include<string.h>
int main()
{
	/*int len = 0;
	int len = strlen("abc");*/
	printf("%d", strlen("abc"));
	return 0;
}

strlen("abc")作为printf函数的函数参数

7. 函数的声明和定义
7.1函数声明

  “函数定义”是指对函数功能的确立,包括指定函数名,函数值类型、形参类型、函数体等,它是一个完整的、独立的函数单位。而“函数声明”的作用则是把函数的名字、函数类型以及形参类型、个数和顺序通知编译系统,以便在调用该函数时系统按此进行对照检查(例如函数名是否正确,实参与形参的类型和个数是否一致)。

在书写形式上,函数声明可以把函数头部复制过来,在后面加一个分号;而且在参数表中可以只写各个参数的类型名,而不必写参数名。

7.2函数定义
函数的定义是指函数的具体实现,交待函数的功能实现。
test.h文件
放置函数的声明
#ifndef __TEST_H__
#define __TEST_H__
// 函数的声明
int Add ( int x , int y );
#endif //__TEST_H__

test.c文件
#include "test.h"
// 函数 Add 的实现
int Add ( int x , int y )
{
return x + y ;
}

接下来则到了最重要的函数递归环节!!!

 7. 函数递归

7.1什么是递归
  程序调用自身的编程技巧称为递归( recursion)。递归作为一种 算法程序设计语言中广泛应用。 一个过程或 函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的 语句来定义对象的 无限集合。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
  上面也许很啰嗦,但总结下来只有五个字: 把大事化小
7.2递归限制条件
1.存在限制条件,当满足这个限制条件的时候,递归便不再继续。
2.每次递归调用之后越来越接近这个限制条件

练习

接受一个整型值(无符号),按照顺序打印它的每一位。
例如:
输入: 1234 ,输出 1 2 3 4.
#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;
}

今天的函数知识就到此结束了,希望大家都能有所收获!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值