前言

本篇介绍了C语言的一些常见字符函数,字符串函数,内存函数的用法及模拟,掌握这些函数的用法可以帮助你更方便的解决一些字符(串)问题和内存问题(不多),而对这些函数的模拟用法可以让你对指针的理解更加深刻,并提升对C语言的理解!

字符函数

1.字符分类函数

想必大家在初学C语言时肯定刷了很多关于字符的题吧,大家在完成这些题的时候是不是使用ASCLL值呢?那样其实显得过于复杂了,我们其实可以一些函数去达到你想要的效果,接下来我来向你们介绍一下哦!
如果函数的参数符合以下条件就返回真

1.1 iscntrl

任何控制字符

1.2 isdigit

十进制数字‘0’ ~‘9’字符

1.3 islower

小写字母a~z

1.4 isupper

大写字母A~Z

1.5 isalpha

字母a ~ z,字母A ~ Z;

1.6 isalnum

字母或者数字

2.字符转换函数

2.1 tolower(int c)

大写字母转小写字母

2.2 toupper(int c)

小写字母转大写

字符串函数

3.strlen的使用和模拟实现

3.1strlen的使用

  • 字符串以‘\0’作为结束标志,strlen函数返回的是在字符串中‘\0"前面出现的字符个数(不含‘\0’)
  • 参数指向的字符串必须要以‘\0’结束
  • 注意函数的返回值为size_t,是无符号的
  • 头文件<string.h>
    大家尤为注意的是加了黄色的部分
#include<stdio.h>
#include<string.h>

int main()
{
	char arr1[] = "abcde";
	char arr2[] = "sdgj";
	if (strlen(arr2) - strlen(arr1) < 0)
	{
		printf("arr2小\n");
	}
	else
	{
		printf("arr1小\n");
	}
	return 0;
}

在这里插入图片描述
大家是不是觉得很意外,明明arr1中的字符个数多,怎么是arr1小呢?
上文说了,size_t是无符号整型size_t与size_t的计算结果也是无符号整型是大于等于0的,故出现这个结果。
那么,我们该如何计算两者大小呢?

if(strlen(arr1)>strlen(arr2))
{
printf("arr1大\n");
}

直接比较strlen不就行了🌹

3.2strlen的模拟实现

#include<stdio.h>
#include<string.h>
#include<assert.h>
size_t my_strlen(char* arr)
{
	assert(arr);//确保不为空集
	size_t r = 0;
	while (*arr)
	{
		arr++;
		r++;
	}
	return r;
}
int main()
{
	char arr1[] = "abcde";
	char arr2[] = "sdgj";
	if (my_strlen(arr2) < my_strlen(arr1))
	{
		printf("arr2有%zu个字符\n", my_strlen(arr2));
		printf("arr2小\n");
	}
	else
	{
		printf("arr1小\n");
	}
	return 0;
}

在这里插入图片描述
想必大家应该很容易理解,这里不过多解释了。

4.strcpy的用法和模拟实现

4.1strcpy的使用

char*strcpy(char*destination,const char*source);

destination是目标空间,source是源字符串这里只说一遍哈,后面的也是这个
作用:将sourse里的值拷贝到destination中,并返回destination的初始地址

  • 源字符串必须以‘\0’结束
  • 会将源字符串的‘\0’拷贝到目标空间
  • 目标空间必须足够大,以确保能存放源字符串
  • 目标空间必须可修改
  • 头文件<string.h>
#include<stdio.h>
#include<string.h>
#include<assert.h>
int main()
{
	char arr1[10] = { 0 };
	char arr2[] = "sdgj";
	strcpy(arr1, arr2);
	char* p = strcpy(arr1, arr2);
	printf("%s\n", arr1);
	printf("%s\n", p);
	return 0;
}

在这里插入图片描述

4.2strcpy的模拟实现

#include<stdio.h>
#include<string.h>
#include<assert.h>

char* my_strcpy(char* att, const char* arr)

{
	assert(att && arr);
	char* ret = att;
	while (*ret++ = *arr++)

	{

		;

	}
	return att;
}

int main()

{

	char arr[] = "abcdef";

	char att[20] = "xxxxxxxxxxxxxxxxxxxx";

	my_strcpy(att, arr);
	char* a = my_strcpy(att, arr);
	printf("%s\n", att);
	printf("%s\n", a);
	return 0;

}

5.strcat的使用和模拟实现

char*strcat(char*destination,const char*source);

5.1strcat的使用

功能:字符串追加,把source指向的原字符串中的所有字符都追加到destination

  • 源字符串必须以‘\0‘结束
  • 目标字符串中也得有\0,否者不知道在哪追加
  • 目标空间足够大
  • 目标空间必可修改
  • 末尾追加
#include<stdio.h>
#include<string.h>

int main()
{
   char str1[20] = "abcdsf";
   char str2[] = "his dog";
   char* p = strcat(str1, str2);
   printf("%s\n", p);
   printf("%s\n", str1);
   return 0;
}

在这里插入图片描述

5.2strcat的模拟实现

#include<stdio.h>

#include<assert.h>

#include<string.h>

void my_strcat(char* arr, char* att)

{

	assert(arr && att);

	while (*arr)

	{

		*arr++;

	}

	while (*att)

	{

		*arr++ = *att++;

	}

	*arr = *att;

}

int main()

{

	char arr[20] = "abcdef";

	char att[7] = "abcdeh";

	my_strcat(arr, att);

	printf("%s\n", arr);

	return 0;

}

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

6.strcmp的使用和模拟实现

6.1strcmp的使用

int strcmp(char*destination,const char*source);
  • 第一个字符串大于第二个字符串,则返回大于0的数字
  • 第一个字符串等于第二个字符串,则返回0
  • 第一个字符串小于第二个字符串,则返回小于0的数字
  • 比较的是两个字符串上对应字符的ASCLL码值的大小,从左向右
#include<stdio.h>
#include<string.h>

int main()
{
	char str1[] = "asdf";
	char str2[] = "asdh";
	printf("%d", strcmp(str1, str2));
	return 0;
}

在这里插入图片描述

6.2strcmp的模拟实现

#include<stdio.h>

#include<assert.h>

int my_strcmp(const char* att, const char* arr)

{

	assert(att && arr);

	while (*att == *arr)

	{

		if (*att == '\0')

			return 0;

		*att++;

		*arr++;

	}

	return *att - *arr;

}

int main()

{

	char arr[7] = "abcdef";

	char att[7] = "abcdeh";

	if (my_strcmp(att, arr) == 0)

	{

		printf("两者相同\n");

	}

	else if (my_strcmp(att, arr) > 0)

	{

		printf("前者大\n");

	}

	else

	{

		printf("后者大\n");

	}

	return 0;

}

想必大家都了解了strcpy,strcat,strcmp的用法了,接下来,给大家介绍一下这几个函数的进阶版(笔者自称)!

7.strncpy,strncat,strncmp

给大家分别写下这些库函数如何表示

char *strncpy(char *destination,const char *source,size_t num);
char *strncat(char *destination,const char *source,size_t num);
int strncpy(char *destination,const char *source,size_t num);

对于以上函数,无非增加了size_t类型的num,代表将要复制,追加,比较大小的比特个数(1字节8比特)
和上方函数是一个用法,但是还是有些微小差别

7.1strncpy

  • 如果源字符串的长度小于num,则拷贝完字符串之后,在目标的后面追加0直至num个
  • 如果大于num,则不保证末尾有\0,需手动添加

7.2strncat

  • 源字符串中不一定要\0了,因为函数会自动补\0(不管是否已有0)

7.2strncmp

这里强调一下,strncmp与strcmp均不忽略大小写

8.strstr的使用和模拟实现

char*strstr(const char* str1,const char*str2)

8.1strstr的使用

功能:在一个字符串中找另一个字符串第一次出现的位置

  • 函数返回str2在字符串str1中第一次出现的位置,无则返回NULL
  • 字符串的比较匹配不包含\0,以\0作为结束标志
#include<stdio.h>
#include<string.h>

int main()
{
	char str1[] = "asdfghjkl";
	char str2[] = "ghjkl";
	char* p = strstr(str1, str2);
	printf("%s\n", str1);
	printf("%s\n", p);
	return 0;
}

在这里插入图片描述

8.2strstr的模拟实现

#include<stdio.h>

#include<string.h>

char* my_strstr(const char* str1,const char* str2)

{

	char* cp = str1;

	char* s1;

	char *s2;

	if (!*str2)

	{

		return cp;

	}

	while (*cp)

	{

		char* s1 = cp;

		char* s2 = str2;

		while (*s1 && *s2 && *s1 == *s2)

		{

			s1++;

			s2++;

			if (!*s2)

			{

				return cp;

			}

		}

		cp++;

	}

	return (NULL);



}

int main()

{

	char str[] = "This is a simple string";

	char* pch;

	pch = my_strstr(str,"simple");

	strncpy(pch, "sample", 6);

	printf("%s\n", str);

	return 0;

}

内存函数

9.memcpy的使用和模拟实现

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

9.1memcpy的使用

  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置
  • 这个函数在遇到‘\0’不会停止下来
  • 如果source和destination有任何的重叠,复制的结果都是未定义的
#include<stdio.h>
#include<string.h>
int main()
{
	char arr[20] = "chen zhao nan";
	memcpy(arr, arr + 5, 5);
	printf("%s\n", arr);
	return 0;
}

在这里插入图片描述

9.2memcpy的模拟使用

#include<stdio.h>

#include<string.h>

#include<assert.h>

void *my_memcpy(void* arr2, const void* arr1, size_t n)

{

	assert(arr1 && arr2);

	void* ret = arr2;

	while (n--)

	{

		*(char*)arr2 = *(char*)arr1;

		arr2 = (char*)arr2 + 1;

		arr1 = (char*)arr1 + 1;

	}

	return(ret);

}

int main()

{

	int arr1[] = { 1,2,3,4,5,6,7,8,9 };

	int arr2[20] = { 0 };

	my_memcpy(arr2, arr1, 20);

	for (int i = 0; i < 10; i++)

	{

		printf("%d ", arr2[i]);

	}

	return 0;

}

前文说了,如果source和destination有任何的重叠,复制的结果都是未定义的!那么,是否有函数可以让两者可以重叠呢?
有的有的😄

10.memmove的使用和模拟实现

void * memmove(void*destination,const void*source,size_t num);
  • 与memcpy差不多,但可重叠
  • 若重叠,就得用memmove

10.1memmove的使用

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[50] = "chen zhao nan is a handsome boy";
	memmove(arr, arr + 5, 10);
	printf("%s\n", arr);
	return 0;
}

在这里插入图片描述

10.2memmove的模拟实现

#include<stdio.h>

#include<string.h>

#include<assert.h>

void* my_memmove(void* dst, const void* src, size_t n)

{

	void* ret = dst;//int 类型,需强制转换为char类型才能加减size_t类型

	if (dst <= src || ((char*)dst >= ((char*)src + n)))

	{

		while (n--)

		{

			*(char*)dst = *(char*)src;

			dst = (char*)dst+1;

			src = (char*)src + 1;

		}

	}

	else

	{

		dst = (char*)dst + n-1;

		src = (char*)src + n-1;

		while (n--)

		{

			*(char*)dst = *(char*)src;

			dst = (char*)dst - 1;//可不可以dst++;

			src = (char*)src - 1;

		}

	}

	return(ret);

}

int main()

{

	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };

	my_memmove(arr1 + 2, arr1, 20);

	for (int i = 0; i < 10; i++)

	{

		printf("%d ", arr1[i]);

	}

	return 0;

}

11.memset,memcmp函数的使用

11.1memset的使用

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

这个函数很好用哈
功能:将ptr的值以字节为单位设置成想要的内容

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[10] = "aaaaaaaaa";
	memset(arr, 'x', 5);
	printf("%s\n", arr);
	return 0;
}

在这里插入图片描述

11.2memcmp的使用

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

这个函数和strncmp差不多,但这里还是说一下区别

  • memcmp可比较多种类型,strncmp专与字符串
  • strncmp遇\0结束,memcmp则强制比较num每个字节
    字符函数,字符串函数,内存函数就介绍到这里,欢迎大家讨论😄
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐