C进阶:字符串相关函数及其模拟实现

C/C++
154
0
0
2024-04-30

一.strlen

1.功能

计算字符串长度,直到遇到 '\0' ;

2.模拟实现

我们是仿照库函数的方式模拟的,所以先来看看strlen 再库函数里是如何定义的;

这个函数很简单,所以直接上代码:

代码语言:javascript

复制

unsigned my_strlen(const char* str)
{
	assert(str);
	unsigned count = 0;
	while (*str++ != '\0')
	{
		count++;
	}
	return count;
}

这里的 assert ,是用来判断 str 是否是空指针的,且需要包含头文件 <assert.h>;

二.strcpy

1.功能

字符串拷贝函数,将源字符串的内容拷贝到目标空间内;

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

这个的实现逻辑同样也很简单,还是直接看代码:

代码语言:javascript

复制

char* my_strcpy(char *dest,char *sour)
{
    assert(dest&&sour);
	char* p = dest;
	while (*dest++ = *sour++)
	{
		;
	}
	return p;
}

三.strcat

1.功能

字符串追加(连接)函数,将一个字符串的内容追加到另一个字符串结束的末尾;

2.注意事项
1.源字符串必须以 '\0' 结束。 2.目标空间必须有足够的大,能容纳下源字符串的内容。3.目标空间必须可修改。4.不可以给自己追加。
3.模拟实现

库函数里的定义:

思路一:要找到目标字符串的结尾在哪里,然后再把源字符串的内容追加在后面;思路二:将目标字符串结尾处作为起始地址,把源字符串内容拷贝进去;

让我们来看代码:

代码语言:javascript

复制

char* my_strcat(char* str1, char* str2)
{
	assert(str1 && str2);
	char* p = str1;
	while (*str1!='\0')    //找到目标字符串的结尾
	{
		str1++;
	}
	while (*str1++ = *str2++)  //字符串追加
	{
		;
	}
	return p;
}

或者根据上面的第二个思路,可以这样写代码:

代码语言:javascript

复制

char* my_strcat(char* str1, char* str2)
{
	assert(str1 && str2);
	char* p = str1;
	while (*str1!='\0')
	{
		str1++;
	}
	strcpy(str1, str2);    //strcpy 代替前面的字符串追加
	return p;
}

四.strcmp

1.功能

字符串比较函数;

2.模拟实现

当要比较的两个字符串有相同字符时,继续向后比较,直到遇到不同的字符,判断其不同字符的大小,如果一直相等,则两字符串相等;

这个函数实现起来也不复杂,代码:

代码语言:javascript

复制

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while ( * str1++ == *str2++)
	{
		if (*str1 == '\0' && *str2 == '\0')   //判断相等
		return 0;
		if (*str1 == '\0' || *str2 == '\0')   //当其中有一方字符串结束时,也跳出循环
			break;
	}
	
	return *str1 - *str2;   //不相等时跳出循环,来到不同字符间的比较
	
}

五.strstr

1.功能

C 库函数 char *strstr(const char *haystack, const char *needle) 在字符串 haystack 中查找第一次出现字符串 needle 的位置,不包含终止符 '\0'。

2.模拟实现

既然是在一个字符串中查找另一个字符串,那么我们肯定是从第1个字符开始,如果相同,那么向后继续查找,如果不同,则换一个查找的起始点,但有时候我们会碰到查找到部分相同的,剩下的部分不相同,这时我们就要换下一个起始点,所以需要一个记录起始点的变量;

请看下图:

具体代码:

代码语言:javascript

复制

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	const char* s1 = str1;
	const char* s2 = str2;
	const char* cp = str1;   //控制起始点
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		while (*s1 && *s2 && ( * s1++ == *s2++ ))  //防止空字符串
		{
			;
		}
		if (*s2 == '\0')
		{
			return cp;
		}
		
		cp++;
	}
	return NULL;

}

上面是一个一个字符的比较,那我们可不可以直接比较字符串呢?

答案是可以的,我们可以使用 strncmp 函数,这个函数和 前面讲的 strcmp 函数功能一致,但它可以控制比较几个字符;

所以我们把要查找的字符串的长度当作 n ,让它一次性只比较 这 n 个字节,看是否相等,当剩下的字节数小于 n 时,后面肯定找不到相等的了,所以这个时候直接返回 NULL;

具体代码:

代码语言:javascript

复制

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	int len2 = strlen(str2);
	const char* cp = str1;
	while (*cp)
	{
		int ret = strncmp(cp, str2, len2);
		if (ret == 0)
			return cp;
		cp++;
		if (strlen(cp) < len2)
			return NULL;
	}