模拟实现strlen、strcpy、ctrcmp、strcat和strstr

1.strlen函数: size_t strlen ( const char * str )

返回非零整数

用途:用于计算字符数组长度,计算 '\0'之前的长度不包括 '\0'

所需头文件:include <string.h>

案例:

#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = "abcde";
	int sz = strlen(arr);
	printf("%d",sz);
	return 0;
}
//输出结果为5

模拟strlen:

原理:定义一个指针访问数组首地址,并一直向后访问,指针走一次num记录一次,输出num值

void  My_strlen(char* arr)
{
	char* p = arr;
	int num = 0;
	while (*p != '\0')
	{
		p++;
		num++; //这里用num记录字符数组长度
	}
	printf("%d", num);
}
int main()
{
	char arr[10] = "abcde";
	My_strlen(arr);
	return 0;
}

2.strcpy函数:char * strcpy ( char * destination, const char * source )

返回字符串

用途:把二个数组的值复制给第一个

所需头文件:include <string.h>

案例:

#include <stdio.h>
#include <string.h>
int main()
{
    char arr1[10] = "x";
	char arr2[10] = "abcde";
	strcpy(arr1,arr2);//把括号里面第二个值复制给第一个
	printf("%s",arr1);
	return 0;
}

这里面的复制是直接覆盖,此时的arr1里面有无元素最后都是输出与arr2里一样的元素。

模拟strcpy:

void My_strcpy(char* arr1, char* arr2)//这里的arr1和下面的arr1是反的
{
	char* p1 = arr1;//此时arr1是空
	char* p2 = arr2;//arr2是有元素
	while (*p1 != '\0')
	{
		*p1 = *p2;
		p2++;
		p1++;
	}
	int sz = My_strlen(arr1);//这里直接调用了之前写的My_strlen来求长度
	for (int i = 0; i < sz; i++)
	{
		printf("%c", arr1[i]);
	}
}
int main()
{
	char arr1[] = "abcde";
	char arr2[10] = { 0 };
	My_strcpy(arr2, arr1);//这里注意是谁复制谁
	return 0;

}

这里有点点绕,但是清楚谁复制谁的值就好了,在调用函数里面可以重新命名数组名以免混淆


3.strcmp函数:int strcmp ( const char * str1, const char * str2 )

这个函数是返回整数

用途:比较两个字符串大小

所需头文件:include <string.h>

这里注意一下:str1>str2返回1,str1=str2返回0,str1<str2返回-1.其中两个字符数组的比较方式是比较同位不同值的大小,比出来就不用在比后面

案例:

#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[20] = "abcdex";
	char arr2[20] = "abcderzzzzz";
	int sz = strcmp(arr1,arr2);
	printf("%d",sz);//这里arr2看起来是大于arr1的,但是arr1的第6个元素大于arr2,所以返回1
	return 0;
}

上图:

模拟strcmp:

#include <stdio.h>
#include <string.h>
int My_strcmp(char* arr1, char* arr2, int a, int b)
{
	char* p1 = arr1;
	char* p2 = arr2;
	while (*p1 != '\0')
	{
		if (*p1 == *p2)
		{
			p1++;
			p2++;
		}
		if (*p1 > *p2)//此时里面比较是ASCLL值
		{
			return 1;
			break;
		}
		if (*p1 < *p2)
		{
			return -1;
			break;
		}
		if (*p1 == *p2 && *p1 == arr1[a - 1])//这里的arr1[a-1]表示已经来到了arr1最后一项
		{
			if(a<b)      //这里还有两种情况,arr1和arr2在a个元素前都一样,此时不确定arr2
			return -1;    //是否结束,若b>a,arr2没有结束,返回-1
			else //照着这个逻辑还有一种情况a>b返回1,但是我却没写,其实如果b提前结束
			return 0;//已经在本循环第二个if就返回了,其次剩a=b返回0的情况
			break;
		}
	}
}
int main()
{
	char arr1[] = "abcd";
	char arr2[] = "abcdc";
    int sz1 = strlen(arr1);//为了方便就直接用strlen求长度了
    int sz2 = strlen(arr2);
	int num = My_strcmp(arr1, arr2, sz1, sz2);
	printf("%d", num);
	return 0;
}

可以输入多组用例测试


4.strcat函数:char * strcat ( char * destination, const char * source )

用途:用来追加字符串

所需头文件:include <string.h>

案例:

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

int main()
{
	char arr1[100] = "abcdx";
	char arr2[100] = "abcdaaaa";
	strcat(arr1,arr2);
	printf("%s", arr1);//输出abcdxabcdaaaa
	return 0;
}

模拟strcat:

#include <stdio.h>
#include <string.h>
void My_strcat(char* arr1, char* arr2, int a, int b)

{

	char* p1 = arr1;

	char* p2 = arr2;

	int i = 0;

	for (i = a; i < a + b; i++)
    
	{

		arr1[i] = *p2;//直接在arr1后面把arr2加上

		p2++;
      
	}

	for (int i = 0; i < a + b; i++)

	{

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

	}

}

int main()

{

	char arr1[10] = "abce";
    // 首先arr1要有足够的空间,如果没有的话,创建一个新数组,一次拷贝arr1,arr2
	char arr2[10] = "cv";

	int sz1 = strlen(arr1);
    
	int sz2 = strlen(arr2);

	My_strcat(arr1, arr2, sz1, sz2);

	return 0;

}

5.strstr函数: 

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

用途:不太好描述,举例arr1[] = "acavefgavavag", arr2[]=''vef" ,其中arr2与arr1中间元素一样,那么就输出arr1的这段元素以及之后的,看看案例就知道了。

所需头文件:include <string.h>

案例

#include <stdio.h>
#include <string.h>
int main()
{
	char* p1 = "abcefgheg";
	char* p2 = "cef";
	char* p3 = strstr(p1,p2);
	printf("%s",p3);
	return 0;
}

结果:

模拟strstr:这个是我按照自己的逻辑写的,还没有优化

void My_strstr(char* a, char* b, int sz, int sum)
{
	char* p1 = a;
	char* p2 = b;
//定义这么多指针后面有用处
	char* p5 = b;
	char* p6 = a;
	int num = 1;
	while (*p1 != '\0')
	{
		if (*p1 != *p2)
//开始直接判断两个数组元素不相等的情况,为什么不从相等开始判断,因为我试过了要不得0.0
		{
			p1++;//不相等时a的指针开始后走,b不变
			p6++;//这个先不用管,后面解释
		}
		else//两个数组相等的情况
		{
			char* p3 = p1;
			char* p4 = p2;
//这一步时遍历a,b数组,看看是否b的整体都在a内,这时候为了不改变p1,p2重新定义指针
			for (int i = 0; i < sz; i++)//sz时a数组的长度
			{
				p3++;
				p4++;
				if (*p3 == '\0')
//这是结束标志,为啥要整个这个,因为把p1的地址赋给p3时,p1可能已经++过了
//可能已经不是首地址了,不需要循环sz次
					break;
				if (*p3 != *p4)
					break;
//如果此时两个数组内的元素又不相等了就直接跳出
				else
					num++;//记录a,b字符串有多少个相等
			}
			p1++;//保证循环一直运动的条件
		}
		if (*p1 == '\0' && num != sum)//sum是b的长度,sum和num不相等,说明要不得
			printf("NULL");
		if (num == sum)//这种就是要得的情况,可以开始输出了
		{
			while (*p5 != '\0')//*p5是b的首地址,先把b内的元素给打印出来
			{
				printf("%c", *p5);
				p5++;
				p6++;
			}
			while (*p6 != '\0')
			{
				printf("%c", *p6);
				p6++;
//还要打印a内的元素,p1已经是\0不能用了,p3用来测试也不能拿来用,所以定义p6
//并且p6必须对应走完b内元素的地址,所以一开始p6就要和p1一块走到与p2相同之前
//然后再把b内元素走了,就可以打印后面的了
			}
		}
	}

}
int main()
{
	char* s = "vacokdgjksdk";
	char* x = "acb";
//首先这是会返回空指针的
	int sum = strlen(x);
	int sz = strlen(s);
	My_strstr(s, x, sz, sum);
}

这个是精简版(标志答案):

#include <stdio.h>
#include <string.h>
char *  my_strstr (const char* str1, const char* str2)
{
        char* cp = (char*) str1;
        char* s1, *s2;
        if ( !*str2 )
            return((char*)str1);
        while (*cp)
        {
                s1 = cp;
                s2 = (char*) str2;
                while ( *s1 && *s2 && !(*s1-*s2) )
                        s1++, s2++;
                if (!*s2)
                        return(cp);
                cp++;
        }
        return(NULL);
}
int main()
{
	char* str1 = "abceafgheg";
	char* str2 = "cef";
	char* p2 = my_strstr(str1,str2);
	printf("%s",p2);
	return 0;
}

这段代码后面再给注释,写几个测试用例调试一下看看代码是什么意思

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值