函数

c语言是模块化程序设计。
函数可以看成模块化程序设计的最小单位
c程序可以由一个或多个源程序文件组成,一个源程序文件又可以由多个函数组成。
main()是一个程序的入口
函数分为:
1,标准库函数:调用这些函数需要包含头文件.<stdio.h>,<math.h>.
2.自定义函数。

函数的定义:
返回值类型  函数名(  类型  形式参数1,类型 形式参数2,...)     <--函数头部
{
声明语句序列
可执行语句序列
}


在函数体内部定义的变量只能在函数体内部访问。
函数头部参数表里的变量称为形式参数,形参也是内部变量,只能在函数体内部访问
形参表是函数的入口。
如果说函数名相当于说明运算的规则的话,那么形参表里的形参就相当于运算的操作数,函数的返回值就是运算的结果。
没有返回值就用void定义返回值的类型。

关键字return后面的变量或表达式的值代表函数要返回的值,它的类型应该与函数定义头部中声明的函数返回值类型一致。

一个函数必须被main()调用才能发挥作用。
函数调用:main()函数调用函数Fact(),必须提供一个成为实际参数的表达式给被调用的函数。
调用其他函数称为主调函数,被调用的函数称为被调函数,实参复制给形参的过程被称为参数传递。

若定义main()时未显示指明其返回值的类型,也未使用void,则其返回值将被默认为int类型,但通常将函数写成:
int main () int main (void)
{ {
..... 或者 ....
return 0 ; return 0;
} }

一般都是前者居多。


函数的封装:函数调用时用户只需要知道函数对外的接口(参数和返回值),不需要知道算法实现和内部定义的变量。

函数对外界的影响仅仅是几个入口参数。


//求n!
#include <stdio.h>

long jiecheng( int n )
{
	int i = 1;
	long result = 1;

	if( n == 0||n == 1 )
	{
		result = 1;
	}
	else
	{
		for( i = 1;i <= n ;i++ )  //循环n次
		{
			result *= i;
		}
	}
	return result ;
}

int main()
{
	int a = 0;
	long jieguo = 0;

	do 
	{
		printf("input a num for n!\n");
		scanf("%d",&a);
	}while( a < 0 );            //判断参数是否输入正确

	jieguo = jiecheng( a );      //传参
	printf("%d! = %ld\n",a,jieguo);

	return 0;
}
input a num for n!
12      
12! = 479001600


刚刚的阶乘的函数需要进行对入口(参数)的合法性的维护,维护程序的健壮性。
判断n必须大于0

//求组合C k(上标) m(下标) =  m!/{k!*(m-k)!}

#include <stdio.h>

long jiecheng( int n )   //阶乘函数
{
	int i = 1;
	long result = 1;

	for ( i = 1;i <= n; i++)
	{
		result *= i;
	}
	return result;

}
int main()
{
	int m = 0;
	int k = 0;
	long zuhe ;
	
    printf(" input k m :\n ");
	scanf("%d,%d",&k,&m);

	if( m < k || m <= 0 || k <= 0 )      //判断值是否输入正确
	{
		printf("input error!,please reinput!\n");
		printf(" input k m :\n ");
		scanf("%d,%d",&k,&m);
	}
	if( m == k )      //组合特殊情况
	{
		zuhe = 1;
	}
	else
	{
		zuhe = jiecheng( m )/(jiecheng( k )*jiecheng( m - k ));//公式
	}

	printf("result = %ld\n",zuhe);

	return 0;
}

[root@localhost 413hanshu]# ./a.out
 input k m :
 5,10
result = 252
[root@localhost 413hanshu]# ./a.out
 input k m :
 3,6
result = 20


如果一个对象部分地由它自己组成或按它自己定义,则我们称之为递归。就是由自己推出自己
还是阶乘的问题:
n!:1           n=0,1;
n*(n-1)!  n>=2;

//求n!
#include <stdio.h>

long jiecheng( int n )
{
	int i = 1;
	long result = 1;

	if ( n == 0||n == 1 )
	{
		result = 1;
	}
	else
	{
		result = (n*jiecheng(n - 1 ));   //阶乘
	}

	return result ;
}

int main()
{
	int a = 0;
	long jieguo = 0;

	do 
	{
		printf("input a num for n!\n");
		scanf("%d",&a);
	}while( a < 0 );            //判断参数是否输入正确

	jieguo = jiecheng( a );      //传参
	printf("%d! = %ld\n",a,jieguo);

	return 0;
}

递归调用函数必须包含两种部分:
1.由其自身定义的与原始问题类似的的更小的规模的子问题,它使递归过程持续进行,称为一般情况。
2.递归调用的最简形式,它是一个能够用来结束递归调用过程的条件,通常称为基线情况

变量的作用域和存储类型
不在任意的语句块定义的变量叫全局变量。全局变量的作用域为整个程序,即全局变量在程序的所有位置都有效。
结合递归和全局变量:打印出函数fib(n)的输出值和循环次数
fib(n): 0                 n=0;
1     n=1;
fib(n-1)+fib(n-2)   n>1;

#include <stdio.h>
#include <stdlib.h>
int count = 0;              //计数递归调用了多少次

int fib( int n)
{
	int result = 0;
	
	count ++;                //计数递归调用次数

	if( n < 0)               //判断是否输入正确
	{
		printf("input error!\n");
		exit (0) ;
	}
	else if( n == 0 )
	{
		result = 0;
	}
	else if( n == 1 )
	{
		result = 1;
	}
	else
	{
		result = fib( n - 1) + fib ( n - 2 );  //递归
	}
	return result;
}

int main()
{	
	int a = 0;
	int Result = 0;

	printf("intput n \n");
	scanf("%d",&a);

	Result = fib (a);
	printf("result = %d\n",Result);
	printf("count = %d\n",count);

	return 0;
}

[root@localhost 413hanshu]# ./a.out
intput n 
5
result = 5
count = 15


变量的存储类型:
存储类型  数据类型  变量名表;

c语言提供了了一下几种不同的存储类型:
1.自动变量
2.静态变量
3.外部变量
4.存储器变量

1自动变量:格式: auto  类型名  变量名 
因为经常使用 auto可以省略。

在不同的并列语句内可以同名变量,不会互相干扰,因为它们各自占据着不同的内存单元,并且有着不同的作用域。
例如:形参就可以与实参同名。

可以用const将形参声明成常量,可以有效防止形参值在函数内被修改。
1.自动变量在定义 时不会自动初始化
2.自动变量在退出函数后,其分配的内存立即释放。

静态变量: static  类型名  变量名;生存周期是整个程序运行时间。整个程序执行期间,只能被初始化一次。
具有一定的记忆功能。


外部变量:  extern 类型名  变量名 ;
外部变量保存在静态存储区内,在程序运行期间分配固定的存储单元,气生存期是整个程勋的运行期。自动初始化0.

寄存器变量:没有必要。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值