【C语言】字符函数&字符串函数&内存函数(下)[进阶篇_复习专用]

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 函数的返回类型为:char*【被分割出来的字符串的起始地址】

➡️strtok函数的工作原理:

  • strtok函数会在str指向的字符串中找到sep集合中的标记(分隔符),并用\0替代这个标记,返回一个被分割出的这段字符串的起始地址

❗有了以上了解,可以从中得出三个点:

  • 1️⃣strtok函数的第一个参数不为 NULL 时,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置【即保存了在这个标记符时的位置,就不往后找了】
  • 2️⃣strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记
  • 3️⃣如果字符串中不存在更多的标记,则返回 NULL 指针【即已经全部分割完的时候,就返回NULL

💥特别注意:

  • strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改

👉示例:

我们现在需要分割一个字符串:“My email address is:Dream_Y-ocean@优快云.com”

我们想将每个单词都分割出来

Eg:“My”、“email”、“address”……

我们便需要:

  • 分割字符集合:、:@.
  • 拷贝被分割的字符串:strcpy函数

这里是引用
但上面的代码会不会显得冗余呢🤔

我们能不能再优化一下呢~

答案是可以的!!!

  • 我们可以用for循环
    在这里插入图片描述

所以我们要好好利用好for循环哦~~

int main()
{

	char arr[] ="My email address is:Dream\_Y-ocean@优快云.com";

	char sep[] = " :@.";  
	//空格、:、. 、@

	char tmp[50] = { 0 };

	strcpy(tmp, arr);

	//优化前:
	/\*printf("%s\n", strtok(tmp, sep));

 printf("%s\n", strtok(NULL, sep));

 printf("%s\n", strtok(NULL, sep));

 printf("%s\n", strtok(NULL, sep));

 printf("%s\n", strtok(NULL, sep));
 
 printf("%s\n", strtok(NULL, sep));
 
 printf("%s\n", strtok(NULL, sep));\*/

	//优化后:
	for (char\* ret = strtok(tmp, sep); ret != NULL; ret = strtok(NULL, sep))
	{
		printf("%s\n", ret);
	}

	return 0;
}

**🥯Ⅲ.**总结

✨综上:就是字符串查找系列函数

➡️简单来说:就是以分割、查找…对字符串进行操作的函数

**🍞二.**错误信息报告函数

**🥐Ⅰ.**strerror函数

这里是引用

char \* strerror ( int errnum );

💡strterror函数的作用:将错误码这个整型里的错误码翻译成错误信息

  • 函数的参数为:int【即参数一般为errnno
    • errno相当于C语言设置的一个全局变量,用来专门存储全局的错误码
    • 即只要程序调用失败,程序就自动把错误吧存储到errno这个变量中
  • 函数的返回类型为:char*

👉示例:
在这里插入图片描述

**🥐Ⅱ.**perror函数

在这里插入图片描述

void perror ( const char \* str );

💡perror函数的作用:与strerror函数一样,将错误信息翻译出来,并打印出来

  • 函数的参数为:填入想打印的字符串
  • 函数的返回类型:void

➡️perror函数的工作原理:可以理解为perror将strerror函数内置在里面,并一并将其打印出来

  • 即程序调用失败的时候,perror先将程序员输入的字符串打印出来,然后程序自动加上并打印:,再把错误信息打印出来

👉示例:
在这里插入图片描述

**🥯Ⅲ.**总结

✨综上:就是错误信息报告函数

➡️简单来说:就是可以把错误信息打印出来的函数

**🍞三.**字符操作函数

**🥐Ⅰ.**字符分类函数

函数下列函数如果条件满足都返回[>0]
iscntrl判断字符是否为:任何控制字符
isspace判断字符是否为:空白字符【空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’】
isdigit判断字符是否为:十进制数字 0~9
isxdigit判断字符是否为:十六进制数字【包括所有十进制数字,小写字母a~f,大写字母A ~ F】
islower判断字符是否为:小写字母a~z
isupper判断字符是否为: 大写字母A~Z
isalpha判断字符是否为:字母az或AZ
isalnum判断字符是否为:字母或者数字,a~ z,A~ Z,0~9
ispunct判断字符是否为:标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph判断字符是否为:任何图形字符
isprint判断字符是否为:任何可打印字符,包括图形字符和空白字符

**🥐Ⅱ.**字符转换函数

函数下列函数会将字符进行转换
tolower将字符转换为小写
toupper将字符转换为大写

**🥯Ⅲ.**总结

✨综上:就是字符操作函数

➡️简单来说:就是对字符进行操作判断的函数

**🍞四.**内存操作函数

**🥐Ⅰ.**memcpy函数

在这里插入图片描述

void \* memcpy ( void \* destination, const void \* source, size\_t num );

💡memcpy函数的作用:通过一个一个字节的方式去实现内存拷贝

  • 函数参数类型为:拷贝目标的起始地址、拷贝源的起始地址、拷贝的数据大小【单位:字节】
  • 函数返回类型为:void*

➡️memcpy函数的工作原理:对字节实现类似strcpy函数的操作,一个一个字节的拷贝

❗有了以上了解,可以从中得出一个点:

  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置

💥特别注意:

  • 1️⃣这个函数在遇到 \0 的时候并不会停下来【不像strcpy函数】
  • 2️⃣如果source和destination空间上有任何的重叠,复制的结果都是未定义的【即如果空间重叠的时候会影响拷贝】

👉示例:

初始化数组,想将数组内的1,2,3,4,5替换到3,4,5,6,7的位置上
在这里插入图片描述
拷贝后:
在这里插入图片描述
却发现想拷贝的数据被修改了❗

💫综上:memcpy的拷贝应避免重叠的内存空间

👉函数的模拟实现:

思路:

  • 因为函数是用void*指针去接收地址的,所以传什么类型都可实现memcpy函数的通用
  • 函数的实现大致与strcpy函数的实现一致,仅仅细微不同
void\* my\_memcpy(void\* dest, const void\*src, size\_t num)   //size\_t == unsigned int == 无符号
//设置成 void\*的返回值,即 可以快速返回 dest的初始地址
//更快的访问到 内容改变的空间
{
	assert(dest && src);

	void\* ret = dest;

	while (num--)
	{
		\*(char\*)dest = \*(char\*)src;

		dest = (char\*)dest + 1;  
		//不难直接 dest++,因为 dest的类型为 void\*,加1电脑不知道应该加多少
		src = \*(char\*)src + 1;

		//\*(char\*)dest++ = \*(char\*)src++; 
		//不能这样些,因为 (char\*)这种 强制类型转换 只是一种临时的状态
		//在 ++的时候就不起作用了,状态效果已经过去了
		//所以对于 void\*来说++不知道加多少
		//且 ++ 的优先级 > 强制类型转换,所以 这样写不行
	}

	return ret;
}

**🥐Ⅱ.**memmove函数

在这里插入图片描述

void \* memmove ( void \* destination, const void \* source, size\_t num );

💡memmove函数的作用:与memcpy函数的功能一样,但此函数可以实现拷贝重叠的空间

  • 函数参数类型为:拷贝目标的起始地址、拷贝源的起始地址、拷贝的数据大小【单位:字节】
  • 函数返回类型为:void*

❗有了以上了解,可以从中得出两个点:

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

👉函数的模拟实现:

思路:

  • void*强制转换类型成char*可以将函数实现更多操作更多类型、普适性更强

【Eg:只强制类型转换成int*那一次性就要访问4个字节的内容,如果想拷贝1个字符(即1字节),就会把本来不想拷贝的也拷贝了】

这里是引用

void\* my\_memmove(void\*dest, const void\*src, size\_t num)
{
	assert(dest && src);

	void\*ret = dest;

	if (dest < src)
	{
		//src从前向后拷贝[前->后]
		//从前到后的方法 就是 memcpy的方法
		while (num--)
		{
			\*(char\*)dest = \*(char\*)src;
			src = (char\*)src + 1;
			dest = (char\*)dest + 1;
		}
	}
	else
	{
		//后->前
		while (num--)
		{
			\*((char\*)dest + num) = \*((char\*)src + num);
		}
	}
	return ret;
}


**🥐Ⅲ.**memcmp函数

这里是引用

int memcmp ( const void \* ptr1, const void \* ptr2, size\_t num );

💡memcmp函数的作用:与strcmp函数的功能一样,只不过是对所有类型都进行一个字节一个字节的比较

➡️ memcmp函数的工作原理:与strcmp的原理一样~只不过是对内存进行比较

❗了解以上知识后,函数的返回值之所以为整型,是因为:
在这里插入图片描述

  • 1️⃣若 ptr1<ptr2,则返回 <0的数字【在VS编译器下,返回值为-1
  • 2️⃣若 ptr1=ptr2, 则返回0【在VS编译器下,返回值为0
  • 3️⃣若 ptr1>ptr2, 则返回 >0的数字【在VS编译器,返回值为1

**🥐Ⅳ.**memset函数

这里是引用

void \* memset ( void \* ptr, int value, size\_t num );

💡memset函数的作用:在ptr指向空间的前num个字节内容改 我们指定value的内容

  • 函数参数类型为:一个指向想被修改内存空间的地址、想修改成的指定内容(整型)、修改的内存空间大小
  • 函数的返回类型:void*

➡️ memset函数的工作原理:类似于memcpy的工作原理,将前num个字节的内容修改成value的内容

👉示例:

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

emset函数的作用:在ptr指向空间的前num个字节内容改 我们指定value`的内容

  • 函数参数类型为:一个指向想被修改内存空间的地址、想修改成的指定内容(整型)、修改的内存空间大小
  • 函数的返回类型:void*

➡️ memset函数的工作原理:类似于memcpy的工作原理,将前num个字节的内容修改成value的内容

👉示例:

[外链图片转存中…(img-XP8J2lqZ-1715851135180)]
[外链图片转存中…(img-hqT1mLCg-1715851135181)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值