C语言函数

Posted on 2019-07-07 19:37  不叫柒桓叶  阅读(264)  评论(0编辑  收藏  举报

函数:function,功能模块

C语言中,函数是完成某个特定功能的指定序列的封装。(在C语言中,指令只能在函数内部)

 

函数可以实现代码的复用,以及模块化的设计

 

结构化设计主张把大任务,分成多个小任务(多个函数)来完成

 

函数就是实现某个功能的指令序列

 

设计一个函数,需要考虑哪些问题?

1)这个函数的功能是什么?

目的

2)完成这个功能,需要什么资源?输入参数

需求分析

 

3)怎么完成?  

算法思路

 

4)完成情况,结果?

返回值

输出

 

功能:求一个数组的最大值

1)目的:求一个数组的最大值

 

2)需要的资源

整个数组

 

3)算法思路

遍历

4)返回值

 

1.c函数实现

C语言定义一个函数

 

返回值类型 函数名(输入参数列表)

{

声明部分

语句部分 =》指令序列

}

 

“返回值类型” :函数返回值的类型

“函数返回值” :语句return 后面的那个表达式的值

函数也可以没有返回值,即返回值类型为void

 

return ; =>仅仅结束该函数

 

return ; =>该函数有返回值

 

“函数名”:要符合C语言的标识符的规定

 

“输入参数列表” :功能模块的输入

格式如下:

(参数类型1 参数名1,参数类型2 参数名2,......)

参数就是函数的局部变量,只不过他的初始值有调用者给定

 

函数也可以没有参数,即输入参数列表为空或void

 

{} :花括号里面就是完成这个函数的功能的代码的实现

 

函数头+函数体

 

/*

求一个数组的最大值

*/

 

int find_max(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;

}

 

这个函数里面的指令会不会自动执行?

 

2.函数调用:

调用函数 :执行某个函数

调用函数:

要调用的函数名(传递个这个函数的实际参数);

 

函数调用语句:要调用的函数名(传递个这个函数的实际参数);

 

要调用的函数名(传递个这个函数的实际参数) =》函数调用表达式

函数调用表达式的值,就是这个函数的返回值

 

函数的调用过程: “传值调用”

 

把实际参数的值赋值给对应的形式参数,然后跳到被调用的函数中去执行

,被调用函数return语句表名被执行完毕,并且整个函数调用表达式的值

就是return后面的表达式的值

 

实际参数:函数调用表达式里面的参数。实际参数不需要写类型

所有有值的表达式都可以当做实际参数

 

fun(3,4+5);//3,4+5.0称为实参

 

int a = 3,b = 7;

fun(a,a+b);

 

形式参数:函数定义时的参数

 

int fun(int a,int b) //a,b就是形参

{

 

}

 

练习:

1)写一个函数,判断一个数组是否为递增数组

返回1

不是 返回0

 

/*

判断一个数组是否为递增数组

@a:数组名

@n:数组元素的个数

返回值:

1 =》递增

0 =》非递增

*/

int is_inc(int a[],int n)

{

int i;

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

{

if(a[i] >= a[i+1])

{

return 0;

}

}

return 1;

}

 

 

函数调用过程:

传值调用,把实参的值拷贝一份赋值给相应的形参

 

主调函数: 调用别人的函数

被调函数: 被别人调用的函数

 

数据传递

主调函数 -》被调函数   参数

被调函数 -》主调函数   返回值

主调函数 -》被调函数   全局变量

 

3.递归函数

我们在定义一个函数表达式的时候,有直接或间接的调用了该函数表达式本身

这种函数称为递归函数

 

假设f(n)n的阶乘

f(4) =>4!

f(5) =>5!

 

...

f(n) =>n!

 

when n = 0 or n = 1 f(n) == 1

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

 

=>f(n) 为递归函数

 

C语言直接支持函数的递归调用(不能是无限递归)

当递归到某个程度是,其结果显而易见

 

int f(int n)

{

if(n < 0)

{

}

if(n == 0 || n == 1)

{

return 1;

}

else

{

return n*f(n-1);

}

}

 

 

int main()

{

int n = 3;

 

}

 

====

设计递归

1)在解决问题的时候,遇到了该问题同样的问题

2)不能是无限递归

 

练习:

(1)写一个函数,求斐波那契数列的第n

1 1 2 3 5 8 13 .....

 

n = 1 F(1) == 1

n = 2 F(2) == 1

n = 3 F(3) == F(2) +F(1)

int F(n)

{

if(n <= 0 )

{

return 0;

}

if(n == 1 || n == 2)

{

return 1;

}

else

{

return F(n-1)+F(n-2);

}

}

 

(2)hanoi塔问题

写一个函数,实现Hanoi塔的搬运步骤

 

功能:把n个盘子从A移动到C,中间利用B

 

输入参数:

n :多少个盘子

A :起点

B :中转点

C :终点

 

Hanoi(1,A,B,C) ?

直接从A移动到C

 

Hanoi(2,A,B,C)

A->B

A->C

B->C

 

//Hanoi(3,A,B,C)

 

Hanoi(n,A,B,C)

 n > 1

(1) Hanoi(n-1,A,C,B)

 

(2)A->C

 

(3)Hanoi(n-1,B,A,C)

 

void Hanoi(int n,char A,char B,char C)

{

if(n == 1)

{

printf("%c->%c\n",A,C);

return ;

}

Hanoi(n-1,A,C,B);

 

printf("%c->%c\n",A,C);

 

Hanoi(n-1,B,A,C);

 

}

 

作业:

(1)能不能计算移动n个盘子,所需要的步数

 

 

(2)“鞍点”:行中最大,列中最小

a[4][4]

 

#include <stdio.h>

 

int main()

{

int a[4][4],i,j,k,max;

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

{

for(j = 0;j < 4;j++)

{

scanf("%d",&a[i][j]);

}

}

 

for(i= 0;i<4;i++)//

{

max = a[i][0];

for(j = 0;j < 4;j++)//找到一行中最大的那个值

{

if(max < a[i][j])

{

max = a[i][j];

}

}

 

for(j = 0;j < 4;j++)//找最大的值的位置

{

if(max == a[i][j])

{

for(k = 0;k < 4;k++)

{

if(a[k][j] < a[i][j])

{

goto loop;

}

}

 

printf("鞍点:a[%d][%d] = %d\n",i,j,a[i][j]);

 

}

 

loop:

  ;

}

 

 

}

}

 

 

=======================

C语言对象的作用域和生存期

1.作用域

what

起作用的一个区域

 

变量和函数的作用域

 

变量从作用域来分,分两种

1)全局变量:定义在函数外面的变量

整个工程都起作用的全局变量

一个有多个源文件(1.c,2.c,3.c....

在这些文件中都可以访问的全局变量

eg:

1.c

int a = 5;(函数外部定义)

作用域:整个工程文件

 

2.c需要用到1.ca

extern int a;//这个变量a是在外面的文件定义的,但是当前文件需要用到

 

仅在当前文件内起作用的全局变量

1.c  

static  int a = 5;(函数外部定义)

=>声明a仅在本文件(1.c)中有效,其他文件不能用1.ca

 

2)局部变量

定义在{}(函数内部或代码块)里面的变量,局部变量

作用域:仅在{}(函数内部或代码块)内起作用

 

eg:1.c

int a = 250;

int main()

{

int a = 5;

if(1)

{

int a = 6;

printf("A = %d\n",a);

}

printf("a = %d\n",a);

}

 

A = 6

a = 5

只要作用域不一样就可以定义同名的变量

 

====

函数的作用域

1)全局作用域

对整个工程都有效

1.c

int sum(int a,int b)

{

return a+b;

}

 

2.c

声明:sum是一个外部定义的函数

 

extern  int sum(int a,int b);

 

fun()

{

sum(2,3);

}

 

2)仅在文件中有效

1.c

static int sum(int a,int b)

{

return a+b;

}

=>sum仅在当前文件有效

 

=static的两个作用

1static修饰全局变量和函数时,使得全局变量和函数的作用域只在当前文件有效

 

(2)static修饰局部变量,使得局部变量的生存期变为随着进程的持续性并且static修饰的变量,只被初始值赋值一次,之后不会再被循环中比如while(1){

Static int x = 2,

X++;}此时只会赋值一次,第二次进循环将不再被赋值为2,而是直接处理下面的内容

 

 

2.生存期

what

从生到死的期间

 

随文件系统的持续性:

 

随内核持续性:

操作系统一启动他就存在,并且存在到操作系统关闭

 

随进程的持续性(随程序的持续性):

程序一运行他就存在,并且存在到程序的退出

 

int a = 5;

 

void fun()

{

int c;

static int b = 6;

b++;

printf("b = %d\n",b);

}

 

int main()

{

fun();

fun();

}

 

全部变量astatic局部变量,随进程的持续性

程序一运行就会给a,b开辟空间,并且这个空间会一致存在直到程序退出

 

static局部变量定义并赋值的语句,只会在给该变量分配空间的时候执行一次

 

其他的普通局部变量:函数执行时分配空间,执行完毕,释放空间

 

 

随代码块持续性:

这个代码运行就存在,直到代码结束

 

普通的局部变量

 

Copyright © 2024 不叫柒桓叶
Powered by .NET 8.0 on Kubernetes