字符串和内存函数(2)

2023-12-14 00:49:33

字符串函数?

strtok函数

strtok函数的规则:

? ? ? ? ?1.参数1是指定一个字符串,它包含0个或多个由参数2字符串中一个或多个分隔符分割的标记

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

? ? ? ? ?3.strtok函数找到参数1的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可以修改。)

? ? ? ? ?4.strtok函数的第一个参数不为NULL,函数将找到参数1中第一个标记,strtok将保存它在字符串中的位置

? ? ? ? ?5.strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记

? ? ? ? ?6.如果字符串中不存在更多的标记,则返回NULL指针。

结合下面的例子:

当执行strtok函数后,如下图:

?实际上,我们切割时并不清楚需要切割几次,因此我们需要通过循环进行切割

分析:很明显,第一次打印abcd。第二次打印ef是因为,参数1为NULL,根据规则,它会从上一次保存的位置继续查找标记,第三次打印也是如此。?

strerror函数

strerror是将错误码翻译成错误信息,返回错误信息的字符串的起始地址。

strerror里的参数是整形,上面是各种类型的错误信息。?

C语言中使用库函数的时候,如果发生错误,会将错误码放在errno的变量中,errno是一个全局变量,可以直接使用的。如上图,我们暂时不用管别的,我们只需要知道strerror里的errno存放错误码即可。

这里,我们再简单介绍下另一个类似的函数perror

perror函数是直接打印错误码所对应的错误信息。perror==printf+strerror。

我们简单修改下上面的代码,发现:perror里面的内容,是我们自定义的信息,在打印完我们的信息后,他会自动在后面补上:号然后加上错误信息。因此也可以知道,perror的好处就是比较方便,会自动识别错误信息。但是他也会自动打印出错误信息。?

字符函数

字符分类函数

字符分类函数有如下:

?因为每个函数的使用方式基本相同,我们就举一个来简单说明:

当我们使用上面的函数时,我们需用引用头文件<ctype.h>,如果函数内为真则返回不等于0的数,如果为假,则返回0。?

字符转换函数

字符转换函数有tolower和toupper。他们的返回值和参数都是int,即字符的ASCII值。如下图,如果参数是小写则转换成大写,如果是大写,则不变。

内存函数

memcpy函数

memcpy函数跟strcpy函数有相似之处,不过memcpy可以拷贝任何类型。mencpy的参数1是目标空间,参数2是原始空间,参数3是拷贝的个数,单位是字节,这里指的是把arr2的前5个元素拷贝到arr1中(因为一个整形是4个字节,5个就是20个字节)。?

void* my_memcpy(void* dest, const void* src, size_t sz)
{
	assert(dest && src);
	while (sz--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
}

上方是memcpy的模拟实现。

?

如上图,如果我们想把前五个数(1,2,3,4,5),从第3个数开始的5个数(3,4,5,6,7)拷贝过去,我们希望得到的结果是{1,2,1,2,3,4,5,8,9,10}。可是最后的结果却不是。这是因为在拷贝的重叠部分被改变了。

前面的拷贝是不重叠内存的拷贝,可以用memcpy。如果是重叠内存的拷贝,可以用memmove函数。

memmove函数

memmove函数的返回值和参数与memcpy的一模一样,如上图,使用它就能达到我们所想要的结果。?

void* my_memmove(void* dest, const void* src, size_t sz)
{
	assert(dest && src);
	void* ret = dest;
	if (dest < src)
	{
		//前->后
		int i = 0;
		for (i = 0; i < sz; i++)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		//后->前
		while (sz--)
		{
			*((char*)dest + sz) = *((char*)src + sz);
		}
	}
	return ret;	
}

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr+2, arr, 20);
	int i;
	for (i = 0; i < 10; i++)
		printf("%d ", arr[i]);
	return 0;
}

上方是模拟memmove函数的实现。

分析: 当原始空间的地址大于目标空间地址时,我们需要从前往后拷贝原始字符串到目标空间。

否则,我们就需要从后往前进行拷贝,这样就不会因为重叠而导致结果达不到预期。while循环中,sz--,起初sz是20,进入循环内变成19,强转后的dest+sz刚好指向最后一个字节,就能从后往前进行拷贝。

memset函数

memset函数是用来设置内存的,以字节为单位进行设置。如上图,参数1是起始地址,参数2是要设置的内容,参数3是设置的字节个数。

memcmp函数

memcmp函数与strcmp函数类似,不过strcmp函数只能进行字符串的比较,memcmp是内存块的比较,可以比较任意类型的数据。如下图:

参数1和参数2与strcmp的一样,参数3指比较前n个字节个数的数据,因为int占4个字节,比较前3个元素,大小相同则返回0。

如上图,我们比较大小的时候,不能单纯比较数字,而要看他们在内存中是怎样的,这样才能得出正确结果。?

文章来源:https://blog.csdn.net/qinjh_/article/details/134812378
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。