当前位置:网站首页>【C语言进阶11——字符和字符串函数及其模拟实现(2))】

【C语言进阶11——字符和字符串函数及其模拟实现(2))】

2022-04-23 18:51:00 初学C语言者


前言

本文接着学习字符和字符串函数,并用代码模拟实现。主要学习内容包括:

4、 字符串查找

  • strstr
  • strtok

5、错误信息报告

  • strerror

6、字符操作函数

7、内存操作函数

  • memcpy
  • memmove
  • memset
  • memcmp

4、字符串查找

4.1 库函数 strstr

char * strstr ( const char *str1, const char * str2);
  • 返回指向str1中第一个出现的str2的指针,如果str2不是str1的一部分,则返回空指针
int main()
{
    
	char a1[] = "abbbcdef";
	char a2[] = "bbc";
	char* ret = strstr(a1, a2);

	if (NULL==ret)
	{
    
		printf("找不到子字串\n");
	}
	else
	{
    
		printf("%s\n", ret);
	}
}

4.2 模拟实现库函数 strstr

char* my_strstr(const char* p1, const char* p2)
{
    
	assert(p1&&p2);
	const char* s1 = p1;//赋予指针初始位置
	const char* s2 = p2;//赋予指针初始位置
	const char* cur = p1;//记录字符串当前指针位置

	while (*cur)
	{
    
		s1 = cur;
		s2 = p2;//移到初始位置
		while (*s1 && *s2 && (*s1==*s2))
		{
    
			s1++;//相等时,指针后移,直到两个不相等或者一方为0
			s2++;
		}
		if (*s2=='\0')
		{
    
			return (char*)cur;
		}
		cur++;//不相等,当前指针加1
	}
	//跳出,就是字符串1移动到末尾
	return NULL;
}
int main()
{
    
	char a1[] = "abbbcdef";
	char a2[] = "bbc";
	char* ret = my_strstr(a1, a2);
	if (NULL==ret)
	{
    
		printf("找不到子字串\n");
	}
	else
	{
    
		printf("%s\n", ret);
	}
}

结果见下图:

在这里插入图片描述

4.3 库函数 strtok

char * strtok ( char * str, const char * sep );
  • sep参数是个字符串,定义了用作分隔符的字符集合第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记
  • strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针
  • strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改
  • strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置
  • strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记
  • 如果字符串中不存在更多的标记,则返回 NULL 指针
int main()
{
    
	char a[] = "[email protected]@hello world";
	char a2[50] = {
     0 };
	strcpy(a2, a);
	printf("%s\n", a2);

	const char* sep = "@. ";//三个分隔符
	printf("%s\n", strtok(a2, sep));//learnC
	printf("%s\n", strtok(NULL, sep));//day
	printf("%s\n", strtok(NULL, sep));//day
	return 0;
}

结果见下图:
在这里插入图片描述

在这里插入图片描述

int main()
{
    
	char a[] = "[email protected]@hello world";
	char a2[50] = {
     0 };
	strcpy(a2, a);
	printf("%s\n", a2);

	const char* sep = "@. ";//三个分隔符
	char* str = NULL;
	//用循环来查找多有的分隔符隔开的字符串,不为空,就找下一个,直到结束
	for (str =strtok(a2,sep); str != NULL; str=strtok(NULL,sep))
	{
    
		printf("%s\n", str);
	}
	return 0;

}

结果见下图:

在这里插入图片描述

5、错误信息报告

5.1 库函数 strerror

char * strerror ( int errnum );
  • 返回错误码,所对应的错误信息
int main()
{
    
	int* p = (int*)malloc(INT_MAX);//在堆区申请内存
	if (p==NULL)
	{
    
		printf("%s\n", strerror(errno));//打印出错信息
		return 1;
	}
	return 0;
}

结果见下图:

在这里插入图片描述

6、字符操作函数

函数 如果他的参数符合下列条件就返回真
iscntrl 任何控制字符
isspace 空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’
isdigit 十进制数字 0~9
isxdigit 十六进制数字,包括所有十进制数字,小写字母a-f,大写字母A~ F
islower 小写字母a~z
isupper 大写字母A~Z
isalpha 字母a-z或A~Z
isalnum 字母或者数字,a-z, A-Z, 0~9
ispunct 标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph 任何图形字符
isprint 任何可打印字符,包括图形字符和空白字符

7、内存操作函数

7.1 库函数 memcpy

void * memcpy ( void * destination, const void * source, size_t num );
  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置
  • 这个函数在遇到 ‘\0’ 的时候并不会停下来
  • 如果source和destination有任何的重叠,复制的结果都是未定义的
int main()
{
    
	int a1[10] = {
     1,2,3,4,5,6,7,8,9,10 };
	int a2[5] = {
     0 };
	memcpy(a2, a1, 20);
	int sz = sizeof(a1) / sizeof(a1[0]);
	for (int i = 0; i < sz; i++)
	{
    
		printf("%d\n", a2[i]);
	}
	return 0;
}

7.2 模拟实现库函数 memcpy

//模拟实现
void* my_memcpy(void* dest, const void* src, size_t cnt)
{
    
	assert(dest&&src);
	void* ret = dest;//接收任何类型的数据
	while (cnt--)
	{
    
		*(char*)dest = *(char*)src;//按字节顺序来交换
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

int main()
{
    
	int a1[10] = {
     1,2,3,4,5,6,7,8,9,10 };
	int a2[5] = {
     0 };
	
	my_memcpy(a2, a1, 20);
	int sz = sizeof(a1) / sizeof(a1[0]);
	for (int i = 0; i < sz; i++)
	{
    
		printf("%d\n", a2[i]);
	}
	return 0;
}

结果见下图:

在这里插入图片描述
在这里插入图片描述

7.3 库函数 memmove

void * memmove ( void * destination, const void * source, size_t num );
  • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理
int main()
{
    
	int a1[10] = {
     1,2,3,4,5,6,7,8,9,10 };	
	memmove(a1+2, a1, 20);	
	int sz = sizeof(a1) / sizeof(a1[0]);
	for (int i = 0; i < sz; i++)
	{
    
		printf("%d\n", a1[i]);
	}
	return 0;
}

7.4 模拟实现库函数 memmove

//模拟实现
void* my_memmove(void* dest, const void* src, size_t cnt)
{
    
	assert(dest&&src);
	void* ret = dest;
	if (dest<src)
	{
    //从左往右拷贝
		while (cnt--)
		{
    
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
    //从右往左
		while (cnt--)
		{
    
			*((char*)dest + cnt) = *((char*)src + cnt);
		}
	}
	return ret;
}

int main()
{
    
	int a1[10] = {
     1,2,3,4,5,6,7,8,9,10 };
	my_memmove(a1+2, a1, 20);
	int sz = sizeof(a1) / sizeof(a1[0]);
	for (int i = 0; i < sz; i++)
	{
    
		printf("%d\n", a1[i]);
	}
	return 0;
}

结果见下图:

在这里插入图片描述

7.5 库函数 memcmp

int memcmp ( const void * ptr1, const void * ptr2, size_t num );
  • 比较从ptr1和ptr2指针开始的num个字节
  • 返回值小于0,前面字节的数据小于后面对应字节的数据
  • 返回值等于0,前面字节的数据等于后面对应字节的数据
  • 返回值大于0,前面字节的数据大于后面对应字节的数据
int main()
{
    
	int a1[] = {
     1,2,3,4,5 };
	int a2[] = {
     1,2,3,4,0x11223305 };
	int ret = memcmp(a1, a2, 18);
	printf("%d\n", ret);
	return 0;
}

结果见下图:

在这里插入图片描述

7.6 库函数 memset

void *memset( void *dest, int c, size_t count );
  • memset 函数将 目标空间 dest 的 总共 count 个字节内容设置为字符c。
int main()
{
    
	int a[] = {
     0x11111111,0x22222222,3,4,5 };
	memset(a, 6, 20);
	return 0;
}

结果见下图:

在这里插入图片描述


总结

字符串库函数的学习基本结束了。学完有点混乱,这块内容就当字典,需要的时候再来查。

感觉单独学字符串库函数有点枯燥,这个要后面刷题才能深刻的理解并掌握这些函数的用法。

库函数实现学习的眼花缭乱,还有一点内容没写完全,等以后再添加内容。

下一篇更新结构体相关的内容。

版权声明
本文为[初学C语言者]所创,转载请带上原文链接,感谢
https://blog.csdn.net/taibudong1991/article/details/124330870