C语言string.h部分函数模拟实现(1)


本篇文章用于模拟实现 “string.h” 中的部分函数.

介绍

1.首先是一个计算字符串长度函数

  • strlen()

2.长度不受限的字符串

  • strcpy()
  • strcat()
  • strcmp()

3.长度受限的字符串

  • strncpy()
  • strncat()
  • strncmp()

4.最后是一个字符串匹配函数的暴力解决方式

  • strstr()

1.计算字符串长度函数

1.1 strlen()

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>

//typedef unsigned int     size_t;
size_t my_strlen(const char* str)//const 使得传入的str不会被改变
{
   //assert()用于防止传入空指针
   assert(str);
   const char* start = str;
   const char* end = str;
   while (*end != '\0')
   {
   	end++;
   }
   return end - start;
}

int main()
{
   char arr[] = "abc\0def";
   int a = my_strlen(arr);//3	strlen的返回值是无符号整型,所以用返回值运算时需要注意
   printf("%d\n",a);
   return 0;
}

2.长度不受限的字符串

2.1 strcpy()

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>
//char* 返回值 返回目标数组的首地址 用于后续调用时可以直接用返回值调用数组
char* my_strcpy(char* dest,const char* src)//const 使得传入的str不会被改变
{
   //断言用于判断数组是否为空
   assert(dest);
   assert(src);
   char* ret = dest;
   while(*dest++ = *src++)
   {
   	//(*dest++ = *src++)的值就是*src的值当*src=='\0'是循环退出
   	;
   }
   return ret;
}

int main()
{
   char arr[10] = "*********";
   //char* p = "abcdef";//常量字符串	空间无法修改	与下相同
   const char* p = "abcdef";
   my_strcpy(arr,p);//拷贝	会拷贝到\0	如果目标空间的大小不够也会拷贝,会造成越界访问
   printf("%s\n", arr);
   return 0;
}

2.2 strcat()

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>

//char* 返回值 返回目标数组的首地址 用于后续调用时可以直接用返回值调用数组
char* my_strcat(char* dest, const char* src)//const 使得传入的str不会被改变
{
   //断言用于判断数组是否为空
   assert(dest);
   assert(src);
   char* ret = dest;
   while (*dest!='\0')
   {
   	dest++;
   	//先找到目标数组的\0处
   	;
   }
   while (*dest++ = *src++)
   {
   	//(*dest++ = *src++)的值就是*src的值当*src=='\0'是循环退出
   	;
   }
   return ret;
}

int main()
{
   char arr[20] = "hello";
   char arr2[] = "world";

   my_strcat(arr,arr2);//字符串追加函数	strcpy相似
   //arr 和 arr2 都需要有\0	先找到arr的\0人后向后追加,追加到arr2的\0
   //目标空间需要可修改	目标空间需要能够容纳下原字符串的内容
   printf("%s\n",arr);

   //注:此函数无法自己追加自己	因为当你追加时会覆盖掉原来的'\0'使得函数遇不到'\0',函数无法结束
   
   return 0;
}

2.3 strcmp()

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>

//char* 返回值 返回目标数组的首地址 用于后续调用时可以直接用返回值调用数组
int my_strcmp(const char* str1, const char* str2)//const 使得传入的str不会被改变
{
   //断言用于判断数组是否为空
   assert(str1&&str2);
   while (*str1==*str2)
   {
   	if(*str1=='\0')
   	{
   		return 0;
   	}
   	str1++;
   	str2++;
   }
   return *str1 - *str2;
   //直接返回差值
}

int main()
{
   char str1[] = "hello";
   char str2[] = "hello";

   //strcmp()比较的是对应位置上的字符的大小,而非长度
   //需要\0用于结束
   int a = my_strcmp(str1, str2);
   //a<0:str1<str2
   printf("%d\n", a);

   return 0;
}

3.长度受限的字符串

3.1 strncpy()

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>

//typedef unsigned int     size_t;
char* my_strncpy(char* dest,const char* src,size_t count)//const 使得传入的str不会被改变
{
   char* ret = dest;
   while (count && (*dest++ = *src++) != '\0')
   {
   	//正常赋值数组元素
   	count--;
   }
   if (count)
   {
   	//补充'\0'
   	while (--count)
   	{
   		*dest++ = '\0';
   	}
   }
   return ret;
}

int main()
{
   char arr[10] = "*********";
   //char* p = "abcdef";//常量字符串	空间无法修改	与下相同
   const char* p = "abcdef";
   my_strncpy(arr, p,8);//拷贝	会拷贝到\0	如果目标空间的大小不够也会拷贝,会造成越界访问
   //如果需要拷贝的数组内容不够会在目标数组后续拷贝位置补充'\0'
   printf("%s\n", arr);
   return 0;
}

3.2 strncat()

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>

//char* 返回值 返回目标数组的首地址 用于后续调用时可以直接用返回值调用数组
char* my_strncat(char* dest, const char* src,size_t num)//const 使得传入的str不会被改变
{
   //断言用于判断数组是否为空
   assert(dest);
   assert(src);
   char* ret = dest;
   while (*dest != '\0')
   {
   	dest++;
   	//先找到目标数组的\0处
   	;
   }
   while (num--)
   {
   	*dest++ = *src++;
   	//追加
   	;
   }
   *dest = '\0';
   //最后添加'\0'
   return ret;
}

int main()
{
   char arr[20] = "hello";
   char arr2[] = "world";

   my_strncat(arr, arr2,3);//字符串追加函数	追加结束之后会在后面追加一个'\0'
   //arr需要有\0	先找到arr的\0人后向后追加,与strcat不同的是,追加结束之后会自动在后面追加一个'\0'
   //目标空间需要可修改	目标空间需要能够容纳下原字符串的内容
   printf("%s\n", arr);

   //注:此函数可以自己追加自己	因为有参数控制追加次数

   return 0;
}

3.3 strncmp()

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>

//char* 返回值 返回目标数组的首地址 用于后续调用时可以直接用返回值调用数组
int my_strncmp(const char* str1, const char* str2, size_t count)//const 使得传入的str不会被改变
{
   //断言用于判断数组是否为空
   assert(str1 && str2);
   while (--count && *str1 == *str2)
   {
   	if (*str1 == '\0')
   	{
   		return 0;
   	}
   	str1++;
   	str2++;
   }
   if (count == 0) 
   {
   	return 0;
   }
   return *str1 - *str2;
   //直接返回差值
}

int main()
{
   char str1[] = "hello";
   char str2[] = "helo";

   //strncmp()与strcmp()相似
   //比较前n个字符
   int a = my_strncmp(str1, str2,3);
   //a<0:str1<str2:以此类推
   printf("%d\n", a);

   return 0;
}

4.长度受限的字符串

4.1 strstr()

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>

//char* 返回子串在字符串中首次出现的起始位置
char* my_strstr(const char* str1, const char* str2)//const 使得传入的str不会被改变
{
   const char* s1 = str1;
   const char* s2 = str2;
   const char* p = str1;
   //循环判断寻找
   while (*p)
   {
   	s1 = p;
   	s2 = str2;
   	while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)
   	{
   		s1++;
   		s2++;
   	}
   	if (*s2 == '\0')
   	{
   		//返回类型不匹配,强转为返回类型
   		return (char*)p;
   	}
   	p++;
   }
   return NULL;
}

int main()
{
   char arr[] = "abcdef";
   char arr2[] = "bcd";
   char* p = my_strstr(arr,arr2);//在arr中找arr2	NULL为不存在	存在则返回子串在字符串中首次出现的起始位置
   //此处的实现方法为暴力实现
   printf("%s\n",p);

   return 0;
}
  • 12
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

魚小飛

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

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

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

打赏作者

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

抵扣说明:

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

余额充值