C语言——字符串函数的模拟实现(strlen、strcpy、strcmp、strcat、strstr、strerror、strtok)

引言:对于字符串来说,我们通常想要对其完成各种各样的目的,不管是排序还是查找都是最普遍的功能,而我们的C语言中也包含着一系列函数是为了实现对字符串的一些功能,今天我们就来介绍他们。


strlen函数:

求字符串的长度(也就是求一个字符串的'\0'前面有多少个字符)

#include<stdio.h>
#include<string.h>
int main(){
	char* str = "abcdef";
	int b = strlen(str);
    printf("%d\n", b);
return 0;
}

看一个特性:我们可以看到这个代码,正常来说结果是-3应该输出的是"<"但是结果是">=",

这是因为strlen函数返回的是无符号整型(size_t),两个无符号整型相减还是无符号整形,那么负3就变成了一个很大的正数,如果想要正常的效果我们可以强制转化为(int)。

这个就是strlen最常用的,用来求一个字符串的长度,那么我们是否可以不用库函数,自己模拟一个strlen呢🤔
#include<stdio.h>
#include<string.h>
//方法一:计数法
size_t my_strlen1(char* str) {
	int count = 0;
	while (*str) {
		count++;
		str++;
	}
	return count;
}
int main(){
	char* str = "abcdef";
    int c = my_strlen1(str);
    printf("%d\n", c);
return0;
}

方法一:计数法,利用for循环,用count计数,当str遇到'\0'的时候循环结束,跳出循环,返回count的值。

#include<stdio.h>
#include<string.h>
//方法二:递归法
size_t my_strlen2(char* str) {
	if (*str == '\0')
		return 0;
	else return 1+my_strlen2(str+1);
}
int main() {
	char* str = "abcdef";
	int d = my_strlen2(str);
	printf("%d\n", d);
return 0;
}

 方法二:递归法,利用递归思想,当没有遇到'\0'的时候,就再次调用该函数,直到str遇到'\0',返回0,然后依次再重新返回,就计算出了字符串的长度。

#include<stdio.h>
#include<string.h>
//方法三:指针-指针
size_t my_strlen3(char* str) {
	char* p = str;
	while (*p != '\0') {
		p++;
	}
	return p - str;
}
int main(){
	char* str = "abcdef";
	int e = my_strlen3(str);
	printf("%d\n", e);
	return 0;
}

方法三:指针-指针,我们先将字符串的首元素地址记为str,再将首元素地址传给p,利用while循环找到最后一个元素的地址,当(结束地址-首元素地址)即为字符串长度。

 可以看我们四种方法的运行结果,都是可以正确的求出字符串‘acbdef的长度.

strcpy函数:

#include<stdio.h>
#include<string.h>
int main(){
	char arr1[20] = { 0 };
	char arr2[] = "Hello";
	strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

这个函数的作用就是将arr2中的字符串拷贝到arr1中。那么我们该如何对他进行模拟实现呢🤔

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
char* my_strcpy(char* dest, const char* src) {
	char* ret = dest;
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}
int main(){
	char arr1[20] = { 0 };
	char arr2[] = "Hello";
	//strcpy(arr1, arr2);
	my_strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

 我们先将两个数组的首元素地址传给函数,因为最终要返回起始地址,所以先将dest给ret,然后运用while循环将src的每一项解引用后赋给dest,然后后置++再寻找下一个元素,直到src元素找到了'\0',然后循环跳出,返回起始地址ret。

我们把arr1打印出来可以看到确实是成功拷贝。 

strcmp函数:

比较的结果是:
如果str1>str2那么就返回一个>0的数 
如果str1<str2那么就返回一个<0的数
如果str1=str2那么就返回0
#include<stdio.h>
#include<string.h>
int main() {
	char arr1[] = { "abc" };
	char arr2[] = { "abdef" };
	int a = strcmp(arr1, arr2);
	if (a > 0) printf(">=");
	else printf("<");
	return 0;
}

这是一个简单的例子,因为d的ASC的值比c的ASC的值大,所以arr1<arr2,所以返回的是一个小于0的数,所以 打印出来的就是小于号。

那么我们来模拟实现实现一下这个函数

#include<stdio.h>
#include<string.h>
int my_strcmp(const char* dest, const char* src){
	while (*dest == *src) {
		if (*dest == 0) return 0;
		dest++;
		src++;
	}
	if (*dest > *src)
		return 1;
	else return -1;
}
int main() {
	char arr1[] = { "abc" };
	char arr2[] = { "abdef" };
	int a = my_strcmp(arr1, arr2);
	if (a > 0) printf(">=");
	else printf("<");
	return 0;
}

 首先,还是一样,先传值然后依旧是运用我们的while循环来进行遍历以及交换,当其中一个已经遍历完之后,会跳出while循环,然后开始判断当前元素谁大谁小,然后根据大小返回大于零还是小于零的数。

strcat函数:

#include<stdio.h>
#include<string.h>
int main() {
	char arr1[20] = { "abc"};
	char arr2[] = { "def" };
	//库函数自带的strcat
	strcat(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

 值得注意的是:

1、目标空间必须足够大,并且可以修改

2、目标空间中必须有\0,以便能够找到目标空间的末尾

3、源字符串中也得有\0,拷贝的时候要拷过去

那么我们如何对这个函数进行模拟实现呢🤔

#include<stdio.h>
#include<assert.h>
char* my_strcat(char* dest, char* src) {
	char* ret = dest;
	assert(dest && src);
	while (*dest != '\0') {
		dest++;
	}
	while (*dest++ = *src++) {
		;
	}
	return ret;
}
int main() {
	char arr1[20] = { "abc"};
	char arr2[] = { "def" };
	my_strcat(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

 依然是传参,然后用第一个while循环找到目标空间中的\0然后,跳出循环,此时dest指向目标函数的末尾,然后进入第二个循环,src开始给dest进行赋值,直到src遇到\0,跳出循环,返回目标函数的起始地址,完成追加。

strstr函数: 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main() {
	char arr1[] = { "abcdefghi" };
	char arr2[] = { "def" };
	char* ret = strstr(arr1, arr2);
	if (ret == NULL) {
		printf("找不到");
	}
	else printf("%s", ret);
	return 0;
}

strstr是字符串查找函数,我们给函数传两个字符串的时候,他会拿源函数去和目标函数进行匹配,如果目标函数中有原函数那么,就返回段函数的起始地址,如果找不到,那么就会返回NULL

那么我们该如何模拟实现这一函数呢🤔

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
const char* my_strstr(const char* str1, const char* str2) {
	const char* sp;
	const char* s1;
	const char* s2;
	assert(str1 && str2);
	if (*str2 == '\0') {
		return str1;
	}
	sp = str1;
	while (*sp) {
		s1 = sp;
		s2 = str2;
		while (*str1 && *str2 && *s1 == *s2) {
			s1++;
			s2++;
		}
		if (*s2 == '\0')
			return sp;
		sp++;
	}
	return NULL;
}
int main() {
	char arr1[] = { "abcdefghi" };
	char arr2[] = { "def" };
	char* ret = my_strstr(arr1, arr2);
	if (ret == NULL) {
		printf("找不到");
	}
	else printf("%s", ret);
	return 0;
}

 可以看到,我们模拟实现的函数成功的查找到了目标函数中的def,并且返回了找到它的起始位置。那么具体的实现我来详细的讲解一下。 

如图,我们用s1和s2进行比较,
1️⃣如果两个相同就各自+1比较下一个,那么按照这样进行下去,当str2为0的时候,就证明已经找到了,如果str1已经为0,str2还没有为0那么就证明,str1里找不到str2。
2️⃣如果两个不同就sp++,然后sp再赋值给s1,这样就不会使得s1一直向前++而找不到原来的位置了,s2也是一样,当sp赋值给s1的时候,str2也同时赋值给s2,让s2能回到起始位置。
这样一直对比下去,直到s1或s2指向0,函数结束。那我们这个函数的模拟就算实现了,但是其实这是个笨方法,效率不高,如果大家感兴趣的话,可以去了解了解kmp算法。

strerror函数:

是用来打印错误码的函数

strtok函数:

是一个奇怪的函数:是用来将一段字符串进行分割的函数

例如:

haohao@xue.xi   // @ .

192.168.101.23    //IP地址,点分十进制

(IP地址本来是一个无符号的整数,这种整数不方便记忆,所以将这个整数转换成点分十进制的表示方式)

#include<stdio.h>
#include<string.h>
int main() {
	char arr[] = "haohao@xuexi@tiantian.xiangshang";
	char* p = "@.";
	char* s = NULL;
	for (s = strtok(arr, p); s != NULL; s = strtok(NULL, p)) {
		printf("%s\n",s);
	}
	return 0;
}

我们这里可以看到,strtok将arr里的字符串给分隔开了,这个函数可以把指定参数替换成'\0',这样就可以将那些干扰的字符给去掉,并将其一一打印出来了。

值得注意的是:这个函数每次只能将其一段一段的切割开,所以首次调用的时候需要把待切割字符串的首地址传过去,如果要再次调用的话,则只需要传一个NULL地址过去,函数便会直接从上一次切割的地方开始从后切割。 

 好了,今天我就给大家分享到这里,感谢大家的观看!!!

  • 32
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 25
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值