IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言_模拟实现字符串操作库函数 -> 正文阅读

[C++知识库]C语言_模拟实现字符串操作库函数

这篇博客是我自己对字符串操作库函数的模拟实现,包括(长度不受限制[^1])的操作函数 strlen()、strcmp()、strcat()、strstr(),以及 memcpy()、memmove(). 这些函数都来源于<string.h>.

strlen()

函数介绍

作用: 计算字符串长度
函数原型:size_t strlen( const char *string );
参数: string 以’\0’结尾的字符串
类型: const char* 因为不会修改字符串,因此用const修饰
返回值: 返回字符串中的字符数,不包括’\0’。没有返回则说明发生错误错误。size_t[^2] 指的是无符号整型。

函数实现

int my_strlen(const char* str)
{
	assert(str != NULL); // 断言。如果输入地址为空则报错

	int count = 0;
	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}

int main()
{
	char str[] = "abcdefg";

	printf("%d ", my_strlen(str));

	return 0;
}

strcmp()

函数介绍

作用: 比较两个字符串的长度大小。
函数原型: int strcmp( const char *string1, const char *string2 );
参数: string1、string2 都是以’\0’结尾的字符串
类型: const char* 不会修改字符串,因此用const修饰
返回值: int整型:如果string1长,返回>0的数;如果string2长,返回<0的数;如果两字符串长度相等,返回0。

函数实现

int my_strcmp(const char* str1, const char* str2)
{
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
			return 0;

		str1++;
		str2++;
	}

	if (*str1 > *str2)
	{
		return 1;
	}
	else
	{
		return -1;
	}

}

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abd";

	char arr3[] = "Hello World!";
	char arr4[] = "Hello World!";

	int ret = my_strcmp(arr1, arr2);
	printf("%s %s %d\n", arr1, arr2, ret);

	int ret1 = my_strcmp(arr3, arr4);
	printf("%s %s %d\n", arr3, arr4, ret1);
	
	return 0;
}

strcat()

函数介绍

作用: 把一个字符串追加到一个字符串后面。
函数原型: char *strcat( char *strDestination, const char *strSource );
参数: strDestination、strSource 都是以 ‘\0’ 结尾的字符串。destination是目的地的意思,所以strDestination指的是要被追加的字符串,strSource指的是追加的内容。
类型: strDestination会被修改,所以是char* 类型;const char* 不会修改字符串,因此用const修饰
返回值: char*类型变量,是strDestination字符串的地址。

函数实现

char* my_strcat(char* str1, const char* str2)
{
	assert(str1 != NULL);
	assert(str2 != NULL);

	char* ret = str1;

	while (*str1)
	{
		str1++; // 如果在括号中++的话,指针最终会停留在'\0'后面
	}

	while (*str1++ = *str2++)
	{
		;
	}

	return ret;
}

int main()
{
	char arr1[20] = "Hello ";
	char arr2[] = "World!";

	printf("%s ", my_strcat(arr1, arr2));

	return 0;
}

strstr()

函数介绍

作用: 判断一个字符串中是否包含另一个字符串
函数原型: char *strstr( const char *string, const char *strCharSet );
参数: string、strCharSet 都是以 ‘\0’ 结尾的字符串。
类型: const char* 不会修改字符串,因此用const修饰
返回值: 函数返回一个指针,指向string字符串中第一个出现的strCharSet,如果strCharSet没有出现在字符串中,则返回NULL。如果strCharSet指向长度为零的字符串,则函数返回string。

函数实现

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 != NULL);
	assert(str2 != NULL);

	const char* s1 = str1; // 这个指针在str1上走
	const char* s2 = str2; // 这个指针在str2上走
	const char* cp = str1; // 这个指针是开始匹配的位置,从str1的第一个字符到最后一个字符

	if (*s2 == '\0')  // 如果str2为空字符串的话,直接返回str1
		return (char*)str1;

	while (*cp != '\0')
	{
		s1 = cp;   // 从cp指向的str1上的位置开始比较
		s2 = str2; // 每一次迭代,都要从str2的第一个字符开始比较

		while (*s1 && *s2 && *s1 == *s2)
		{
			s1++;
			s2++;
		}

		// 如果能走到这有三种情况:1.s1已经找完了 2.s2已经找完了,说明匹配成功了 3.匹配失败
		if (*s2 == '\0') // 第二种情况
		{
			return (char*)cp;
		}

		cp++; // 如果匹配失败,则从str1的下一个字符开始匹配,如此迭代
	}
	return NULL;
}

int main()
{
	char arr1[] = "abcdefghi";
	char arr2[] = "cde";

	printf("%s", my_strstr(arr1, arr2));
	
	return 0;
}

memcpy()

函数介绍

作用: 拷贝一块内存上的数据到另一块内存,因此称为内存拷贝函数
函数原型: void *memcpy( void *dest, const void *src, size_t count );
参数: dest: destination的缩写,指的是目标内存;src:source的缩写,指的是要拷贝的内存;count:指的是要拷贝的内容的字节数。
类型: void*: void* 可以接收各种类型的指针变量,因为事先是不知道要输入哪种类型的指针; const void* 不会修改该内存上的值,因此用const修饰;size_t: 因为拷贝是逐字节拷贝的,所以要传入需要拷贝的字节数
返回值: dest的地址。

函数实现

void* my_memcpy(void* dest, void* src, int count)
{
	assert(dest != NULL);
	assert(src != NULL);

	void* ret = dest; // 记录目标的起始地址

	while (count--)
	{
		*(char*)dest = *(char*)src; // 强制转换类型为char*,逐个字节拷贝
		dest = (char*)dest + 1;  // 强制转换类型为char*之后,地址以字节为单位增加
		src = (char*)src + 1;
	}

	return ret;

}

int main()
{
	char arr1[20] = { 0 };
	char arr2[] = "Hello World!";

	printf("%s ", my_memcpy(arr1, arr2, sizeof(arr2)));

	return 0;
}

memmove()

函数介绍

作用: 拷贝一块内存上的数据到另一块内存,但是memcpy函数的区别是:这memmove可以从同一个字符串上拷贝,也就是说可以把一个字符串上的部分内容拷贝到另一部分
函数原型: void *memcpy( void *dest, const void *src, size_t count );
参数: dest: destination的缩写,指的是目标内存;src:source的缩写,指的是要拷贝的内存;count:指的是要拷贝的内容的字节数。
类型: void*: void* 可以接收各种类型的指针变量,因为事先是不知道要拷贝哪种类型的数据; const void* 不会修改该内存上的值,因此用const修饰;size_t: 因为拷贝是逐字节拷贝的,所以要传入需要拷贝的字节数
返回值: dest的地址。

在实现这个函数之前,我们需要明确拷贝过程中会遇到的两种情况。

  • 情况一:dest指向的地址在src之前。
    如果我们要把红框中的四个数据拷贝到绿框中去,那么从src指向的地址开始(从前往后),逐字节往dest指向的地址处拷贝就行。
    情况一
  • 情况二:dest指向的地址在src之后。
    和上面一样,我们要把红框中的数据拷贝到绿框中去,此时如果继续从src指向的地址开始,从前往后逐字节往dest指向的地址拷贝数据的话,会覆盖掉红框后面的数据,我们本来的设想是把数字5放到数字8的位置,从前往后拷贝最终会导致将数字2放到数字8的位置。所以我们应该从后往前拷贝,也就是说先把数字5放到8的位置,然后把4放到7的位置,以此类推。
    情况二

代码实现

// memmove函数实现

void* my_memmove(void* dest, void* src, int count)
{
	assert(dest != NULL);
	assert(src != NULL);

	void* ret = dest;
	// 目标是把src指向的内存上的数据复制到dest指向的内存
	// 考虑到内存覆盖问题,需要分两种情况: 1. dest在src之前 2. dest在src之后

	if (dest < src) // 情况1
	{
		// 此时不用担心从src开始的某一段内存在复制的时候被覆盖,因此直接从头开始拷贝就行
		while (count--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}

	}
	else
	{
		// 此时src的地址在dest之前,因此dest有可能在从src开始的要复制的一段内存上,
		// 那么就有可能会覆盖掉要复制的一部分数据,所以要从后往前复制
		while (count--)
		{
			*((char*)dest + count) = *((char*)src + count);
		}

	}

	return ret;
}

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };

	my_memmove(arr + 2, arr + 5, 4 * sizeof(int));

	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

结语

除了上述几个函数,还有一些函数会在后续自己实现。因为最近比较忙,所以隔了这么久才写了这篇博客,其实我有很多想记录的内容。以后要是有时间,我就会写写博客,很多东西在输出的时候才会发现自己有没有理解。最后,如果内容有问题,恳请指正!

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-17 16:02:42  更:2022-07-17 16:07:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/13 11:51:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码