库函数的介绍、使用、模拟实现

目录

字符串库函数;

1.strlen;

简要介绍:

使用:

模拟实现:

2.strcpy;

简要介绍:

使用:

模拟实现:

3.strcat;

简要介绍:

使用:

模拟实现:

4.strcmp;

简要介绍:

使用:

​编辑模拟实现:

5.strstr;

简要介绍:

使用:

模拟实现:

6.strtok;

简要介绍:

使用:

内存库函数;

1.memcpy

简要介绍:

使用:

模拟实现:

2.memmove

简要介绍:

模拟实现:

3.memcmp;

简要介绍:

使用:


字符串库函数;

1.strlen;

简要介绍:

size_t strlen ( const char * str )。

字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )

参数指向的字符串必须要以 '\0' 结束。

注意函数的返回值为size_t,是无符号的。

使用:

在strlen后面输入字符串地址或者字符串;

代码举例:

#include<string.h>
#include<stdio.h>
int main()
{
	char arr[] = "abcde";
	int sz = sizeof(arr) / sizeof(arr[0]);
	size_t ret = strlen(arr);
	printf("%u\n", ret);
	return 0;
}

运行结果:

模拟实现:

代码1(指针-指针):

size_t mystrlen(const char* x,const char* y)
{
	
	return y-x;
}
int main()
{
	char arr[] = "abcde";
	int sz = sizeof(arr) / sizeof(arr[0]);
	size_t ret = mystrlen(arr,arr+sz-1);
	printf("%u\n", ret);
	return 0;
}

代码1分析:

这里主要使用了指针-指针=两指针之间的元素个数;因为arr是字符串,所以里面的元素包含\0,函数传参的时候正好传首元素的地址和最后一个元素后面的地址,两地址相减就得到整个字符串的元素个数;

运行结果:

代码2:

size_t mystrlen(const char* x)
{
	int count = 0;
	while (*x != '\0')
	{
		count++;
		x++;
	}
	return count;
}
int main()
{
	char arr[] = "abcde";
	int sz = sizeof(arr) / sizeof(arr[0]);
	size_t ret = mystrlen(arr, arr + sz - 1);
	printf("%u\n", ret);
	return 0;
}

代码2分析(计数器):

把首元素地址传过去,解引用看是不是\0,一直到\0,每次不是\0就加1,最后返回计数器;

运行结果:

代码3(递归):

size_t mystrlen(const char* x)
{
	if (*x != '\0')
	{
		x++;
		return 1+mystrlen(x);
	}
	{
		return 0;
	}
	
}
int main()
{
	char arr[] = "abcde";
	int sz = sizeof(arr) / sizeof(arr[0]);
	size_t ret = mystrlen(arr);
	printf("%u\n", ret);
	return 0;
}

代码3分析:

这里的思想是只要解引用不是\0,就把地址加1,返回1+函数(新地址),最后找到\0,返回最终的长度;

运行结果:

2.strcpy;

简要介绍:

源字符串必须以 '\0' 结束。

会将源字符串中的 '\0' 拷贝到目标空间。

目标空间必须足够大,以确保能存放源字符串。

目标空间必须可变。

使用:

char * strcpy ( char * destination, const char * source );
#include<string.h>
int main()
{
	char arr1[20] = "xxxxxxxxxxxxxxxxxx";//目标空间必须可变,不能是常量字符串;char* arr="xxxxxxxxxxxxxxxxxxxxxxx";
	char arr2[20] = "abiuwdfakf";//源字符串必须以 '\0' 结束。否则会出现错误;
	strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

分析:

将arr2中的内容全部拷贝到arr1中,最后再打印出arr1;

运行结果:

模拟实现:

代码:

#include<stdio.h>
#include<assert.h>
char* mystrcpy(const char* arr2, char* arr1)
{
	assert(arr1!=NULL);
	assert(arr2!= NULL);
	char* ret = arr1;
	while (*arr2 != '\0')
	{
		*arr1 = *arr2;
		arr1++;
		arr2++;
	}
	*arr1 = *arr2;
	return ret;
}
int main()
{
	char arr1[] = "hello guys";
	char arr2[] = "xxxxx";
	
	/*printf("%s\n", mystrlen(arr2, arr1));*///利用函数返回值实现链式访问;
	mystrcpy(arr2, arr1);
	printf("%s\n",arr1);
	return 0;
}

代码分析:

传过去两个字符串的地址,开始解引用,只要不是\0,就赋给新的字符串,两个地址同时++,直到\0,跳出循环,将\0赋给新的字符串;返回一开始存储的地址;

运行结果:

3.strcat;

简要介绍:

追加字符串,在字符串\0位置开始追加新的字符串;

使用:

代码:

#include<string.h>
int main()
{
	char arr[20] = "hello";
	char arr1[] = "world";
	strcat(arr, arr1);
	printf("%s\n", arr);
	return 0;
}

代码分析:

在arr的\0位置开始追加字符串arr1,最后的结果是helloworld;

运行结果:

模拟实现:

代码:

#include<assert.h>
#include<stdio.h>
char* mystrcat(char* arr, const char* arr1)
{
	assert(arr);
	assert(arr1);
	char* ret = arr;
	while (*arr)
	{
		arr++;
	}
	while (*arr++ = *arr1++);//当自己给自己追加,会把\0的位置给赋值成h,会把\0覆盖,永远找不到\0;
	return ret;
}
int main()
{
	char arr[20] = "hello";
	char arr1[] = "world";
	printf("%s\n", mystrcat(arr, arr1));
	return 0;
}

代码分析:

把两个字符串的地址传给函数,先存下第一个字符串的源地址;开始对字符串1的内容解引用,不是\0就+1,一直找到\0,从这个位置开始把字符串2的值赋给字符串1,每赋完一个就+1,一直到字符串2的\0,最后返回字符串1的源地址;

运行结果:

4.strcmp;

简要介绍:

第一个字符串大于第二个字符串,则返回大于 0 的数字;
第一个字符串等于第二个字符串,则返回 0;
第一个字符串小于第二个字符串,则返回小于 0 的数字;
比较对应字符的大小,当比到\0==\0时停止;

使用:

代码:

#include<string.h>
int main()
{
	char arr1[] = "adc";
	char arr2[] = "acd";
	
	printf("%d\n", strcmp(arr1, arr2));
	return 0;
}

代码分析:

因为d在c后面,所以返回>0;

运行结果:


模拟实现:

代码:

#include<stdio.h>
#include<string.h>
int mystrcmp(const char* arr1, const char* arr2)
{
	while (*arr1 == *arr2)
	{
		if (*arr1=='\0')
		{
			return 0;
		}
		arr1++;
		arr2++;
	}
	if (*arr1 > *arr2)
	{
		return 1;
	}
	else if (*arr1 < *arr2)
	{
		return -1;
	}
}

int main()
{
	char arr1[] = "adc";
	char arr2[] = "acd";
	
	printf("%d\n", mystrcmp(arr1, arr2));
	return 0;
}

代码分析:

传过去两个字符串地址,开始逐对比较,如果第一个就不相等,判断大小,返回值;如果第一个相等,地址++,一直到找到不相等的,如果到最后\0的位置还相等,那就返回0;

运行结果:

5.strstr;

简要介绍:

在一个字符串里找另外一个字符串,即看另外一个字符串是不是大字符串的子串,如果有,返回该位置的地址;

使用:

代码:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "uihfaposfrf";
	char arr2[] = "pos";
	char*ret=strstr(arr, arr2);//在arr中找arr2,返回arr2在arr中出现的地址;
 if(ret!=NULL)
 {
	printf("%s\n", ret);
 }
	return 0;
}

代码分析:

在arr里找arr2,最后返回地址,打印出arr中arr2及他后面的内容;

运行结果:

模拟实现:

代码:

#include<stdio.h>
char* mystrstr(const char* arr, const char* arr2)
{
	char* x1 = arr;
	char* s1 = x1;
	char* s2 = arr2;
	while (*x1)
	{
		char* s1 = x1;
		char* s2 = arr2;
		while (*s1&&* s2&&* s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return x1;
		}
		else {
			x1++;
		}
	}
	return NULL;
}
int main()
{
	char arr[] = "appos";
	char arr2[] = "pos";
	char* ret = mystrstr(arr, arr2);//在arr中找arr2,返回arr2在arr中出现的地址;
	printf("%s\n", ret);
	return 0;
}

代码分析:

传过去两个字符串地址,先存储下来,把字符串2的内容与字符串1比较,如果相等,则字符串1的地址++,一直到有相等的出现,出现以后再从相等的位置开始往后比较每一位,如果当中又出现不相等,且不是\0的位置,字符串1地址++;如果那个不相等的地址指向\0,则返回字符串1的地址;

运行结果:

6.strtok;

简要介绍:

char*strtok ( char*str, constchar*sep );

sep参数是个字符串,定义了用作分隔符的字符集合。

第一个参数指定一个字符串,它包含了 0 个或者多个由 sep 字符串中一个或者多个分隔符分割的标记。

strtok 函数找到 str 中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:
strtok 函数会改变被操作的字符串,所以在使用 strtok 函数切分的字符串一般都是临时拷贝的内容并且可修改。)
strtok 函数的第一个参数不为 NULL ,函数将找到 str 中第一个标记, strtok 函数将保存它在字符串中的位置。
strtok 函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标 记。
如果字符串中不存在更多的标记,则返回NULL;

使用:

代码:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "cuofiaiw&noiwd+jooqd%opw@niovnse owo?wdc";
	char arr2[50] = {0};
	strcpy(arr2, arr);
	char sep[] = "&%+@ ?";
	char* ret;
	for (ret = strtok(arr2, sep);ret != NULL;ret = strtok(NULL, sep))//找到里面的字符,改为\0,返回地址;除了第一次使用arr2,其他可以使用NULL,因为strtok有记录功能;
	{
		printf("%s\n", ret);
	}
	return 0;
}

代码分析:

每次找到相应符号,转为\0,打印,再使用,从\0后面的地址开始找,如此循环,找出各个符号之间的字符串内容;

运行结果:

内存库函数;

1.memcpy

简要介绍:

void* memcpy ( void* destination , const void* source , size_t num );
函数 memcpy source 的位置开始向后复制 num 个字节的数据到 destination 的内存位置。
如果 source destination 有任何的重叠,复制的结果都是未定义的。
遇到\0也不会停下;

使用:

代码:

#include<stdio.h>
#include<string.h>
int main()
{
	int arr[] = { 1,2,4,5,6,7,8 };
	int arr1[20] = { 0 };
	memcpy(arr1, arr, 20);//20 表示要拷贝的字节;
	int i = 0;
	while (i<20)
	{
		printf("%d ", arr1[i]);
		i++;
	}
	return 0;
}

代码分析:

拷贝20个字节,即五个整形,所以是arr1的前五个元素;

运行结果:

模拟实现:

代码:

#include<assert.h>
#include<stdio.h>
void* my_memcpy(void* arr1, void* arr, size_t num)
{
	void* ret = arr1;
	assert(arr1 && arr);
	while (num--)
	{
		*(char*)arr1 = *(char*)arr;
		arr1 = (char*)arr1 + 1;
		arr = (char*)arr + 1;
		
	}
	return ret;
}
int main()
{
	int arr[] = { 1,2,4,5,6,7,8 };
	          // 01 00 00 00 02 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00
	int arr1[20] = { 0 };
	my_memcpy(arr1, arr, 21);//22 表示要拷贝的字节;
	int i = 0;
	while (i < 20)
	{
		printf("%d ", arr1[i]);
		i++;
	}
	return 0;
}

代码分析:

因为是一个字节一个字节拷贝,所以都转为char*类型的指针,这样可以一个字节一个字节的跳动;

运行结果:

2.memmove

简要介绍:

memcpy 的差别就是 memmove 函数处理的源内存块和目标内存块是可以重叠的。
如果源空间和目标空间出现重叠,就得使用 memmove 函数处理。

模拟实现:

代码:

#include<stdio.h>
#include<string.h>
#include<assert.h>
void* mymemmove(void* dest, void* source, size_t num)
{
	void* ret = dest;
	assert(dest && source);
	while (num--)
	{
		if (dest < source)
		{
			*(char*)dest = *(char*)source;
			dest = (char*)dest + 1;
			source = (char*)source + 1;
		}
		else
		{
			*((char*)dest + num) = *((char*)source + num);//加到第19个字节;
		}
	}
	return ret;
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9 ,0 };
	/*memmove(arr, arr + 2, 20);*/
	/*memmove(arr+2, arr, 20);*/
	mymemmove(arr, arr+2, 20);
	int i = 10;
	for (i = 0; i < 10;i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

代码分析:

memmove的特点是重叠的部分也可以使用,所以重叠这里分为目标地址和源地址的位置关系,如果目标地址在源地址左边,那么从目标地址的首地址开始赋值;如果在右边,那么从目标地址往后的最后一个元素开始赋值;

运行结果:

3.memcmp;

简要介绍:

int memcmp ( const void * ptr1, const void * ptr2, size_t num );比较ptr1和ptr2前num个字节;

使用:

代码:

#include<stdio.h>
#include<string.h>
int main()
{
	int arr[] = { 1,2,1,4,5,6 };
	int arr1[] = { 1,2,257 };
	int ret=memcmp(arr, arr1, 9);
	printf("%d\n", ret);
	return 0;
}

代码分析:

比较arr和arr1前9个字节,因为257和1的第一个字节内容相同,所以应该返回1;

运行结果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值