个人主页:_麦麦_

今日名言:生活不能等待别人来安排 ,要自己去争取和奋斗;而不论其结果是喜是悲,但可以慰藉的是,你总不枉在这世界上活了一场。有了这样的认识,你就会珍重生活,而不会玩世不恭;同时,也会给人自身注入一种强大的内在力量。——《平凡的世界》

目录

一、前言

二、正文

4.错误信息报告

♥错误信息

♥strerror

♥fopen(额外赠送)

5.字符分类函数

6.字符转换【只针对字母】

♥tolower

♥toupper

7.内存操作函数

♥memcpy

♥ memmove

♥memcmp函数

♥memset

三、结语


一、前言

不知不觉中,关于字符函数和字符串函数的讲解步入了尾声,在今天这一部分我们主要讲解三大类:错误信报告、字符操作和内存操作函数。大家一定要搬来小板凳好好听讲呀!为小伙伴们送上迟到的元宵节快乐。

二、正文

4.错误信息报告

♥错误信息

在正式开始介绍strerror在这个函数之前,我们需要先对错误码错误信息有一个大致的了解。

C语言的库函数在运行的时候,如果发生错误,就会将错误码存在一个变量中,这个变量是:errno,而这些错误码通常是一些数字 :1、 2、 3、 4、 5。

而这些错误码就分别对应着错误信息,那么我们该如何翻译错误码呢,这就用到了strerror函数。

♥strerror

char * strerror(int errnum);

●功能:用于返回错误码所对应的错误信息

●包含的头文件:

//strerror函数使用演示#include #include #include int main(){printf("%s\n", strerror(0));printf("%s\n", strerror(1));printf("%s\n", strerror(2));printf("%s\n", strerror(3));printf("%s\n", strerror(4));printf("%s\n", strerror(5));return 0;}

那么在什么场景下我们会用到strerroe函数,就字面意义而言,就是当我们使用库函数失败时,可以采用strerroe函数来帮助我们认识到使用该库函数失败的原因,从而对此进行有针对性的修改。下面我就以“fopen”函数为例,来让小伙伴更具体地认识strerror的使用场景。

♥fopen(额外赠送)

PFILE * fopen(const char * filename,const char * mode)

●功能:打开文件

●参数: 指向所打开文件的指针,指向打开方式的指针

●头文件:

●返回值:如果打开成功,就返回一个有效指;如果打开失败,就返回一个NULL指针

fopen函数使用演示#include #include int main(){//采用阅读的方式打开文件FILE* pFile;pFile = fopen("text.ext", "r");if (pFile==NULL){printf("打开文件失败\n");return 1;}//读文件(略)//关闭文件fclose(pFile);return 0;}

当我们运行该段代码的时候,屏幕上会打印“打开文件失败”,但是如果我们想解决这个问题,就会发现无从下手,我们并不知道为什么文件会打开失败,自然也就无从下手。这个时候,strerror函数就起到了一个很好地报告错误信息的效果。

//strerroe使用场景演示#include #include #include int main(){//采用阅读的方式打开文件FILE* pFile;pFile = fopen("text.ext", "r");if (pFile==NULL){printf("%s\n",strerror(errno));return 1;}//读文件(略)//关闭文件fclose(pFile);return 0;}

5.字符分类函数

函数如果它的参数符合下列条件就返回真

iscntrl 任何控制字符

isspace 空白字符:空格’ ‘、换页’\f’、换行’\n’、回车’\r’、制表符’\t’或垂直制表符’\v’

isdigit 十进制数字0-9

isxdigit十六进制数字,包括所有十进制数字,小写字母a-f,大写字母A-F

islower小写字母a-z

issupper 大写字母A-Z

isalpha字母a-z或A-Z

isalnum 字母或者数字,a-z、A-Z、0-9

ispunct标点符号,任何不属于数字或者字母的图形字符(可打印)

isgraph任何图形字符

isprint 任何可打印字符,包括图形字符和空格字符

//字符分类函数使用示例#include #include int main(){int ret = islower('A');//判断是否为小写字母printf("%d\n", ret);return 0;}

6.字符转换【只针对字母】

♥tolower

int tolower (int c);

●功能:转换成小写字母

♥toupper

int tolower (int c);

●功能:转换成大写字母

//字符转换函数使用示例#include #include int main(){printf("%c\n", tolower('A'));//转换成小写字符printf("%c\n", toupper('a'));//转换成大写字符return 0;}

7.内存操作函数

在介绍完上述函数后,我们为什么继续介绍内存操作函数呢,是因为上述函数确实能对字符和字符串进行很好的操作,但如果换做是整形数组,或者结构体呢。上述函数就显得捉襟见肘,难以下手了。这也是内存操作函数存在的意义。

♥memcpy

⑴函数介绍

void * memcpy(void * destination, const void *source, size_t)

●功能:函数从courcede的位置开始向后复制num个字节的数据到destination的内存位置

●这个函数在遇到’\0’的时候并不会停下来

●如果source和destination有任何的重叠,复制的结果都是未定义的

//memcpy函数使用演示#include int main(){int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[5] ={0};memcpy(arr2, arr1 + 3, 40);return 0;}

⑵模拟实现

//memcpy函数的模拟实现#includevoid* my_memcpy(void* dest, void* sorc, size_t num){assert(dest && sorc);char* ret = (char *)dest;while (num--){*(char*)dest = *(char*)sorc;dest=(char*)dest+1;sorc=(char*)sorc+1;}return ret;}

通过对memcpy函数的介绍,我们发现该函数仍存在一定缺陷,就是source与destination若过有重叠,那么可能得不到我们想要的结果,代码如下:

#include int main(){int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };memcpy(arr1 + 4, arr1 + 3, 9); return 0;} //理论上:1 2 3 4 4 5 6 8 9 10 //实际上:1 2 3 4 4 4 4 8 9 10 

♥ memmove

⑴函数介绍

void * memmove(void * destnation, const void * source, size_t);

●memmove与memcpy的差别就是memmove处理的源内存块和目标内存块是可以重叠的

●如果源空间和目标空间出现重叠,就得使用memmove函数处理

/memmove函数使用示例#include int main(){int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };memmove(arr1 + 4, arr1 + 3, 9);return 0;}

⑵模拟实现

在实现memmove的模拟实现之前,我们需要先梳理下实现思路。首先,为什么memcpy不能对重叠空间进行拷贝,是因为在进行拷贝的时候,由于源空间与目标空间具有重叠部分,会将源空间的原本的内容进行修改,导致无法实现想要的拷贝结果。在知道这个原因之后,接下来就是对拷贝过程的优化。拷贝其实有两种方式,一种是从前往后拷贝,另一种则是从后向前拷贝。采用后者确实能解决部分的源空间与目标空间的重叠的拷贝,但是有的重叠拷贝它却无法解决。因此最好的拷贝方式应该是将二者结合,针对不同情况采用不同的拷贝方式。以下只采用一种方法进行模拟实现。

//memmove的模拟实现#include #include void* my_memmove(void* dest, const void* sorc, size_t num){assert(dest && sorc);char* ret = (char *)dest;if (((char *)dest-(char *)sorc) 后dest = (char*)dest + 1;sorc = (char*)sorc + 1;}}else//目标空间指针与源空间指针重合或之后{while (num--){*((char*)dest + num ) = *((char*)sorc + num );//后->前}}return ret;}

♥memcmp函数

int memcmp(const void * ptr1, const void * ptr2 ,size_t num);

●功能:比较从ptr1和ptr2开始的n个字节

●返回值如下:

//memcmp函数使用示例#include int main(){ //VS小端存储int arr1[] = { 1, 2, 3 };//01 00 00 00 02 00 00 00 03 00 00 00int arr2[] = { 1, 2, 5 };//01 00 00 00 02 00 00 00 05 00 00 00int ret = memcmp(arr1, arr2, 9);return 0;}

♥memset

void * memset(void * ptr , int value, size_t num);

●功能:内存设置函数

●以字节为单位来设置内存函数

//memset函数使用示例#include int main(){char arr[] = "welcome to mt blog!";memset(arr, 'x', 7);return 0;}

三、结语

关于字符串函数和字符函数的讲解就已经全部结束了,如果对库里其他的函数感兴趣的同学可以通过一下网站继续学习:https://cplusplus.com/

关注我 _麦麦_分享更多干货:_麦麦_的博客_CSDN博客-领域博主
大家的「关注❤️ + 点赞 + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下期见!