C语言的函数

1、什么是函数?

function --> 功能、函数

c语言中函数是指对能对完成某个特定功能的代码块的封装形式

怎么封装?

把这些特定功能的代码块放在一个{}内

函数有什么用?为什么要用?

结构化程序设计者 ,主张把很大的任务分成多个小任务(函数)来完成。

把每一个小任务封装成函数,有利于简化代码,提高代码复用率,因为有些小任务可能会在程序中多次使用,

如果把这些功能我们封装成函数,每次要用到那个功能时候,不用重复的编写这个功能的的代码,

只需要“调用”该函数即可。

封装成函数有利于维护代码(找bug 方便升级)

如:

求两数的和

int sum(int a,int b)

{

int s;

s = a + b;

return s;

}

2、怎么设计函数/怎么写函数

定义函数的语法:

返回值类型 函数名(形参类型1 形参名1,形参类型2 形参名2,....) ------> 函数头

{

//完成特定功能的代码块

...

...// {}内 称为 函数体

...

return 值;// 有时候可以省略

}

如上 求和的函数

(1)明确干什么,完成什么任务 取个名 ----> 函数名function

符合 C语言标识符定义,不能取关键字相同 最好能够顾名思义 sum

(2)明确完成这个任务,需要什么条件 这些条件放在函数名后面的()中

----> 通过"参数列表" 告诉使用者

参数列表:

形参类型1 形参名1,形参类型1 形参名1...

求和需要的条件 两个整型数据 (只有知道这两个数才能去和)

形参类型 C语言合法类型

形参名 符合 C语言标识符定义,不能取关键字

有些情况 可以不用 参数, ()中为空或者写 void

(3)明确完成任务 后的 结果 ----返回值

返回值是执行完该函数/完成该功能 之后 的结果

大部分情况都有一个结果,有对应的类型称为返回值类型

怎么返回:return 结果;

return s;

有些特殊情况可以没有返回值的,返回值类型就写 void

(4) 函数体

具体的代码实现

完成该功能的代码块

int s;

s = a + b;

练习:

写一个判断是否为闰年的函数 如果是闰年就返回1,否则返回0

3、怎么使用函数(调用函数)

函数写好后,不会自动执行,需要被调用的时候才会执行。

怎么调用:

函数名(实参列表);---> 函数调用表达式

实参列表,要和被调用的函数的形参列表对应(参数个数要相同,类型要相同或兼容)

但是实参列表中 不需要写参数类型

int sum(int a,int b)

{

int s;

s = a + b;

return s;

}

int a = 10,b = 20;

sum(a,b);

sum(b,a);

sum(5,7);

sum(2*2,1/1);

.....

sum(int x,int y);//error 不需要写参数类型

总结:

实参列表中的实参可以是常量、变量、表达式 或它们的组成形式,都不需要写参数类型

如果函数有返回值的话(有 return 语句),则需要接收该返回值

变量名 = 函数名(参数列表);

变量名类型 要和 返回值类型 相同 / 兼容

如:

int z = sum(3,5);// int z; z = sum(3,5);

z = sum(2*2,1/1);

....

主调函数和被调函数

主调函数:调用函数的函数,可以是任意函数

被调函数:被调用的函数,可以是除了main函数之外任意函数

练习:

调用刚刚写的求闰年的函数

写一个判断一个数是否为质数的函数并在主函数内调用

4、函数的声明

声明:告诉编译器这是一个函数

声明一个函数的语法:

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

就把函数头复制过来,加个分号即可,写在头文件之后

注意:形参列表中可以省略形参名字,但是不能省略类型

函数声明不是必须的,一般来讲被调函数写在主调函数之后,就需要申明,否则编译器可能会不认识这是一个函数

5、函数调用详细过程

大概分为三步:

(1)传参

把实参的值一一对应的传递给形参

这个过程中会为形参分配空间并且初始化(初始值就是 对应实参)

在被调函数中改变形参的值,不会影响实参的值。因为它们是独立的变量

(2)进入被调函数的函数体中执行代码

(3)执行 return 语句,遇到 } 也会结束

无论是在函数的那个位置遇到 return 直接结束函数

return 后面的值会赋值给 函数调用表达式 ,如果没有 return 语句,那么函数调用表达式的值不确定

分析:

long long int jiecheng(int n)

{

if(n == 1)

return 1;

else

{

long long int s = jiecheng(n -1) * n;//自己调用自己递归

return s;

}

}

int main()

{

int a = 20;

long long int j = jiecheng(a);

printf("j = %lld\n",j);

return 0;

}

作业:

理解函数相关知识

分析上面代码

写一个求阶乘的函数 和上面的不一样

写一个函数 把10进制转换成n进制 (2<= n <= 16)

f(1) = 1;

f(m) = f(m-1) * f(m-2) * .... * f(2) * f(1);

f(m) = m*....4*3*2*1

6、递归

递归是指 函数体中调用函数本身的方式(主调函数和被调函数 都是本身)

在数学上经常用到

如:

求阶乘

f(n) = 1 (n = 1)

= f(n-1) * n(n > 1)

求斐波拉契数列

f(n) = 1(n =1 或 n = 2)

= f(n - 2) + f(n - 1)(n > 2)

特点:

在解决问题的某个步骤需要用到这个问题本身

并且 问题的规模 逐渐缩小,当缩减到一定程度的时候结果显而易见。

7、数组作为函数参数

比如

写一个求一维数组最大值函数

一般需要两个参数

第一个参数是这个数组名

第二个参数是数组的元素个数

例:

int arraymax(int a[],int n)

{

int max = a[0];

int i;

for(i = 0;i < n;i++)

{

if(a[i] > max)

{

max = a[i];

}

}

return max;

}

void test()

{

int b[10] = {1,3,5,7,8,10,12,2,4,6};

int max = arraymax(b,10);//调用的时候不用 []

printf("该数组的最大值是%d\n",max);

}

8、练习:

写一个求一维数组所有元素和的函数

写一个函数 判断一维数组是否为升序(是的话返回0,不是返回1)

递归:

当 n = 1 肯定升序1个元素

当 n > 1 ,除了最后一个元素之外的子数组是升序 并且 最后一个元素大于 倒数第二个元素 -->升序

作业:

求100以内的“完数”

完数: 所有的因数(除去它本身)之和等于它本身

6 = 1 + 2 + 3

提示:

先得到 该数的因数

再累加完 判断一下 是否 相等 不用做了 输出就好

如果 大于 了 不用做了 换个数

附加题:

汉诺塔问题,打印出最优次数和最优解的步骤 A 、B、C代表那三根柱子

把A 上面的 所有 放到 B 上面

1、 A上面的 n-1 先放到 C 上面

2、 把 A上面剩的最大的 盘 放到B

3、C 上面 的 n-1 个放到 B上面

1、3 还是一个汉诺塔问题 但是 规模减小了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

新棉衣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值