C语言1. 字符串函数结尾+内存函数与它们的实现:任意类型拷贝的memcopy()+任意类型拷贝自己给自己的mymemmove()

本文详细介绍了C语言中的字符串处理函数strtok()及strerror()的使用方法,并深入探讨了内存操作函数memcpy()与memmove()的区别及其实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. strtok():以分割符分割字符串的函数

它会直接改变字符串内容,直接以分割符切割,把分隔符换为\0。所以一般操作都是对临时拷贝的内容做修改。
第一次调用,strtok()必须给参数s字符串,即对谁分割,往后将S设置为NULL,每次调用成功会返回指定被分割出片段的指针,它每次分割都会记录上次分割到了哪里,即给\0的位置。
利用for的巧妙写法:

int main()
{
	char arr[] = "liuzheng@123.net";
	char buf[30] = { 0 };
	const char* sep = "@.";
	strcpy(buf, arr);
	char* str = NULL;
	for (str = strtok(buf, sep); str != NULL; str = strtok(NULL, sep))
	{
		printf("%s\n", str);
	}
	return 0;
}

有人的疑问:它第n次调用,如何知道上次切割在哪儿,且为什么函数调用完释放了内存空间,还能找到上次的值?

它在内部创建了静态变量

2. strerror()返回错误信息库的函数

strerror(i):给不同码,对应不同错误信息
函数哪里执行出错,会把错误码放到全局变量errno错误码中,通过strerror(errno)可以拿到错误信息。

  • perror(”mystring“) 插入: 报错时会报你的字符串加系统对应错误

库中还有很多控制大小写,标点符号、图形字符的函数
putchar()打印字符 toupper()转为大写,tolower()转为小写

内存操作函数===

memcpy() 内存拷贝

· memcpy():(void* dest, const void* src, size_t count): void* 因为不知道拷贝的类型是什么,拷贝多少字节由于count参数决定
和strcpy()的区别就是这个可以拷贝任何类型,而strcpy()只能拷贝string

void* my_memcpy(void* dest, const void* src, size_t count)
{
	assert(dest && src);
	void* ret = dest;
	while (count--)
	{
		// 无类型的指针先强制转换,再解引用成char接收
		*(char*)dest = *(char*)src;
		dest = (char*)dest+1;
		src = (char*)src + 1;
	}
	return ret;
}

缺点是:不能把自己的内容拷贝给自己,因为这种实现方式,你把自己前面的字符串给后面的过程中,可能后面的字符就已经被覆盖掉了。

memmove()重叠内存拷贝,*自己拷贝给自己
  • 自己实现memmove(),主要需要考虑重叠的部分

拷贝部分dest和src位于不同位置,拷贝顺序也不同,如果全部按从前往后害怕后面需要拷贝的字符被前面的覆盖
请添加图片描述
拷贝顺序如下图示,src拷贝至dest
请添加图片描述

void* mymemmove(void* dest, const void*src, size_t count)
{
	assert(dest && src);
	void* ret = dest;
	if(dest<src)	// dest在左边,它的尾是src头,src头部先做赋值,就不会丢失,按src->顺序
	{
		// src前到后拷贝给dest
		while (count--)	// count是字节数,如果要拷贝4个整形,count会给20
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	// dest在src右边,即使要重合,但是重合部分是src的尾,按src -> 会让src的尾字符串丢失,按<-即可
	else
	{
		// 很巧妙的写法,不必在外面先赋值让各自指向最后
		while (count--)
		{
			*((char*)dest+count) = *((char*)src+count);
		}
	}
	return ret;
}

int main()
{
	int arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	// 自己给自己赋值
	mymemmove(arr1 + 2, arr1, 20);
	int i = 0;
	int sz = sizeof(arr1) / sizeof(arr1[10]);
	for (i = 0;i<sz; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

注意函数中,void 任意类型的函数,返回任意类型的ret,*
请添加图片描述

memcmp():可选择字节数做字典序比较

前面一样,但是后面第二个更大,返回-1
请添加图片描述

memset():以字节为单位设置内容

请添加图片描述
查看内存情况,&arr位置前20个全设置为0,不是把数组每个元素设0,而以字节为单位设置值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值