网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事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的内容
👉示例:
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
emset函数的作用:在ptr指向空间的
前num个字节内容改 我们指定
value`的内容
- 函数参数类型为:一个指向想被修改内存空间的地址、想修改成的指定内容(整型)、修改的内存空间大小
- 函数的返回类型:void*
➡️ memset
函数的工作原理:类似于memcpy
的工作原理,将前num个字节的内容修改成value的内容
👉示例:
[外链图片转存中…(img-XP8J2lqZ-1715851135180)]
[外链图片转存中…(img-hqT1mLCg-1715851135181)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新