详细介绍关于字符函数和字符串函数【C语言】

文章目录

  • strlen
    • strlen的模拟实现
  • strcpy
  • strncpy
  • strcat
    • strcat 的模拟实现
  • strncat
  • strcmp
    • strcmp的模拟实现
  • strncmp
  • strstr
    • strstr的模拟实现
  • strtok
  • strerror
  • 内存操作函数
    • memcpy
      • memcpy的模拟实现
    • memmove
      • memmove的模拟实现

strlen

这里鄃鳕推荐一个可以查找函数的具体细节的网站 ,以便后续学习https://legacy.cplusplus.com/reference/cstring/strlen/?kw=strlen

在这里插入图片描述

字符串以 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包
含 ‘\0’ )
注意函数的返回值为size_t,是无符号的(很重要)

strlen的模拟实现

  int my_strlen( const char* str)
{
	  int count = 0;
	  assert(str!=NULL);
	  while (*str != '\0')
	  {
		  str++;
		  count++;
	  }
	  return count;
}
int main()
{
	char arr[] = "abc";
	int len = my_strlen(arr);
	printf("%d\n", len);
	return 0;
}

看下面一道题:

int main()
{
	if (my_strlen("abc") - my_strlen("abcdef") > 0)
	{
		printf(">\n");
	}
	else
	{
		printf("<=\n");
	}
	return 0;
}

答案是> ,为什么呢? strlen的返回类型是size_t ,是unsigned int ,是无符号数,3-6 得到的-3 在内存中被解读成非常大的正数
自然结果大于0

strcpy

在这里插入图片描述

int main()
{
	char arr[] = "###########";
	char* p = "hello";
	strcpy(arr, p);
	printf("%s", arr);
	return 0;
}

源字符串必须以 ‘\0’ 结束。
会将源字符串中的 ‘\0’ 拷贝到目标空间
目标空间必须足够大,以确保能存放源字符串
目标空间必须可变,所以不加const ,源字符串不用改变,加个const 更加安全

strncpy

在这里插入图片描述

拷贝num个字符从源字符串到目标空间。
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
当strcpy 目标空间没有足够大而导致出现问题,而strncpy 相对于strcpy来说 ,多了一个参数 ,相对比较安全。

int main()
{
	char arr1[20] = "abcdefghi";
	char arr2[] = "qwer";
	strncpy(arr1, arr2, 6);
	printf("%s\n", arr1);
	return 0;
}

strcat

在这里插入图片描述

int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world";
	strcat(arr1, arr2);
	printf("%s", arr1);
	return 0;
}

源字符串必须以 ‘\0’ 结束。
目标空间必须有足够的大,能容纳下源字符串的内容
目标空间必须可变,所以不加const ,源字符串不用改变,加个const 更加安全

详细介绍关于字符函数和字符串函数【C语言】_第1张图片

strcat 的模拟实现

 char * my_strcat(char* dest, const char* src)
{
	 // 找到目标空间的\0
	 char* ret = dest;  
	 assert(dest && src);
	 while (*dest)
	 {
		 dest++;
	 }
	 //追加
	 while (*dest++ = *src++)
	 {
		 ;
	 }
	 return ret; 
}
int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world";
		printf("%s", my_strcat(arr1, arr2));
	return 0;
}

那么字符串自己给自己追加,这样做行吗?

int main()
{
	char arr[20] = "abcd";
	strcat(arr, arr);
	printf("%s\n", arr);
	return 0;
}

\0被改变了,找不到结束的标志\0了
详细介绍关于字符函数和字符串函数【C语言】_第2张图片

strncat

在这里插入图片描述

int  main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world";
	strncat(arr1, arr2, 10);
	printf("%s\n", arr1);
	return 0;
}

strncat相比较strcat多了一个参数 ,相对而言更安全

strcmp

在这里插入图片描述


标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字

可以都加上const ,让代码更安全

int main()
{
	
	int ret = strcmp("abbb", "abq");
	printf("%d", ret);
	return 0;
}

strcmp的模拟实现

 int my_strcmp(const char* s1, const char* s2)
{
	assert(s1 && s2);
	while (*s1 == *s2)
	{
		if (*s1 == '\0')
		{
			return 0;
		}
		s1++;
		s2++;
	 }
	return *s1 - *s2;
}
int main()
{
	    char* p = "abcdef";
		char* q = "abcdef";
		int ret = my_strcmp(p, q);
		if (ret > 0)
		{
			printf("p>q\n");
		}
		else if( ret < 0)
		{
			printf("p);
		}
		else
		{
			printf("p==q\n");
		}

	return 0;
}

strncmp

在这里插入图片描述


详细介绍关于字符函数和字符串函数【C语言】_第3张图片

int main()
{
	char* p = "aqcdef";
	char* q = "abcqwert";
	int ret = strncmp(p, q, 4);
	printf("%d\n", ret);
	return 0;
}

strstr

在这里插入图片描述

int main()
{
	    char arr1[] = "abbbcdef";
		char arr2[] = "bbc";
		char * ret = strstr(arr1, arr2);
		if (ret == NULL)
		{
			printf("没找到\n");
		}
		else
		{
			printf("找到了:%s\n", ret);
		}
	return 0;
}

strstr的模拟实现

 char * my_strstr(const char* str1, const char* str2)
{
	 assert(str1 && str2);
	 const char* s1 = NULL;
	 const  char* s2=NULL;
	  const char* cp = str1;
	  if (* str2 == '\0')//str2是空字符串
	  {
		  return (char *)str1;
	  }

	  while (*cp)//查找
	  {
		  s1 = cp;
		  s2 = str2;
		  while (*s1 && *s2 && (*s1 == *s2))
		  {
			  s1++;
			  s2++;
		  }
		  if (*s2 == '\0')
		  {
			  return(char * ) cp;
		  }
		  cp++;
	  }
	  return NULL;//找不到
}
int main()
{
	//在arr1中查找是否包含arr2数组
	    char arr1[] = "abbbcdef";
		char arr2[] = "bbc";
		char * ret = my_strstr(arr1, arr2);
		if (ret == NULL)
		{
			printf("没找到\n");
		}
		else
		{
			printf("找到了:%s\n", ret);
		}
	return 0;
}

详细介绍关于字符函数和字符串函数【C语言】_第4张图片


strtok

在这里插入图片描述


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

strerror

在这里插入图片描述


strerror 函数 (返回错误码,所对应的错误信息)
使用库函数的时候
调用库函数失败的是,都会设置错误码
全局的错误码

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	fclose(pf);
	pf = NULL;

	return 0;
}

内存操作函数

memcpy

在这里插入图片描述

int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	memcpy(arr2, arr1, 20);
	return 0;
}
  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
  • 这个函数在遇到 ‘\0’ 的时候并不会停下来。
  • 如果source和destination有任何的重叠,复制的结果都是未定义的。
  • memcpy函数应该拷贝不重叠的内存(在vs2019memcpy可以拷贝重叠的内存,但是正常情况下memcpy是不能拷贝重叠的内存)

memcpy的模拟实现

 void * my_memcpy(void* dest, const void* src, size_t num)
{
	 assert(dest && src);
	 void* ret = dest;
	 while (num--)
	 {
	 *(char*)dest = *(char* )src;
		 src = (char*)src + 1;
		 dest = (char*)dest + 1;
	 }
	 return ret;
}
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	my_memcpy(arr2, arr1, 20);
	return 0;
}

详细介绍关于字符函数和字符串函数【C语言】_第5张图片

void* 是无具体类型的指针 ,解引用不知道访问几个字节 ,+1 也不知道跳过几个字节,强制类型转换为char* 就是一个很好的解决办法

memmove

在这里插入图片描述

int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	memmove(arr1, arr1+2, 20);
	return 0;
}
  • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理。

memmove的模拟实现

详细介绍关于字符函数和字符串函数【C语言】_第6张图片

 void * my_memmove(void* dest, const void* src, size_t num)
{
	 assert(dest && src);
	 void* ret = dest;
	 if (dest < src)  
		 //前——>后
	 {
		 while (num--)
		 {
			 *(char*)dest = *(char*)src;
			 src = (char*)src + 1;
			 dest = (char*)dest + 1;
		 }
	 }
	 else
	 {
		 //后——>前
		 while (num--)
		 {
			* ( (char *) dest + num) = *(  (char *)src + num);

		 }
	 }
	 return ret;
}
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	my_memmove(arr1, arr1 + 2, 20);
	return 0;
}

从后向前拷贝:

详细介绍关于字符函数和字符串函数【C语言】_第7张图片



如果你觉得这篇文章对你有帮助,不妨动动手指给点赞收藏加转发,给鄃鳕一个大大的关注
你们的每一次支持都将转化为我前进的动力!!!

你可能感兴趣的:(c语言,c++,开发语言)