模拟实现一些库函数(1)

函数介绍

本章内容会给大家展示
求字符串长度
strlen
长度不受限制的字符串函数
strcpy
strcat
strcmp
长度受限制的字符串函数介绍
strncpy
strncat
strncmp
字符串查找
strstr
并将这些函数全部模拟出来,带给大家。

字符串长度strlen函数

这个函数是用来实现求字符串长度的,话不多说我们上代码。

int main()
{
	char str[] = "ABCDEFGHIJK";
	int sz=strlen(str);
	printf("%d", sz);
	return 0;
}

模拟实现一些库函数(1)_第1张图片
那么我们来实现模拟strlen函数

#include
int my_strlen(const char* str)
{
	assert(str);
	int i = 0;
	while (*str != '\0')
	{
		str++;
		i++;
	}
	return i;
}
int main()
{
	char str[] = "ABCDEFGHIJK";
	int sz=my_strlen(str);
	printf("%d", sz);
	return 0;
}

模拟实现一些库函数(1)_第2张图片

我们知道strlen函数是以接收到’\0’为信号来计算的,所以我们传参传过去的是数字名也就是数组首元素地址,在自定义函数中我们只是计算数组长度,并不希望改变原数组,所以我们可以用const来修饰,为了防止穿过来的是空指针,我们用assert函数,不过需要引入一个的头文件。

长度不受限制的函数

strcpy

strcpy函数是字符串拷贝函数,我们直接看效果,上代码,来模拟。

int main()
{
	char str1[] = "************";
	char str2[] = "hello world";
	strcpy(str1, str2);
	printf("%s\n", str1);
	return 0;
}

模拟实现一些库函数(1)_第3张图片
接下来我们直接来实现

char* my_strcpy(char* str1, const char* str2)
{
	char* ret = str1;
	assert(str1 && str2);
	while ((*str1++ = *str2++))
	{
		;
	}
	return 0;
}
int main()
{
	char str1[] = "************";
	char str2[] = "hello world";
	my_strcpy(str1, str2);
	printf("%s\n", str1);
	return 0;
}

首先,strcpy需要两个参数一个是拷贝数组,一个是拷贝目标数组,而拷贝目标数组我们不希望他被改变所以用const来修饰,为了防止传参过来的是空指针所以两个参数我们都用assert函数来检验。之后再用while循环来实现字符拷贝,因为strcpy函数返回的是拷贝字符串首地址,所以我们设置ret来接受首地址,最后返回ret即可。

strcat

strcat是拼接函数,我们依然先看效果。

int main()
{
	char str1[20] = "ABCD";
	char str2[] = "EFGH";
	strcat(str1, str2);
	printf("%s", str1);
	return 0;
}

模拟实现一些库函数(1)_第4张图片
了解了效果之后,我们来实现模拟。

char* my_strcat(char* str1,const char* str2)
{
	char* ret = str1;
	assert(str1 && str2);
	while (*str1 != '\0')
	{
		str1++;
	}
	while ((*str1++ = *str2++))
	{
		;
	}
	return ret;
}
int main()
{
	char str1[20] = "ABCD";
	char str2[] = "EFGH";
	my_strcat(str1, str2);
	printf("%s", str1);
	return 0;
}

模拟实现一些库函数(1)_第5张图片
其实,追加函数和拷贝函数的原理很相似,只不过是从拷贝函数的末尾开始拷贝,所以我们设置一个循环,跳过追加目标函数的所有字符从’\0’,开始拷贝,接下来就和strcpy函数一样了。

strcmp

首先该函数是比较函数其中,str1和str2是要进行比较的字符串。函数返回一个整数值来表示比较结果,返回值的含义如下:

若返回值为 0,表示两个字符串相等;
若返回值小于 0,表示str1小于str2;
若返回值大于 0,表示str1大于str2。

我们先看效果

int main()
{
	char str1[] = "ABCD";
	char str2[] = "ABCD";
	char str3[] = "ABC";
	char str4[] = "ABCDF";
	int ret1 = strcmp(str1, str2);
	int ret2 = strcmp(str1, str3);
	int ret3 = strcmp(str1, str4);
	printf("%d\n", ret1);
	printf("%d\n", ret2);
	printf("%d\n", ret3);
	return 0;
}

模拟实现一些库函数(1)_第6张图片
了解了效果后,我们来开始模拟

int my_strcmp(const char* str1, const char* str2)
{
	int ret = 0;
	assert(str1 && str2);
	while (!(ret = *(unsigned char*)str1 - *(unsigned char*)str2) && *str2)
	{
		++str1;
		++str2;
	}
	if (ret < 0)
		return -1;
	else if (ret > 1)
		return 1;
	else
		return ret;
}
int main()
{
	char str1[] = "ABCD";
	char str2[] = "ABCD";
	char str3[] = "ABC";
	char str4[] = "ABCDF";
	int ret1 = my_strcmp(str1, str2);
	int ret2 = my_strcmp(str1, str3);
	int ret3 = my_strcmp(str1, str4);
	printf("%d\n", ret1);
	printf("%d\n", ret2);
	printf("%d\n", ret3);
	return 0;
}

模拟实现一些库函数(1)_第7张图片
我们知道了strcmp的返回值是str1和str2进行比较后得出的,所以函数类型就是int型,在这里只是比较,不希望原字符串有任何改变,所以我们都用const来修饰两个参数,之后我们进入while循环来比较,因为当两个字符串的当前字符相等且尚未到达字符串的结束符时,继续执行循环体,即逐个比较两个字符串的字符,直到出现不同的字符或其中一个字符串到达结束符为止。所以我们设置了这样的循环条件,之后逐个比较str1和str2。

长度受限制的字符串函数

strncpy

该函数和strcpy函数的区别在于多了一个拷贝字符个数限制的条件,由于效果仅在于拷贝个数的限制,所以我们不在看效果,直接开始模拟。

char* my_strncpy(char* str1, size_t size, const char* str2)
{
	char* ret = str1;
	assert(str1 && str2);
	int i = 0;
	while (i < size&&*str2)
	{
		*str1++ = *str2++;
		i++;
	}
	*str1 = '\0';
	return ret;
}
int main()
{
	char str1[] = "***************";
	char str2[] = "hello world!";
	int k = 0;
	printf("请输入拷贝字符个数:");
	scanf("%d", &k);
	my_strncpy(str1, k, str2);
	printf("%s", str1);
	return 0;
}

模拟实现一些库函数(1)_第8张图片
我们只需要多加一个size_t的参数,来限制拷贝个数即可,注意拷贝完成后,由于个数的限制没有到达结束,所以我们要令循环结束后的str指针也就是拷贝完成后的str指针所指向的内容是’\0’。

strncat

同样的这个函数也只是多了一个追加的个数限制条件。我们直接来模拟这个函数的实现。

char* my_strncat(char* str1, size_t size, const char* str2)
{
	char* ret = str1;
	assert(str1 && str2);
	int i = 0;
	while (*str1)
	{
		str1++;
	}
	while (i < size&&*str2)
	{
		*str1++ = *str2++;
		i++;
	}
	*str1 = '\0';
	return ret;
}
int main()
{
	char str1[20] = "ABCD";
	char str2[] = "EFGHIJKL";
	int k = 0;
	printf("请输入追加字符的个数:");
	scanf("%d", &k);
	my_strncat(str1, k, str2);
	printf("%s", str1);
	return 0;
}

模拟实现一些库函数(1)_第9张图片
同样的,我们在知道了strcat函数的模拟以及strncpy函数的模拟,仅需要添加一个限制追加字符个数,并且将追加循环完成后str1所指向的内容赋值为’\0’即可。 其他的地方基本和上面几个函数的实现相似。

strncmp

这个函数与strcmp的区别也是多了一个比较个数的限制条件。为了防止大家误会这个函数的效果,我们来看一下这个函数的具体效果,再来模拟实现。

#include 
#include 

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

    int result = strncmp(str1, str2, 3);

    if (result == 0) {
        printf("前 3 个字符相等\n");
    }
    else if (result < 0) {
        printf("str1 小于 str2\n");
    }
    else {
        printf("str1 大于 str2\n");
    }

    return 0;
}

模拟实现一些库函数(1)_第10张图片
接下来,我们来具体模拟一下该函数

#include 
#include 
int my_strncmp(const char* str1, const char* str2, size_t size)
{
    int ret = 0;
    assert(str1 && str2);
    int i = 0;
    while (i < size)
    {
        ret = *(unsigned char*)str1 - *(unsigned char*)str2;
        if (ret != 0)
        {
            return ret > 0 ? 1 : -1;
        }
        if (*str1 == '\0')
            break;


        ++str1;
        ++str2;
        i++;
    }
    return 0;
}
int main()
{
    char str1[] = "hello";
    char str2[] = "world";
    int k = 0;
    printf("请输入str1和str2字符比较个数:");
    scanf("%d", &k);
    int result = my_strncmp(str1, str2, k);

    if (result == 0) {
        printf("前 3 个字符相等\n");
    }
    else if (result < 0) {
        printf("str1 小于 str2\n");
    }
    else {
        printf("str1 大于 str2\n");
    }

    return 0;
}

模拟实现一些库函数(1)_第11张图片
首先也是多了一个限制比较个数的参数,但是有一点不同的是,由于比较完前k个字符,接下来的字符不一定是’\0’,所以我们的代码和实现strcmp有一点不同,一个一个字符来比较即可。

字符串查找函strstr

首先我们了解一下strstr函数的作用:
strstr 函数是C语言标准库 中提供的一个字符串处理函数,用于在一个字符串中查找指定子字符串的第一次出现位置。

函数原型如下:

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

strstr 函数接受两个参数:str1 是要搜索的字符串,str2 是要查找的子字符串。

函数返回一个指向 str1 中第一次出现 str2 的位置的指针。如果未找到子字符串,返回 NULL。
来看一下效果:

int main() {
    char str1[] = "Hello, World!";
    char str2[] = "World";

    char* result = my_strstr(str1, str2);

    if (result != NULL) {
        printf("'%s' 第一次出现在 '%s' 中的位置是:%ld\n", str2, str1, result - str1);
    }
    else {
        printf("'%s' 未在 '%s' 中找到\n", str2, str1);
    }

    return 0;
}

模拟实现一些库函数(1)_第12张图片
接下来我们来模拟实现一下。

#include 

// 自定义实现 strstr 函数
char* my_strstr(const char* str1, const char* str2) {
    assert(str1);
    // 如果 str2 为空字符串,则直接返回 str1
    if (*str2 == '\0') {
        return (char*)str1;
    }

    // 遍历 str1
    while (*str1 != '\0') {
        const char* p1 = str1;
        const char* p2 = str2;

        // 在 str1 中查找 str2
        while (*p1 == *p2 && *p1 != '\0') {
            p1++;
            p2++;
        }

        // 如果 p2 指向了 str2 的结尾,说明找到了 str2,返回位置
        if (*p2 == '\0') {
            return (char*)str1;
        }

        // 在 str1 中继续查找
        str1++;
    }

    // 没有找到 str2,返回 NULL
    return NULL;
}

int main() {
    char str1[] = "Hello, World!";
    char str2[] = "World";

    char* result = my_strstr(str1, str2);

    if (result != NULL) {
        printf("'%s' 第一次出现在 '%s' 中的位置是:%ld\n", str2, str1, result - str1);
    }
    else {
        printf("'%s' 未在 '%s' 中找到\n", str2, str1);
    }

    return 0;
}

模拟实现一些库函数(1)_第13张图片
首先,我们需要两个字符串数组参数,在str1中寻找str2,由于我们只是寻找,并不希望原字符串发生改变,所以我们在接受参数时用const来修饰一下,如果str2指向的是空指针那么我们直接返回str1,如果不是进入我们的代码中,遍历str1,我们把str1和str2赋给p1和p2,然后设置一个如果存在才能进入的循环,然后给一个if语句,如果p2解引用等于‘\0’,说明str2到了末尾,也就是找到了,我们返回这个时候的str1指针所指向的位置,之后在if语句外str1++,如果没有碰到str2就遍历str1,这样我们最后遍历完str1,就能知道str2是否存在于str1中了。

总结

相信大家能看出来模拟这些函数有很多地方都是很相似的,那么就分享到这里,各位看客老爷万福金安。

模拟实现一些库函数(1)_第14张图片

你可能感兴趣的:(c语言)