首页 > 其他分享 >函数

函数

时间:2022-12-25 16:23:20浏览次数:41  
标签:函数 int max void printf 变量

函数

函数的作用

什么是函数

用来完成一定的功能。函数名即给对应功能起一个名字

为什么要使用函数?

事先编好一批常用的函数来实现各种不同的功能,把它们保存在函数库中。需要用时,直接可以调用,可以实现模块化程序设计。大大减少重复编写代码的工作量,提高程序可读性

graph TB 程序软件 --> 功能1 程序软件 --> 功能2 程序软件 --> 功能3 程序软件 --> 功能4 程序软件 --> 功能5

说明:

  • 一个C程序由一个或多个程序模块组成,每一个程序模块作为一个源程序文件。对于较大的程序,一般不希望把所有内容全放在一个文件中,而是把它们分别放在若干个源文件中,由若干个源程序文件组成一个C程序。这样便于分别编写和编译,提高调试效率。一个源程序文件可以为多个C程序公用
  • C程序的执行是从main函数开始的,如果在main函数中调用其他函数,在调用后流程返回到main函数,在main函数中结束整个程序的运行

函数的定义

定义函数的方法

定义无参函数

无参数函数:函数名后面的括号中是空的,没有任何参数

类型名 函数名()   
{
	函数体
}
//或
类型名 函数名(void)   
{
	函数体
}

函数名后面括号内的void表示,即函数没有参数

定义有参函数

类型名 函数名(形式参数列表)   
{
	函数体
}

定义空函数

类型名 函数名()   
{

}

调用函数

调用函数的方法

C语言要求,在程序中用到的所有函数,必须先定义,后使用。为了使用函数时,可以调用到对应的函数

调用函数的形式:

函数名(实参列表)

如果实参列表没有参数,对应的括号也不能省去,如果有多个实参,使用逗号隔开

调用函数的3中形式

  • 函数调用语句:把函数调用单独作为一个语句
  • 函数表达式:函数调用出现在另一个表达式中,如a=strcpy_new(a,b)
  • 函数参数:作为另一个函数调用时的参数

数据如何传递

无参函数不需要进行数据传递。当函数为有参数函数时,要区别数据是如何传递的

定义有参函数:

类型名 函数名(形式参数列表)
函数名(实参列表)
{
	函数体
}
#include <stdio.h>
...
代码1...
...
函数名(实参列表)
...

说明:

  • 函数调用过程中,将实参传递给被调用的形参,使得形参对应变量的内容为实参传递的值。值只在调用期间有效
  • 实参可以是常量、变量或表达式,但要求它们的值必须是确定的
  • 实参和形参的数据类型需要是一致的。如果出现不同类型输出传递,会进行强制转换

返回值

如果需要函数返回一个确定的数值给调用函数,可以通过return语句来实现,也称为函数的返回值

示例;

#include "stdio.h"
int max(int a, int b)
{
    return (a > b ? a : b);
}
int main()
{
    int a, b;
    scanf("%d,%d", &a, &b);
    printf("%d\n", max(a, b));
    return a;
}

结果:

3,5
5

Press any key to continue

说明:

  • 函数的返回值是通过函数中的return语句获得的。如果不需要返回值可以不写return语句,一个函数也可以只有return语句
  • 函数的返回值数据类型需要指定,并且返回给调用函数也需要相同
  • 定义函数时指定的数据类型和return语句中的表达式结果的数据类型相同
  • 无返回值的函数,一般定义为void类型的函数

函数声明

为什么要函数声明?

如果定义的函数位于调用函数之后,需要在主调函数中对别调用的函数作声明。使得在调用函数的时候,编译系统能够正确的识别函数

如何声明?

2种声明形式

  • 函数类型 函数名(参数类型1 参数名1, 参数类型2 参数名2, …., 参数类型n 参数名n)
  • 函数类型 函数名(参数类型1, 参数类型2 , …., 参数类型n)

最简单的做法:将函数定义的首行(函数原型)赋值过来,再加上一个分号,就成了函数的声明

也可以在文件的最开头对所有调用的函数进行声明,则在各个函数中,不必对所调用的函数再作声明。外部声明在整个文件范围内都是有效的

函数嵌套

函数内部不能再定义函数,但可以在函数内部调用另一个函数,称为函数嵌套

main()
...
调用 max
...
int max()
...
调用 max_2
...
return m
int max_2
...
return 最大值

调用 max --> int max();return m --> 调用 max

调用 max_2 --> int max_2;return 最大值 --> 调用 max_2

函数递归

直接或间接调用函数本身,称为函数的递归调用

无限循环

示例:

#include "stdio.h"
int fun(int i)
{
    printf("%d\t", i);
    return fun(i + 1);
}
void main()
{
    int num;
    scanf("%d", &num);
    fun(num);
}

结果:

5
5	6	7	8	9	10	11	12	13	14	15	16	17	18	19	20	21	22	23	24	...

Press any key to continue

求一个数的阶乘

示例:

#include "stdio.h"
int fact(int n)
{
    int f;
    if (n == 1)
        f = 1;
    else
        f = fact(n - 1) * n;
    return f;
}
void main()
{
    int i;
    scanf("%d", &i);
    printf("%d\n", fact(i));
}

结果:

5
120

Press any key to continue

函数参数为数组

传递数组元素

一般来说,变量都可以使用数组元素替代。因此数组元素也可以作为函数实参进行传递

将数组的元素当作实参传递和变量的传递类似,实参使用数组名[下标];形参使用对应元素的类型即可

求5个数值中的最大值

示例:

#include "stdio.h"
int max(int x,int y)
{
	return x>y?x:y;
}
void main()
{
	int a[5],b,c,i;
	for(i=0;i<5;++i)
		scanf("%d",&a[i]);  
	for(i=1,b = a[0];i<10;++i)
	{
		c = max(b,a[i]);
		if( c > b)
			b = c;
	}
	printf("最大的数为:%d\n",b);
}

结果:

2
5
8
7
6
最大的数为:8

Press any key to continue

传递一维数组名

也可以使用数组名作为函数参数

注意:用数组元素作为实参传递时,是传递数组元素的值,但是用数组名作为实参传递时,传递的是数组元素的首元素地址

求5个数值的平均值

示例:

#include "stdio.h"	
float ave(float a[])		//主调函数和被调函数都应该分别定义数组,且数组类型一致
{							//系统不检查形参数组的大小,a[]也可以的
	int i;					//将实参数组的首元素的地址传递给形参,因此a和num使用相同的内存地址
	float b,sum = a[0];
	for(i=1;i<5;++i)
		sum =sum+a[i];
	b = sum/5;
	return b;
}
void main()
{
	float num[5],average;
	int i;
	for(i=0;i<5;++i)
		scanf("%f",&num[i]);
	average = ave(num);
	printf("平均值为:%f\n",average);
}

结果:

5
2
7
9
8
平均值为:6.200000

Press any key to continue

num和a使用同一个内存空间,一旦通过a[0]改变了值,对应的num[0]也改变值内容

传递多维数组名

多维数组元素也可以作函数参数使用

注:形参定义多维数组时,行数可以省略

示例:

#include "stdio.h"
int max(int a[][4])		//编译器不会检查第一维的大小
{
	int i,j,max;
	max = a[0][0];
	for(i=0;i<3;++i)
		for(j=0;j<4;++j)
			if(a[i][j]>max) max = a[i][j];
	return max;
}
void main()
{
	int a[3][4] = {{3,2,7,4},{8,5,8,3},{2,5,3,8}};
	printf("%d\n",max(a));
}

结果:

8

Press any key to continue

局部变量和全局变量

在一个函数中定义的变量能否在其他函数中使用?

示例:

#include "stdio.h"
void fun(int a)
{
	int i,j,k ;	
	i = 10;			
	j = 12;
	k = 3;
	printf("fun函数输出:%d\t%d\t%d\t%d\n",i,j,k,a);	//输出x,y,z,
}
void main()
{
	int x,y,z ;
	x = 10;
	y = 1001;
	z = 1003;
	fun(x);
	printf("主函数输出:%d\t%d\t%d\n",x,y,z);	//输出i,j,k;
}

结果:

fun函数输出:10	12	3	10
主函数输出:10	1001	1003

Press any key to continue

通常变量在函数内部定义,只在本函数范围内有效。这就是变量的作用域

变量定义的范围:

  • 局部变量
    • 在函数的开头定义
    • 在函数内的复合语句内定义
  • 全局变量
    • 在函数的外部定义

局部变量

  • 不同函数中可以使用相同的变量名,但代表的是对应函数内部的数据,互不干扰
  • 形式参数也是局部变量
  • 程序执行完复合语句或调用函数,系统会将对应占用的内存单元释放

全局变量

全局变量可以为本文件中所有的函数共用

在一个函数既可以使用本函数中的局部变量,又可以使用全局变量。全局变量可以实现各个函数之间数据的直接传递

当出现全局和局部定义了相同的变量名时,优先使用局部变量

示例:

int a = 10; 	// 各个函数对全局变量进行改变,会使得全局变量发生变化
#include "stdio.h"
void ff()
{
    int a = 1000;
    int c = 100000;
    a++;
    printf("%d\t%d\n", a, c);
}
// int b = 1;
void main()
{
    int c = 100;
    a++;
    printf("%d\t%d\n", a, c);
    ff();
}

结果:

11	100
1001	100000

Press any key to continue

存在的问题:

  • 全局变量在程序的全部执行过程中都暂用存储单元,而不是在需要时才开辟空间
  • 各模块之间的耦合性比较强,降低了程序的可靠性

全局变量可以实现各个函数之间数据的直接传递,减少return的传递

示例:

float max = 0, min = 0;
#include "stdio.h"
float ave(float a[])
{
	int i;
	float b, sum = a[0];
	for (i = 1; i < 10; ++i)
	{
		if (a[i] > max)
			max = a[i];
		if (a[i] < min)
			min = a[i];
		sum = sum + a[i];
	}
	b = sum / 10;
	return b;
}
void main()
{
	float num[10], average;
	int i;
	for (i = 0; i < 10; ++i)
		scanf("%f", &num[i]);
	max = num[0];
	min = num[0];
	average = ave(num);
	printf("平均值为:%f\t最大值为:%f\t最小值为:%f\t", average, max, min);
}

结果:

1
2
3
3
2
4
3
4
5
6
平均值为:3.300000	最大值为:6.000000	最小值为:1.000000

Press any key to continue

存储类别

变量的存储类别:

  • 自动的
  • 静态的
  • 寄存器的
  • 外部的

函数中的局部变量,如果没有特别声明static存储类型时,都是动态的分配存储空间

动态存储方式:在程序运行期间根据需要进行动态的分配存储空间

函数的形参、局部变量、复合语句中定义的局部变量都是动态存储方式。在使用时开辟空间,在调用结束时回收对应的空间

auto变量

为了区分变量的存储类别,一般在动态存储变量前面加一个auto(自动变量) 关键字

注:一般默认变量前面是auto类型的变量。可以省略不写

示例:

#include "stdio.h"
void fun(int a)
{
	auto int x,y,z ;	
	x = 10;			
	y = 12;
	z = 3;
	printf("fun函数输出:%d\t%d\t%d\t%d\n",x,y,z,a);
}
void main()
{
	int x,y,z ;
	x = 10;
	y = 1001;
	z = 1003;
	fun(x);
	printf("主函数输出:%d\t%d\t%d\n",x,y,z);
}

static变量

static的作用:在定义变量的前面冠上static关键词,表示局部变量的值在函数调用结束后不消失而继续保留原值。在下一次调用该函数时,该变量的值是上一次的值。对应的变量为静态局部变量,属于静态存储方式

静态存储方式:在程序运行期间由系统分配固定的存储空间

示例:

#include "stdio.h"
void fc()
{
    auto int a = 0;   // 新赋值
    static int b = 0; // 使用上一次函数结束后的值
    a += 3;
    b += 3;
    printf("a=%d\tb=%d\n", a, b);
}
void main()
{
    fc();
    fc();
    fc();
}

结果:

a=3	b=3
a=3	b=6
a=3	b=9

Press any key to continue

注:

  • 静态局部变量在整个程序运行期间都不释放内存空间
  • 在第一次赋值有效,以后不再重新赋值,而是使用上一次函数结束后的值
  • 如果不赋初始值,静态局部变量数值类型默认为0,字符默认为\0;自动变量对应是不确定的值
  • 不是必要,不要过多的使用静态变量,降低程序的可读性

register变量

寄存器的存取速度远远高于内存的读取速度,因此一般把需要反复读取的变量冠上register,代表寄存器变量

但现代计算机读取速度非常快,性能非常高,编译系统能够识别反复需要读取的变量,从而自动的将对应的变量存放在寄存器中。在实际编写代码中,无需再对变量进行register申明

extern变量

  1. 在一个文件内扩张外部变量的作用域

    如果外部变量没有在文件开头定义,对应的作用域是在定义处到文件的最后。如果在定义点之前需要使用外部变量,可以通过关键字extern对该变量作外部变量声明

    示例:

    #include "stdio.h"
    void ff()
    {
        extern int a;
        int c = 100000;
        a++;
        printf("%d\t%d\n", a, c);
    }
    int a = 10;
    void main()
    {
        int c = 100;
        a++;
        printf("%d\t%d\n", a, c);
        ff();
    }
    

    结果:

    11	100
    12	100000
    
    Press any key to continue
    

    提示:

    • 全局变量也是静态存储
    • 外部变量的定义放在引用它的所有函数之前,可以避免额外的extern声明
  2. 当有多个文件时,将外部变量的作用扩张到其他文件

    如果一个程序包含多个文件,假如a文件定义了外部变量,b文件要想使用a文件中的外部变量,需要用extern进行变量声明

  3. 不让别的文件使用本文件的外部变量

    定义外部变量时加上static声明

内部函数和外部函数

如果一个函数只能被本文件中其他函数所调用,称为内部函数(静态函数)

在定义函数时,在函数类型的前面加上static声明

如果在定义函数的函数类型前面加上extern关键词,则表示函数是外部函数,可以被其他文件使用

定义函数时,默认都是外部函数,可以省略extern

扩展

设置密码

示例:

#include "stdio.h"
#include "windows.h"

int password;
void password_intput()
{
    printf("请输入需要设置的密码:");
    scanf("%d", &password);
    printf("设置成功\n");
}
void password_validation()
{
    int password_verify, i = 0;
    while (1)
    {
        Sleep(10000);
        printf("请验证您的密码:");
        scanf("%d", &password_verify);
        if (password_verify == password)
            printf("输入的密码正确\n");
        else
        {
            printf("输入的密码不正确\n");
            i++;
        }
        if (i == 5)
        {
            printf("五次验证不通过,密码开始锁定\n");
            printf("密码锁定中...\n");
            break;
        }
    }
}
void main()
{
    password_intput();
    password_validation();
}

标签:函数,int,max,void,printf,变量
From: https://www.cnblogs.com/ruoxianshi/p/17004156.html

相关文章

  • Python中使用zip函数的七重境界
    1.引言Python中有一些内置函数,可以使我们的代码非常优雅。​​zip​​函数就是其中之一,但是zip函数的使用对于初学者来说不是很直观,有时容易出错。因此本文将从7个层次来......
  • 【模式识别】判别函数和感知机算法
    给定两个类别的一共8个样本,通过感知机算法求解判别函数defbi_perception():X1=np.array([[0,0,0],[1,0,0],[1,0,1],......
  • csharp通过dll调用opencv函数,图片作为参数
    [blog项目实战派]csharp通过dll调用opencv函数,图片作为参数     一直想做着方面的研究,但是因为这个方面的知识过于小众,也是由于自己找资料的能力......
  • 工作表函数的代码嘴脸(可定义名称的函数合集)
    ​​LET函数​​​​Lambda公式,函数公式or函数名?​​​​华丽丽地越过了多维引用的MakeArray​​​​有了ByRow和ByCol,MM函数还要怎么混?​​​​同样华丽丽地越过了多维引用......
  • JS函数
    斐波那契数列//数列:112358...functionfibonacci(n){if(n===1||n===2){return1}returnfibonacci(n-1)+fibonacci(n-2)}console......
  • Javascript的函数、递归函数、作用域
      代码示例:<!DOCTYPEhtml><html><head><metacharset="utf-8"><title></title></head><body><script>fu......
  • Python爬虫-第二章-1-函数
    list()bin,oct,hexformat,ord,chrall,any,enumerate#DemoDescribe:常用内置函数1'''list()bin,oct,hexformat,ord,chrall,any,enumerate'''#----------1.list()'''l......
  • C++ empty函数
    https://blog.csdn.net/qq_41598072/article/details/99973908empty是用来测试变量是否已经配置。若变量已存在、非空字符串或者非零,则返回false值;反之返回true值。所......
  • C++ sort函数中利用lambda进行自定义排序规则
    在c++中,由于sort()函数默认提供的是由小到大的排序方式,因此有时候我们需要自定义排序规则来实现由大到小的排序。一维vector<>排序#include<bits/stdc++.h>usingnam......
  • 线性探测法的查找函数
    试实现线性探测法的查找函数。函数接口定义:PositionFind(HashTableH,ElementTypeKey);其中HashTable是开放地址散列表,定义如下:#defineMAXTABLESIZE100......