C语言进阶——字符函数和字符串函数(下)

🌇个人主页:_麦麦_

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

目录

一、前言

二、正文

        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);       

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

●包含的头文件:<string.h> <errno.h>

//strerror函数使用演示
#include <stdio.h>
#include <string.h>
#include <errno.h>

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)

●功能:打开文件

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

●头文件:<stdio.h>

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

fopen函数使用演示
#include <stdio.h>
#include <string.h>

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

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

//strerroe使用场景演示
#include <stdio.h>
#include <string.h>
#include <errno.h>

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 <stdio.h>
#include <string.h>

int main()
{
	int ret = islower('A');    //判断是否为小写字母
	printf("%d\n", ret);
	return 0;
}

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

                ♥tolower

int tolower (int c);

●功能:转换成小写字母

                ♥toupper

int tolower (int c);

 ●功能:转换成大写字母

//字符转换函数使用示例
#include <stdio.h>
#include <string.h>

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 <stdio.h>

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函数的模拟实现
#include<asser.t>

void* 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 <stdio.h>

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 <stdio.h>

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 <stdio.h>
#include <assert.h>

void* my_memmove(void* dest, const void* sorc, size_t num)
{
	assert(dest && sorc);
	char* ret = (char *)dest;
	if (((char *)dest-(char *)sorc) < 0)	//目标空间指针位于源空间指针之前	
	{
		while (num--)
		{
			*(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 <string.h>
int main()
{                               //VS小端存储
	int arr1[] = { 1, 2, 3 };	//01 00 00 00 02 00 00 00 03 00 00 00		
	int arr2[] = { 1, 2, 5 };	//01 00 00 00 02 00 00 00 05 00 00 00
	int ret = memcmp(arr1, arr2, 9);
	return 0;
}

                ♥memset

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

 ●功能:内存设置函数

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

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

三、结语 

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

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

  • 88
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 102
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 102
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_麦麦_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值