【C语言】函数----函数的分类、库函数详解(strcpy、memset)、自定义函数的实现(找较大值、交换两个数)


一.函数是什么

维基百科中对函数的定义:子程序

1.在计算机科学中,子程序(英语:Subroutine, procedure, function, routine, method,
subprogram, callable unit),是一个大型程序中的某部分代码, 由一个或多个语句块组
成。它负责完成某项特定任务,而且相较于其他代 码,具备相对的独立性。
2.一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软
件库。


在这里插入图片描述


二.C语言中函数的分类

1.库函数
2.自定义函数


在这里插入图片描述


1.库函数

1.库函数是c语言库内已经写好的函数,只要我们引入相应的头文件就可以直接使用,比如在编写完一个代码后想打印在屏幕上看看,这个时候我们会频繁的使用一个功能:将信息按照一定的格式打印到屏幕上(printf)。
2.我们会频繁的做一些字符串的拷贝工作(strcpy).
3.计算某个数的n次方(pow)。

像上面非业务性的代码,我们在编写代码的时候用的都比较频繁,为了支持可移植性和提高程序的效率,所以C语言的基础库(标准库)中提供了一系列类似的库函数,方便程序员进行软件开发。

C语言中常用的库函数有:

IO函数:即输入()input输出(output)函数
字符串操作函数:strlen、strcmp
字符操作函数:大小写转换、字符分类
内存操作函数:memcpy、memmove、memset…
时间/日期函数:time
数学函数:pow、sqrt
其他库函数

使用库函数必须要包含它所对应的头文件
接下来我们来学习几个常用的库函数,掌握库函数的使用方法:

(1)strcpy()

char * strcpy ( char * destination, const char * source );

以上是strcpy()函数的函数原型,具体包含了:

1.返回类型:char*
2.函数名:strcpy
3.函数参数及其类型:两个参数,类型均为char* ,const是一个修饰符,具体含义之后会有总结

strcpy()函数的功能:将source内的字符串拷贝到destination字符数组中,包含‘\0’.
用以下代码来演示:

#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[20] = { 0 };
	char arr2[] = "hello world";
	printf("%s\n", arr1);//拷贝前arr1内为空,什么都没有
	//将arr2中的字符串拷贝到arr1中
	strcpy(arr1, arr2);//arr1就是destination,arr2就是source,都表示的是字符的首地址
	printf("%s\n", arr1);
	return 0;
}

具体的实现细节:
在这里插入图片描述


代码结果:
在这里插入图片描述


(2)memset()

void * memset ( void * ptr, int value, size_t num );

1.返回类型:void*
2.函数名:memset
3.函数参数及其类型:三个参数,类型分别为void* 、int、size_t

memset()函数的功能为:把ptr指向的这块空间的前num个字节的数据设置成value这个值
如下参数介绍:
在这里插入图片描述


返回值介绍:
在这里插入图片描述
简单来说就是设置内存,把一个字符串原本的内容覆盖掉,设置成我们想要的字符,比如将hello的前三个字符设置成字符*,如下代码:

#include <stdio.h>
#include <string.h>
int main()
{
	char arr[20] = "hello";
	printf("%s\n", arr);//设置前
	memset(arr, '*', 3);
	printf("%s\n", arr);//设置后
	return 0;
}

在这里插入图片描述
代码结果:
在这里插入图片描述


2.自定义函数

作为一个程序员,其实更重要的是自定义函数,我们需要自己设计函数名、参数、返回类型,需要我们自己完成函数体的具体功能,比如我们写一个函数能够找出两个数的最大值:

(1)找较大值

#include <stdio.h>
int get_Max(int a, int b)
{
	//一般方法
	/*if (a > b)
	{
		return a;
	}
	else
	{
		return b;
	}*/
	return a > b ? a : b;//比较大小,当a大于b返回a,否则返回b
}

int main()
{
	int a = 0;
	int b = 0;
	printf("请输入两个数:>");
	scanf("%d %d", &a, &b);
	int ret = get_Max(a, b);
	printf("%d较大\n", ret);
	return 0;
}

这里我们自己输入两个整数,将这两个整数作为函数的参数,返回两个数中的较大值,所以函数的参数类型为整型,返回类型也为整型,用到了两种基本的方法,具体可以参照注释理解。
以5和10进行验证:
在这里插入图片描述


(2)void的意义

void在不同的地方究竟有什么不同的含义呢?我们观察以下代码:

#include <stdio.h>
void test(void)
{
	printf("hello\n");
}

int main()
{
	test();
	return 0;
}

其实很容易理解,其中第一个void表示的是该函数执行完后什么都不需要返回,第二个void表示该函数不需要、不能传任何参数。


(3)交换两个数

我们输入两个整数,调用一个函数后交换这两个数:
错误代码:

#include <stdio.h>
void Swap(int m, int n)
{
	int tmp = m;
	m = n;
	n = tmp;
}

int main()
{
	int a = 0;
	int b = 0;
	printf("请输入两个数:>");
	scanf("%d %d", &a, &b);
	printf("交换前:a=%d b=%d", a, b);
	Swap(a, b);
	return 0;
}

我们将两个数传过去后,再打印两个数发现并没有改变,我们的思路没有问题,但却没有实现相应的功能。
其实在这里我们要注意一点:当函数调用的时候,实参传递给形参,形参是实参的一份临时拷贝,改变形参不影响实参。
我们来看看这段代码不成功的原因:
在这里插入图片描述
我们看到实际参数的两个数分别有各自的地址,形式参数同样有各自的地址,在调用这个函数的时候,只是把实际参数临时拷贝到形式参数中,Swap函数内部完成了两个数的交换,但实际参数并没有交换,因为这是两块独立的空间,互不干扰。
这时的结果为:
在这里插入图片描述


正确代码如下:

#include <stdio.h>
Swap(int* m, int* n)
{
	int tmp = *m;
	*m = *n;
	*n = tmp;
}

int main()
{
	int a = 0;
	int b = 0;
	printf("请输入两个数:>");
	scanf("%d %d", &a, &b);
	printf("交换前:a=%d b=%d\n", a, b);
	Swap(&a, &b);
	printf("交换后:a=%d b=%d\n", a, b);
	return 0;
}

我们注意到,在传参的时候,实参前加了个&,函数形参类型也变为了int*,这是因为在进行函数操作的时候我们需要改变参数的内容,如果只把两个数值传给Swap函数,在执行Swap函数时虽然交换了两个数的值,但当函数执行完的一瞬间,它所执行的一系列操作都会返回给系统,相当于交换后又被销毁了,所以我们需要传两个数的地址,用int型的指针来接收,在交换的时候,用(解引用符号)*来进行交换,这样,即使函数调用完后被销毁,两个数地址内的内容已经被交换,函数的功能也已经实现了。
我们看一下最后的结果:
在这里插入图片描述


三、求素数

求100-200间的素数

代码如下:

#include <stdio.h>
#include <math.h>
int is_prime(int m)
{
	int j = 0;
	for (j = 2; j <= sqrt(m); j++)
	{
		if (0 == m % j)
		{
			return 0;
		}
	}
	return 1;
}

int main()
{
	int i = 0;
	for (i = 100; i <= 200; i++)
	{
		if (is_prime(i))
		{
			printf("%d ", i);
		}
	}
	printf("\n");
	return 0;
}

我们用了一个循环来实现,从100-200之间,每个数都进行判断,函数的实现功能是:是素数,返回1,不是素数返回0。而素数的判断条件是:从2到这个数开平方,只要这个数能被整除,就不是素数,否则就是素数。
运行结果:
在这里插入图片描述


return和break:

按上述代码来看,return是直接返回,而break是跳出循环,return比break更直接、彻底。


四、判断闰年

找出1000-2000年是闰年的并打印出来

代码如下:

#include <stdio.h>
int is_leap_year(int m)
{
	if (0 == m % 4 && 0 != m % 100 || 0 == m % 400)
		return 1;
	else
		return 0;
}

int main()
{
	int i = 0;
	for (i = 1000; i <= 2000; i++)
	{
		if (is_leap_year(i))
		{
			printf("%d ", i);
		}
	}
	printf("\n");
	return 0;
}

同样使用了for循环来遍历1000-2000,逐一进行判断,而闰年的判定规则是:能被4整除且不能被100整除或能被400整除,是闰年返回1,否则返回0。
运行结果:
在这里插入图片描述


五、用函数完成二分查找

写一个函数,完成二分查找
1.找到了,返回下标
2.找不到,返回-1

代码如下:

#include <stdio.h>
int binary_search(int arr[], int k, int sz)
{
	int left = 0;
	int right = sz - 1;
	while (1)
	{
		int mid = (left + right) / 2;
		if (arr[mid] > k)
		{
			right = mid - 1;
		}
		else if (arr[mid] < k)
		{
			left = mid + 1;
		}
		else
		{
			return mid;//找到了,直接返回
		}
	}
	return -1;//找不到
}

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 7;
	int len = sizeof(arr)/sizeof(arr[0]);//获取元素个数
	int ret = binary_search(arr, k, len);
	if (-1 == ret)
	{
		printf("找不到!\n");
	}
	else
	{
		printf("找到了,下标是%d\n", ret);
	}
	return 0;
}

我们可以看出,这跟之前的简单二分查找思路基本一样,只是增加了一些参数。
运行结果:
在这里插入图片描述

sizeof的基本应用

我们先看一下下面的代码:

int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%d\n", sizeof(arr));//40
	printf("%d\n", sizeof(arr[0]));//4
	int len = sizeof(arr)/sizeof(arr[0]);//10

上面的sizeof(arr)是计算整个数组的大小,单位是字节,而sizeof(arr[0])计算的是数组中一个数的大小,单位是字节,arr[]是整型数组,内有10个元素,所以按字节来看就是40个字节,arr[0]是数组中一个元素的大小,一个整型大小为4个字节,所以我们可以通过sizeof(arr)/sizeof(arr[0])的方式来获取这个数组内的元素个数。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

叶落闲庭

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

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

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

打赏作者

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

抵扣说明:

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

余额充值