初始C语言(6)(函数)的详细内容解答。

目录

 main函数和库函数;

什么是函数;

函数定义与调用;

将函数的返回值作为参数传递给函数;

值传递;

没有返回值的函数;

不含形参的整数;

作用域;

文件作用域;

数组的传递;

函数的传递和const类型修饰符;

线性查找;

总结;


main函数和库函数;

在C语言中,main函数是必不可少的,程序在运行的时候,会执行main函数的主体部分,在main函数中使用的printf,scanf,puts函数在C语言中被称为库函数。

什么是函数;

我们先创建一个简单的函数:

创建一个函数,接收两个整数的参数,返回较大值的整数!

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

int max(int a, int b)
{
	if (a > b)
	{
		return a;
	}
		
	else
	{
		return b;
	}
}

int main(void)
{

	int a = 0;
	int b = 0;
	
	printf("请输入两个整数:\n");
	printf("整数1:"); scanf("%d", &a);
	printf("整数2:"); scanf("%d", &b);

	max(a, b);

	printf("两个整数最大值是%d", max(a, b));


	return 0;
}

 我们可以用一张图片来解答刚才创建函数的流程!

函数这一名词,来源于数学术语函数(function)。意思是“功能”“作用”“职责”的意思 。


函数定义与调用;

函数的创建---函数定义

函数的使用---函数调用

函数定义(创建):

函数是由两个大部分组成的,分别是函数头函数体。函数头又包括(返回类型,函数名称,形参声明)。

 函数头:该部分表示函数的名称和格式。

返回类型:函数返回的值的类型,可以是double也可以是void(不返回值)。

函数名:函数的名称,我们在使用函数的时候,就可以直接使用函数名。

形参声明:小括号括起来的部分,是用于接收辅助性提示变量--形式参数的声明。

函数体:函数体是复合语句,仅在某个函数中使用的变量,原则上应该在函数中声明和使用。但要注意不能声明和形参同名的变量,否则会变量名冲突的错误。

函数调用(使用):

创建一个函数,求出两个整数相加的和!

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

int num(int i, int m)
{ 
	int z = 0;
	z = i + m;

	return z;
}

int main(void)
{

	int a, b = 0;

	printf("请输入两个整数:\n");

	printf("整数1:"); scanf("%d", &a);
	printf("整数2:"); scanf("%d", &b);

	printf("两个整数相加的和是%d。", num(a, b));


	return 0;
}





在这个程序中,定义了两个函数,一个是主函数(main)一个是求和函数(num)。虽然求和函数定义在main函数的前面,但是却没有先执行求和函数,而是执行了main函数,因为main函数是一个程序的主体,在所有函数中,都会第一时间从main函数执行。

而求和函数的执行流程解析:

 函数调用的形式就是在函数名后面加上小括号。这个小括号就叫做(函数调用运算符)而函数表达式就叫做函数调用表达式,函数调用运算符中的括起来的就是实参,当实参不止一个的时候,就需要用逗号隔开

进行函数调用以后,程序的流程会转到被调用的函数处,这时,传递过来的实参会被赋值给函数接受的形参!

形参的初始化结束以后,将执行函数体。程序遇到return语句的时候,或者执行到函数体最后的大括号的时候,就会从该函数转到调用函数。

写一个函数,求出三个整数中最大的一个数。

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

int max3(int i, int m, int e)
{ 
	int max = i;
	if (m > max)
	{
		max = m;
	}
	if (e >max)
	{
		max = e;
	}

	return max;
}

int main(void)
{

	int a, b, c = 0;

	printf("请输入三个整数:\n");

	printf("整数1:"); scanf("%d", &a);
	printf("整数2:"); scanf("%d", &b);
	printf("整数3:"); scanf("%d", &c);

	printf("最大的数是%d。", max3(a, b, c));



	return 0;
}

将函数的返回值作为参数传递给函数;

输入两个整数,计算出他们的平方差并显示。

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

int pf(int a)
{
	return a * a;
}

int ret(int i, int m)
{
	return(i > m ? i - m : m - i);
}


int main(void)
{

	int x = 0;
	int y = 0;  //我输入的两个整数

	printf("请输入两个整数:\n");
	printf("整数1:"); scanf("%d", &x);
	printf("整数2:"); scanf("%d", &y);

	pf(x); //计算平方的函数
	pf(y);
	ret(pf(x), pf(y));

	printf("平方差是%d", ret(pf(x), pf(y)));


	return 0;
}

分析:

分析之前,我们再回顾一下‘ ? :’ 条件操作符(三目操作符),其表达形式如下:

表达式1为真时,执行表达式2,否则执行表达式3。 

这个代码我们定义了两个函数,分别是pf函数(计算平方的函数)和ret函数(比较两个整数的函数)。首先定义的第一个函数(pf函数)因为我们需要返回一个整形的值,所以返回类型一定是int,接着就是接收整形就平方,因为输入的整数,也是用int类型接收,最后直接返回就行了。第二个就是ret函数,这个函数比较奇怪的地方是它return后面的那个表达式,但是我们前面介绍过了这个操作符,但这个操作符放在ret函数里面的意义就是“较大的值减去较小的值”。这个就是平方差的方法!定义完成后,直接调用。

值传递;

创建一个计算幂的函数,如果n是整数,就计算出x是n的几次幂。

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

double power(double x, int n)
{
	int i = 1;
	double tmp = 1.0;

	for (i = 1; i <= n; i++)
	{
		tmp *= x;
	}

	return tmp;

}

int main(void)
{
  double a = 0;
  int b = 0;
	
  printf("求出a的b次幂:\n");
	
  printf("实数a:"); 
  scanf("%lf", &a);  //输入double类型的变量的时候,就不是%d了
  printf("整数b:");
  scanf("%d", &b);
	
  //power(a, b);  //创建一个求次幂的函数
	
  printf("%.2f的%d次幂是%.2f.\n", a, b, power(a, b));
	

	return 0;
}


如上述代码,形参x的值被赋值了实参a的值,形参n的值被赋值了实参b的值,像这样值来通过进行参数的机制称为值传递

没有返回值的函数;

显示出一个直角在左下方的等腰直角三角形(函数)。

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

void put_staris(int n)
{
	while (n-- > 0)
	{
		printf("*");
	}
}

int main(void)
{
	int i = 0;
	int len = 0;

	printf("生成一个直角三角形在左下方:\n");
	printf("几边:");
	scanf("%d", &len);

	put_staris(i);

	for (i = 1; i <= 5; i++)
	{
		put_staris(i);
		putchar('\n');
	}


	return 0;
}

因为我们写的这个函数不需要返回结果,只需要显示,这个时候我们就可以使用void。

void就是“空”的意思,意思是没有。在c语言中,不论有没有返回值都同样作为函数,在其他的编程语言中。没有返回值会定义其他非函数的概念,例如子程序或者过程。

不含形参的整数;

输入一个正整数,并显示其倒转的值

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

int scan_zfhanshu(void) //判断正负的函数  不需要接收,输入void
{
	int tmp;

	do
	{
		printf("请输入一个正整数:");
		scanf("%d", &tmp);
		if (tmp <= 0)
		{
			printf("请不要输入非正整数的数字。\n");
		}


	} while (tmp <= 0);
	
	return tmp;
}


int ret_daozhuan(int num) //进行倒转的函数
{
	int tmp = 0;

	if (num > 0)
	{
		do
		{
			tmp = tmp * 10 + num % 10;
			num /= 10;

		} while (num > 0);

	}
	return tmp;
}


int main(void)
{
	int i = scan_zfhanshu();

	printf("该整倒转后的值是多少:%d", ret_daozhuan(i));


	return 0;

}

分析:

因为在函数中就可以读取到键盘输入的整数并返回,所以就不需要接收形参了,因此在小括号中输入void

在main函数中声明的i变量,其实是在scan—zfhanshu中输入的整数(程序执行时从键盘上输入非负的整数)。

作用域;

在这两个创建的函数中,都有一个相同标识符(名称)的变量tmp。但是他们两个却是各自独立的变量。

也就是说在函数scan_zfhanshu中的tmp变量是scan_zfhanshu中独有的一个变量。

在函数ret_daozhuan中的tmp变量是ret_daozhuan独有的一个变量,相互是不干预的。

赋给变量的标识符,它的名称都有一个通用的范围,称为作用域。

在程序块(复合语句)中声明的变量的名称,只在该程序块中调用,在其他区域无效,也就是说,变量的名称从变量声明的位置开始,到包含该声明的变量的程序块最后的大括号}为止这一区域都有用,这样的作用域称为块作用域。(参考下面图片)

文件作用域;

输入5名同学的分数,并求出最高分。

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

#define number 5   //定义number为5

int tensu[number];   //定义一个数组为五个人 (创建数组的实体声明,定义) 

int top(void);  //定义一个判断最高分的函数

int main(void)
{
	int i = 0;
	extern int tensu[number];  //声明这个数组,并不是定义

	printf("请输入这%d学生的分数:\n", number);

	for (i = 0; i < number; i++)
	{
		printf("%d:", i + 1);
		scanf("%d", &tensu[i]);
	}
	printf("最高分是:%d", top());

	return 0;

}

int top(void)
{
	extern int tensu[number];
	int i = 0;

	int max = tensu[0];

	for (i = 1; i < number; i++)
	{
		if (tensu[i] > max)
		{
			max = tensu[i];
		}
	}

	return max;

}

在函数的程序块中声明的变量等标识符是该程序块特有的部分。而想数组tensu这样,在函数外面声明的变量标识符,其名称的开始到程序的结尾都是通用的

这样的作用域称为文件作用域

声明和定义:

 该程序中,创建了一个元素为5的数组。想这样创建的变量实体的声明称称为定义

函数原型声明:

编译器在读取数据的时候,也是按照从头到尾的顺序依次解读的。因为上述程序中,top函数定义在main函数后面的,所以想要在main函数中调用top函数我们就一定要声明!

像:

 明确了记述了函数的返回类型,以及形参的类型和个数的声明称为函数原型声明。

需要注意的是,这种声明需要分号结尾。

函数原型定义只是声明了函数的返回值和形参等相关信息,并没有定义函数的实体。函数定义和函数原型声明不同之处如下所示:

如果函数top函数的需求发生了改变,那么定义函数和函数原型声明两部分都必须进行修改。但是如果top函数定义放在了main函数前面,就不用特意使用函数原型声明了。

数组的传递;

写一个程序,计算出英语和数学的最高分数

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

#define NUMBER 5

int max_js(int v[], int n)  //
{
	int i = 0;
	int max = v[i];

	for (i = 1; i < n; i++)
	{
		if (v[i] > max)\
		{
			max = v[i];
		}
	}

	return max;
}

int main(void)
{

	int i = 0;
	int mat[NUMBER] = { 0 };   //数学分数
	int eng[NUMBER] = { 0 };   //英语分数

	int max_m = 0;  //数学最高分
	int max_e = 0;  //英语最高分

	printf("输入%d同学的分数:\n",NUMBER);

	for (i = 0; i < NUMBER; i++)
	{
		printf("[%d]英语:", i + 1);
		scanf("%d", &eng[i]);
		printf("   数学:");
		scanf("%d", &mat[i]);
	}

	int max_js();  //创建一个计算最高分的函数

	max_e = max_js(eng, NUMBER);  //英语最高分
	max_m = max_js(mat, NUMBER);  //数学最高分

	printf("英语最高分数=%d\n", max_e);
	printf("数学最高分数=%d\n", max_m);




	return 0;
}

创建的max_js的作用就是:找出包含任意个元素的int类型数组中的最大值,然后返回该值。

该数组接收的形参的声明就是“类型名 参数名[ ]” ,这样的n就是接收元素的个数。

函数的传递和const类型修饰符;

就数组全部设置为0

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

void print_arr(const int v[], int n)
{
	int i = 0;

	printf("{");
	for (i = 0; i < n; i++)
	{
		printf("%d ", v[i]);
	}
	printf("}");
}

void print_zero(int v[], int n)
{
	int i = 0;
	for (i = 0; i < n; i++)
	{
		v[i] = 0;
	}
}

int main(void)
{

	int arr1[] = { 1, 2, 3, 4, 5 };
	int arr2[] = { 3, 2, 1 };

	printf("arr1="); print_arr(arr1, 5); 
	putchar('\n');

	printf("arr2="); print_arr(arr2, 3);
	putchar('\n');


	print_zero(arr1, 5);
	print_zero(arr2, 3);

	printf("把0赋值给所有元素。\n");

	printf("arr1="); print_arr(arr1, 5); 
	putchar('\n');

	printf("arr2="); print_arr(arr2, 3);
	putchar('\n');
	

	return 0;
}

const:当我们希望变量不被改变的时候,我们就可以在前面使用const的类型修饰符,简而言之就是在变量面前加上const这个值就不会被修改。、

由于我们在printf_arr这个函数中使用了const类型修饰符,因此在函数中就不能在修改数组v的元素值了。

注意:

如果只是引用所接受的数组元素值,而不改写的话,在声明接受数组的形参时候就应该加上const。这样函数调用就可以安心的调用函数了。

线性查找;

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

#define NUMBER 5  //定义数组元素个数

#define FAILEAD -1  //查找失败

int search(const int v[], int key, int n)  //分别代表的是:输入元素的值不能改变,查找的元素,接收元素的个数
{
	int i = 0;

	while (1)
	{
		if (i == n)
		{
			return FAILEAD;
		}

		if (v[i] == key)
		{
			return i;
		}

		i++;
	}

}

int main(void)
{
	int i = 0;
	int ky = 0;  //我要查找的值
	int idx = 0;
	int vx[NUMBER] = { 0 };


	for (i = 0; i < NUMBER; i++)
	{
		printf("vx[%d]", i + 1);
		scanf("%d", &vx[i]);
	}
	
	printf("要查找的值:");
	scanf("%d", &ky);

	idx = search(vx, ky, NUMBER);  //分别代表的是元素的值。要查找元素的值,和数组元素的个数

	if (idx == FAILEAD)
	{
		puts("查找失败。");
	}
	else
	{
		printf("%d是数组的第%d元素。\n", ky, idx + 1);
	}

	return 0;
}

函数search是从元素个数为5的int 类型数组v中依次查找与key相同的值,而这个key就是我们输入的ky的值。如果有相同的值,则返回数组元素的下标,如果没有则返回FAILERA,也就是-1。

函数search中的while语句表达式中的“1”,因此只有在执行return语句中才能跳出循环,否则将永远执行下去。

像这样,从数组开头顺次搜索找出与目标相同的元素一系列操作,称为线性查找或者叫顺序查找。

总结;

1.函数体是复合语句(程序块)。如果仅有函数中使用变量,原则上应该在函数中声明和使用。

2.函数调用的形式是在函数名后面加上小括号。这个小括号称为函数调用运算符。如果没有实参,则小括号中为空。有多个实参的情况下,用逗号隔开。

3.创建变量或者函数实体的声明称为定义声明,否则为非定义声明。

4.在函数中执行return语句的时候,或函数执行结束的时候,程序流就会返回到原来进行调用的地方。如果函数放返回类型不是void类型,则返回到原来调用的地方时,会返回到单一的值。

5.在函数外定义的变量,拥有文件作用域;在函数内定义的变量拥有块作用域;

6.对函数调用表达式进行判断,会得到函数返回的值。

到此函数的内容就已经结束了!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值