库函数的模拟实现

发布于:2024-05-19 ⋅ 阅读:(146) ⋅ 点赞:(0)

库函数的模拟实现

1 .模拟实现strlen

• 字符串以 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前⾯出现的字符个数(不包 含 ‘\0’ )。

• 参数指向的字符串必须要以 ‘\0’ 结束。

• 注意函数的返回值为 size_t,是⽆符号的(易错

• strlen的使⽤需要包含头⽂件

方法1:计数器

define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
size_t my_strlen( const char*str)
{
	int count = 0;
	assert(str != NULL);
	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}
int main()
{
	char a[] = "student";
	size_t b = my_strlen(a);
	printf("%zd\n", b);
	return 0;
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方法2:指针-指针

#include <stdio.h>
#include <assert.h>
size_t my_strlen( const char*str)
{
	char* start = str;//记录起始位置
	assert(str != NULL);
	while (*str != '\0')
	{
		str++;
	}
	return str-start;
}
int main()
{
	char a[] = "student";
	size_t b = my_strlen(a);
	printf("%zd\n", b);
	return 0;
}

方法3:递归

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
size_t my_strlen( const char*str)
{
	if (*str != '\0')
		return 1 + my_strlen(str + 1);
	else
		return 0;
}
int main()
{
	char a[] = "fourth";
	size_t b = my_strlen(a);
	printf("%zd\n", b);
	return 0;
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

总结:

前两个方法用到了创建临时变量的方法,第三个方法没有用到临时变量的创建

2 .模拟实现strcpy

• 源字符串必须以 ‘\0’ 结束。

• 会将源字符串中的 ‘\0’ 拷⻉到⽬标空间。

• ⽬标空间必须⾜够⼤,以确保能存放源字符串。

• ⽬标空间必须可修改。

• 学会模拟实现

#include <string.h>
int main()
{
	char arr1[] = "hello world";
	char arr2[10] = { 0 };
	strcpy(arr2, arr1);
	printf("%s", arr2);
	return 0;
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <string.h>

int main()
{
char arr1[] = "hello world";
char* p = "xxxxxxxxxxxxxxxxxxxx";//常量字符串-不能修改
strcpy(p, arr1);//err
printf("%s\n", p);

	return 0;
}//不能实现,因为目的地空间大小不可修改

源头的字符串必须含有’\0’,没有\0,strcpy不能结束

//为的是实现链式访问
//strcpy返回的函数是目标空间的起始地址
#include <string.h>
char* my_strlen(char* dest, const char* str)
{
	assert(dest && str);
    char*ret=dest;
	while(*dest = *str)//拷贝过去字符后,判断表达式的值,当\0拷贝过去后,判断为假,停止循环
	{
		;
	}
	return ret;//返回目标空间的地址
}
int main()
{
	char arr1[] = "hello world";
	char arr2[40] = { 0 };
	my_strcpy(arr2, arr1);
	printf("%s", arr2);
	return 0;
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

++的优先级高于*,但是这个++是后置++,效果延后,先进行 *dest

3 .模拟实现strcat

• 源字符串必须以 ‘\0’ 结束。

• ⽬标字符串中也得有 \0 ,否则没办法知道追加从哪⾥开始。

• ⽬标空间必须有⾜够的⼤,能容纳下源字符串的内容。

• ⽬标空间必须可修改。

strcat的使用

int main()
{
	char arr1[66] = "hhhhh    ";
	char arr2[] = "hello world";
	strcat(arr1, arr2);//字符串追加
	printf("%s\n", arr1);
	return 0;
}

使用注意点

1.找到目标空间的末尾\0

2.再将源字符串拷贝过来

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#include <string.h>

//要返回目标空间的起始地址
char* my_strcat(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest && src);
	//1. 找目标空间的\0
	while (*dest != '\0')
		dest++;
//	//2. 拷贝
	while (*dest++ = *src++)
		;
	return ret;
}

int main()
{
	/*char arr1[20] = "he\0lloxxxxx";//只能读到he
	char arr2[] = "world";*/

	char arr[20] = "abc";

	strcat(arr, arr);//字符串追加
	printf("%s\n", arr);

	return 0;
}

4 .模拟实现strcmp

• 标准规定:

◦ 第⼀个字符串⼤于第⼆个字符串,则返回⼤于0的数字

◦ 第⼀个字符串等于第⼆个字符串,则返回0

◦ 第⼀个字符串⼩于第⼆个字符串,则返回⼩于0的数字

◦ 那么如何判断两个字符串? ⽐较两个字符串中对应位置上字符ASCII码值的⼤⼩。

strcmp的使用

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abq";
	int ret=strcmp(arr1, arr2);
	if (ret > 0)
	{
		printf(">\n");
	}
	else
	{
		printf("<=\n");
	}
	return 0;
}

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[] = "abcdef";
	char arr2[] = "abq";
	int ret=my_strcmp(arr1, arr2);
	printf("%d\n", ret);
	return 0;
}

5 .一些注意点

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

举例

  • strncpy 函数的使⽤
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "adcttttt";
	strncpy(arr2, arr1, 4);
	printf("%s\n", arr2);
	return 0;
}

• 拷⻉num个字符从源字符串到⽬标空间。

• 如果源字符串的⻓度⼩于num,则拷⻉完源字符串之后,在⽬标的后边追加0,直到num个。

  • strncat 函数的使⽤
int main()
{
	char arr1[40] = "helloworld";
	char arr2[] = "supernova";
	strncat(arr1, arr2, 4);
	printf("%s\n", arr1);
	return 0;
}

• Appends the first num characters of source to destination, plus a terminating null-character. (将source指向字符串的前num个字符追加到destination指向的字符串末尾,再追加⼀个 \0 字 符)。

• If the length of the C string in source is less than num, only the content up to the terminating null-character is copied.(如果source 指向的字符串的⻓度⼩于num的时候,只会将字符串中到 \0 的内容追加到destination指向的字符串末尾)。

  • strncmp函数的使⽤

    ⽐较str1和str2的前num个字符,如果相等就继续往后⽐较,最多⽐较num个字⺟,如果提前发现不⼀ 样,就提前结束,⼤的字符所在的字符串⼤于另外⼀个。如果num个字符都相等,就是相等返回0.

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcg";
	int ret = strncmp(arr1, arr2,4);
	printf("%d\n", ret);
	return 0;
}

6 .模拟实现strtok

int main()
{
	char arr1[] = "abcdef@woshishuaige";
	char buf[256] = { 0 };
	strcpy(buf, arr1);
	char* sep = "@.";
	char* ret = strtok(buf, sep);
	printf("%s\n", ret);
	return 0;
}

打印结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

• sep参数指向⼀个字符串,定义了⽤作分隔符的字符集合

• 第⼀个参数指定⼀个字符串,它包含了0个或者多个由sep字符串中⼀个或者多个分隔符分割的标 记。

• strtok函数找到str中的下⼀个标记,并将其⽤ \0 结尾,返回⼀个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以被strtok函数切分的字符串⼀般都是临时拷⻉的内容并且 可修改。)

• strtok函数的第⼀个参数不为 NULL ,函数将找到str中第⼀个标记,strtok函数将保存它在字符串 中的位置。

• strtok函数的第⼀个参数为 NULL ,函数将在同⼀个字符串中被保存的位置开始,查找下⼀个标 记。

• 如果字符串中不存在更多的标记,则返回 NULL 指针。

补充要了解的知识

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

进一步的改进:

int main()
{
	char arr1[] = "abcdef@woshishuaige";
	char buf[256] = { 0 };
	strcpy(buf, arr1);
	char* sep = "@.";
	char* ret = NULL;
    for(ret = strtok(buf, sep);ret!=NULL;ret=strtok(NULL,sep))
    {
	printf("%s\n", ret);
    }
	return 0;
}

为什么函数能够记忆上次的位置?

可能具有static关键字
串中不存在更多的标记,则返回 NULL 指针。

补充要了解的知识

[外链图片转存中…(img-Y17xD7pA-1716019561139)]

进一步的改进:

int main()
{
	char arr1[] = "abcdef@woshishuaige";
	char buf[256] = { 0 };
	strcpy(buf, arr1);
	char* sep = "@.";
	char* ret = NULL;
    for(ret = strtok(buf, sep);ret!=NULL;ret=strtok(NULL,sep))
    {
	printf("%s\n", ret);
    }
	return 0;
}

为什么函数能够记忆上次的位置?

可能具有static关键字


网站公告

今日签到

点亮在社区的每一天
去签到