字符函数和字符串函数的模拟实现

目录

一、strlen 

1.模拟实现strlen

二、strcpy

2.模拟实现strcpy

三、strcat

 3. 模拟实现strcat

四、strcmp

​编辑   4. 模拟实现strcmp

 五、strstr

5. 模拟实现strstr 

六、笔试题

一、strlen 

size_t strlen ( const char * str );
返回值是无符号整形
#include<stdio.h>
#include<string.h>

/*strlen函数返回的是在字符串中'\0'前面出现的字符个数(不包含'\0')。
size_t strlen ( const char * str );
参数指向的字符串必须要以'\0'结束。
注意函数的返回值为size_t,是无符号的(易错)*/
int main()
{
	const char* str1 = "abcdef";
	const char* str2 = "bbb";
	printf("%d\n", strlen(str1));//6
	printf("%d\n", strlen(str2));//3
	if (strlen(str2) - strlen(str1) > 0)
	//3-6=-3
	//10000000 00000000 00000000 00000011 - 补码
	//11111111 11111111 11111111 11111100 - 反码
	//11111111 11111111 11111111 11111101 - 原码
	//再转成十进制数
	{
		printf("%u\n", strlen(str2) - strlen(str1));
		printf("%d\n", strlen(str2) - strlen(str1));
		printf("str2>str1\n");
	}
	/*结果显示,str1 >str2 ,与预期结果不符合,
	原因是strlen返回值是无符号的,相减之后作为无符号数处理,结果<0*/
	else
	{
		printf("str1>str2\n");
	}
	return 0;
}
打印的时候,计算机存的是补码,但是我们打印出来的是十进制,
我们得把补码转成原码,然后把原码转成十进制数,得到的结果才和打印出来的十进制数一致。
所以%u打印出来的会认为无符号型打印会非常大

 str2>str1

1.模拟实现strlen

int my_strlen(const char* str)
{
	int count = 0;
	while (*str++)
	{
		count++;
	}
	return count;
}
int main()
{
	char arr[] = "abcdefg";
	int ret = my_strlen(arr);
	printf("%d\n", ret);
	return 0;
}

二、strcpy

模拟实现需要注意:1)源字符串必须以 '\0'结束。2)会将源字符串中的 '\0'拷贝到目标空间。3)目标空间必须足够大,以确保能存放源字符串。4)目标空间必须可变。

2.模拟实现strcpy

/*模拟实现需要注意:
1)源字符串必须以 '\0'结束。2)会将源字符串中的 '\0'拷贝到目标空间。
3)目标空间必须足够大,以确保能存放源字符串。4)目标空间必须可变。*/
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest++ = *src++);
	return ret;
}
int main()
{
	char arr1[20] = {0};
	char arr2[10] = "abcdefg";
	printf("%s\n", my_strcpy(arr1, arr2));
	return 0;
}

三、strcat

模拟实现注意:

        char * strcat ( char * destination, const char * source );
        源字符串必须以'\0' 结束。目标空间必须有足够的大,能容纳下源字符串的内容,目标空间必须可修改。

int main()
{
	char src[20], dest[50];
	strcpy(src, "This is source");
	strcpy(dest, "This is destination");
	strcat(dest, src);
	printf("最终的目标字符串: |%s|", dest);
	return(0);
}

 3. 模拟实现strcat

c语言*p++是什么意思?-C#.Net教程-PHP中文网

    /*while(*dst++);这样写是错误的*/
    /*由于运算符*的优先级高于运算符++,所以是先取指针dst指向的地址单元的数据。具体如下:
    1、取数组当前位置的值*dst;
    2、然后,dst指向下一位置的数据。
    所以这样写会导致直接到\0就结束了,只会输出woshiyige*/

char* my_strcat(char* dst, const char* src)
{
	assert(dst && src);
	char* ret = dst;
	while (*dst)
	{
		dst++;
	}

	while (*dst++ = *src++);
	return ret;
}
int main()
{
	char arr1[50] = "wo shi yi ge ";
	char arr2[20] = { 's','b','!' ,'\0'};
	printf("%s\n", my_strcat(arr1, arr2));
	return 0;
}

四、strcmp

int main()
{
	char str1[15];
	char str2[15];
	int ret;
	strcpy(str1, "abcdef");
	strcpy(str2, "ABCDEF");
	ret = strcmp(str1, str2);
	if (ret < 0)
	{
		printf("str1 小于 str2");
	}
	else if (ret > 0)
	{
		printf("str1 大于 str2");
	}
	else
	{
		printf("str1 等于 str2");
	}
	return(0);
}

        注意:不会因为字符串长度不同而区别大小,只是从开始到找到\0停止。只要发现ascii码值不同的,就有返回值。

   4. 模拟实现strcmp

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		if (str1 == '\0')
		{
			return 0;
		}
		str1++;
		str2++;
	}
	return *str1 - *str2;

}
int  main()
{
	char arr1[] = "aAASebcd";
	char arr2[] = "aAAsebcdD";
	int ret = my_strcmp(arr1, arr2);
	if (ret > 0)
	{
		printf("arr1 大于 arr2");
	}
	else if (ret < 0)
	{
		printf("arr1 小于 arr2");
	}
	else
	{
		printf("arr1 等于 arr2");
	}
	return 0;
}

 五、strstr

        strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。

注意下列情况的返回值:

5. 模拟实现strstr 

思路:因为我们要在str1里找str2,那么如果在str1中找到了str2,那如果返回str1,我们找不到最开始的位置,因为我们的思路一开始肯定是两个指针遍历两个数组,如果在str1中找到了和str2相同的,就同时往后走,这样我们就无法找到最开始的位置返回str1了。

怎么解决上述问题?

        引入一个指针在str1上,让他去记住最开始的位置,然后别的指针接着遍历。

这样综上我们就知道起码使用三个指针完成

    char* n1 = (char*)str1;
    char* n2 = (char*)str2;
    char* n3 = (char*)str1;

以下是普通的思路:

 但是如果出现如下情形时:

char arr1[] = "abbbcdef";
	char arr2[] = "abbc";

         那么我们就必须想办法让n2能回到最初的位置,再重新遍历。完善以下思路,代码就出来了,如下所示:

char* my_strstr(const char* str1, const char* str2)
{
	char* n1 = (char*)str1;
	char* n2 = (char*)str2;
	char* n3 = (char*)str1;
	if (n2 == '\0')
	{
		return (char*)str1;
	}
	else
	{
		while (*n2)
		{
			while (*n1 && *n1 != *n2)
			{
				n2 = (char*)str2; 
				n3++;
				n1 = n3;
			}
			n2++;
			n1++;
			if (*n1 == '\0')
			{
				return NULL;
			}
		}
		return (char*)n3;
	}
}
int main()
{
	char arr1[] = "abbbcdef";
	char arr2[] = "abbc";
	char* ret = my_strstr(arr1, arr2);
	if (NULL == ret)
		printf("没找到\n");
	else
		printf("%s\n", ret);
	return 0;
}

六、笔试题

逆序输出字符串:

相当于模拟实现reverse

void reverse(char* left, char* right)
{
	while (left < right)
	{
		char tmp = 0;
		tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}
int main()
{
	char arr[100] = { 0 };
	gets(arr);//获取字符串
	//将字符串倒置
	int len = strlen(arr);//计算字符串长度,以求最后一位的地址
	printf("%d\n", len);
	reverse(arr, arr + len - 1);//进行倒置
	printf("%s\n", arr);
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值