C语言之字符串函数和内存函数

目录

前言

字符串函数

 strlen

strlen的模拟实现:

strcpy

strcpy的模拟实现

strcat

 strcat的模拟实现

strcmp

strcmp的模拟实现:

 内存函数

memcpy

memcpy的模拟实现

memmove

memcmp

memset

总结


前言

    之前为大家分享了函数相关的知识点,当时讲述的函数的知识点大多都是自定义函数,而今天为大家分享的就是C语言库中的一些函数,何为库函数,库函数就是C语言自身封装的一些函数,我们可以直接通过引入头文件的形式对这些函数进行使用,就比如我们在写C语言程序之前,好多小伙伴都直接引入了#include<stdio.h>,很多人不知道为什么,其实这便是引入了库函数,因为我们在写程序时,会使用到scanf和printf函数,这两个函数就是C语言中的库函数,所以我们要对其引入头文件。这期,主要为大家讲述的就是C语言中比较重要的一些库函数,以及如何通过自己的方法去实现这些库函数。

字符串函数

 strlen

这个函数想必大家都不陌生吧,这个函数我们之前是讲到过的,先来看一段代码:

#include<stdio.h>
int main(){
	char ch1[20] = "123456789";
	int len = strlen(ch1);
	printf("%d\n",len);
	return 0;
}

我们知道strlen是求字符串长度的一个库函数,但是我们通过运行结果发现,ch1这个字符串的长度是9,我们知道一个字符串的末尾是有一个'\0'作为字符串结束的标志的,'\0'本身也是一个字符,如此,打印的结果应该是10,但是我们打印的结果确是9,这就证明,strlen这个函数在求字符串的长度时,只求'\0'之前的所有字符串的长度,'\0'是不用记作长度的。

strlen的模拟实现

#include<stdio.h>
int my_strlen(const char* dest) {
	int count = 0;
	while (*dest++) {
		count++;
	}

	return count;
}
int main(){
	char ch1[20] = "123456789";
	int len = strlen(ch1);
	printf("%d\n",len);
	int len2 = my_strlen(ch1);
	printf("%d", len2);
	return 0;
}

不难发现,运行结果是相同的。上述的模拟实现只是一种方式,还有其它的方法,递归的方法实现在之前的递归那期有讲到,感兴趣的小伙伴可以自行查看。

strcpy

这玩意儿是干嘛的,先说结论,它是字符串拷贝函数,就相当于将一个字符串的内容复制粘贴到了另一个字符串。来吧,展示:

#include<stdio.h>
int main()
{
	char ch1[20] = "zhangsan";
	char ch2[20] = "lisi";
	printf("%s\n",ch1);
	strcpy(ch1, ch2);
	printf("%s\n",ch1);
	return 0;
}

运行结果如下:

不难发现,我们已经将ch2的值拷贝到了ch1

注意:strcpy进行拷贝时,依旧是将'\0'之前的字符串进行拷贝。在进行拷贝时,目标字符串的空间应该足够大,起码得等于源字符串。

strcpy的模拟实现

直接上代码:

char* my_strcpy(char* dest, const char* src) 
{
	char* ret = dest;
	while (*dest++ = *src++) 
	{
		;
	}
	return ret;
}
int main()
{
	char ch1[10] = "zhangsan";
	char ch2[10] = "wangmazi";
	printf("%s\n",ch1);
	my_strcpy(ch1,ch2);
	printf("%s\n",ch1);
	return 0;

}

通过运行结果不难发现,我们模拟实现的函数也实现了字符串的拷贝。

strcat

这个函数是用来做字符串追加的,字符串追加是什么意思呢?很简单,就是在一个字符串的后面追加一些字符串。直接上代码:

int main()
{
	 char ch1[10] = "xiongda";
	 char ch2[10] = "xionger";
	 printf("%s\n", ch1);
	 strcat(ch1,ch2);
	 printf("%s\n",ch1);
	return 0;
}

运行结果如下:

通过运行结果不难发现strcat的用法。

注意:strcat的追加时,源字符串必须以'\0'结束

 strcat的模拟实现

直接上代码:

char* my_strcat(char* dest,const char* src)
{
	char* ret = dest;
	while (*dest)
	{
		dest++;
	
	}
	while (*dest++ = *src++)
	{
		;
	}
	return ret;

}
int main()
{
	char ch1[10] = "zhangsan";
	char ch2[20] = "lisi";
	printf("%s\n",ch1);
	my_strcat(ch1, ch2);
	printf("%s\n",ch1);
	return 0;
}

 

我们的自定义函数也实现了strcat的模拟。

strcmp

用于比较字符串的内容,注意:与字符串的长度无关,只与字符所对应的asc码的大小有关

直接上代码:

int main() 

{
	char ch1[20] = "aaaaaaaaaaaa";
	char ch2[20] = "bbb";
	int b = strcmp(ch1, ch2);
	if (b < 0)
	{
		printf("ch1 < ch2");

	}
	else if (b == 0) 
	{
		printf("ch1 == ch2");
	}
	else 
	{
		printf("ch1 > ch2");
	}
	return 0;
}

大家先猜测一下,这两个字符串,哪个字符串的长度比大一点,大部分小伙伴第一次一定会认为是第一个ch1较大,但是事实是这样吗?我们直接看运行结果;

运行结果进一步验证了我们的猜想是错误的,这里我们需要注意:

1.strcmp函数是内容比较函数,比较的是字符串的内容的大小,并非是字符串的长度。

2.strcmp函数的返回值是一个整型,返回的数有三种类型:>0,=0,<0,每一种分别对应了不同的大小关系。

3.strcmp的函数的比较是从字符串第一个不想同的字符开始比较的,比如上述的ch1和ch2,因为它们的字符都不相同,所以是从第一个字符开始进行比较的,因为a的asc码是小于b的asc码的,所以会返回一个小于零的数,所以ch1<ch2

strcmp的模拟实现

代码如下:

int my_strcmp(const char* s1, const char* s2)
{
	assert(s1 && s2);

	while (*s1 == *s2)
	{
		if (*s1 == '\0')
			return 0;
		s1++;
		s2++;
	}

	return *s1 - *s2;
}

 以上四个便是我们常见的字符串函数,但是上述函数有一个缺点,就是不管字符串有多长都会拿去拷贝,连接和比较,没有空间的限制,这样就会导致内存溢出的情况,因此我们又引入了以下的函数;strncpy,strncat,strncmp这些函数就保证了内存不会溢出,因为它们规定了字符的个数。

这里只给出一个实例,其它的都是类似的:

比较前四个字符:

int main()
{
	char arr1[] = "abcde";
	char arr2[] = "abcft";
	int ret = strncmp(arr1, arr2, 4);
	printf("%d\n", ret);
	return 0;
}

 内存函数

我们为什么要引入内存函数呢?比如上面的字符串拷贝函数,它只能在字符串之间进行拷贝,如果我们要实现整型数组的拷贝,strcpy肯定是行不通的,所以在此基础上我们引入了内存函数,我们通过内存函数,可以实现其它类型数组的拷贝。

memcpy

与strcpy功能大致类似,内存拷贝函数,可以拷贝任何类型的数据,是以字节为单位进行拷贝的。

int main()

{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	int i = 0;
	for (i = 0; i < 20; i++) {

		printf("%d ", arr2[i]);

	}
	printf("\n");
	memcpy(arr2, arr1, 40);
	
	for (i = 0; i < 20; i++) {

		printf("%d ",arr2[i]);

	}
	printf("\n");
	return 0;
}

memcpy的模拟实现

void* my_memcpy(void* dest, const void* src, size_t count)
{
	void* ret = dest;
	assert(dest && src);

	while (count--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

通过运行结果不难发现,实现了整型的拷贝。

memmove

memmove也可以实现内存拷贝,与memcpy的区别就是可以实现重叠的拷贝,比如说我们要把一个整型数组的第1和第2个元素拷贝到第2个和第3个元素的位置上去,此时memcpy是无法实现这个功能的,但是memmove是可以实现这些功能的。

比如:

int main()

{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	int i = 0;
	for (i = 0; i < 10; i++) {

		printf("%d ", arr1[i]);

	}
	printf("\n");
	memmove(arr1+1, arr1, 8);

	for (i = 0; i < 10; i++) {

		printf("%d ", arr1[i]);

	}
	printf("\n");
	return 0;
}

memcmp

内存比较,与字符串比较,只不过比较的是某个字节的内容:

int main()
{
	int arr1[] = { 1,2,3,4,5 };//01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 ...
	int arr2[] = { 1,2,3,6,6 };//01 00 00 00 02 00 00 00 03 00 00 00 06 00 00 00 ...

	int ret = memcmp(arr1, arr2, 13);

	printf("%d\n", ret);

	return 0;
}

 上述代码比较的是第13个字节的内容,4<6,所以返回值应该是一个负数。

结果确实返回了一个负数。

memset

memset的作用是将前所少个字节的内容设置为多少。

int main() {
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%d\n", arr1[4]);
	memset(arr1,5,20);
	printf("%d\n",arr1[4]);



}

 上述代码就是将数组的前20个字节全部设置为5

进行调试,截图如下:

我们发现,前20个字节确实被改成了5

总结

以上便是这期的所有内容,当然还有其它的字符串函数和内存函数,这期只是讲到了一些比较重要的函数,我们要知道strcpy和memcpy的区别,strcpy是实现字符串拷贝的,而memcpy可以实现各种类型数据的拷贝,要知道memcpy和memmove的区别,memcpy通常用于不重重叠的拷贝,而memmove通常用于重叠的拷贝,但是memmove也可以用于不重叠的拷贝,也就是说,memmove可以实现memcpy实现的所以功能,一般情况下,只要遇到了内存拷贝的问题,无脑使用memmove就行。

本期内容到此结束^_^

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

棠~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值