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

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

🌇个人主页_麦麦_

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

目录

一、前言

二、正文

        4. 错误信息报告

                ♥错误信息

                ♥strerror

                ♥fopen额外赠送

        5.字符分类函数

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

                ♥tolower

                ♥toupper

        7.内存操作函数

                ♥memcpy

                ♥ memmove 

                ♥memcmp函数

                ♥memset

三、结语 


一、前言

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

二、正文

        4. 错误信息报告

                ♥错误信息

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

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

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

                ♥strerror

     char * strerrorint 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 * fopenconst char * filenameconst 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 * memcpyvoid * 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 * memmovevoid * 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 memcmpconst 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 * memsetvoid * 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博客-领域博主
        大家的「关注❤️ + 点赞👍 + 收藏⭐」就是我创作的最大动力谢谢大家的支持我们下期见

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6