模拟实现C库函数:strchr、strcmp、strstr、memcpy和memmove

本文详细解析了C语言中常用的字符串处理函数,包括查找字符、比较字符串、查找子串、内存拷贝等,并提供了实现代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数原型:char *strchr(const char *s, int c) 

功能: 查找字符串s中首次出现c字符的位置

说明: 返回首次出现c的位置的指针,返回的地址是被查找的字符串指针开始的第一个与c相同字符的指针,若s中不存在c则返回NULL。

返回值: 成功返回要查找的字符第一次出现的位置,否则返回NULL。

#define _CRT_SECURE_NO_WARNINGS 0
#include <stdio.h>
#include <windows.h>
char *my_strchr(const char *s, char c)
{
	if (s == NULL)
	{
		return NULL;
	}

	while (*s != '\0')
	{
		if (*s == c)
		{
			return s;
		}
		s++;
	}
	return NULL;
}
int main()
{
	char str[] = "This is a sample string";
	char * pch;
	printf("Looking for the 's' character in \"%s\"...\n", str);
	pch = my_strchr(str, 's');

	//输出每个's'的位置
	while (pch != NULL)
	{
		printf("found at %d\n", pch - str + 1);
		pch = my_strchr(pch + 1, 's');
	}
	system("pause");
	return 0;
}


函数原型:int strcmp(const char *dest, const char *source) ;

返回值:返回整数值,如果dest > source,则返回值大于0,如果dest = source,则返回值等于0,如果dest < source ,则返回值小于0。字符大小是按照字符的字典序列进行排列的。

参数说明:都是以''/0''为结束符的字符串

#define _CRT_SECURE_NO_WARNINGS 0
#include <stdio.h>
#include <windows.h>
#include <assert.h>
int *my_strcmp(const char *str1, const char *str2)
{
	assert(str1);
	assert(str2);
	int ret = 0;
//可以根据ret的值比较大小,进入循环是为了用ret的值来比较大小
	while (!(ret = *str1 - *str2) && *str1 && str2)
	{
		str1++;
		str2++;
	}
	if ((*str1 == '\0') && (*str1 == '\0'))
	{
		return 0; //一样大
	}
	else
	{
		if (ret > 0)
		{
			ret = 1; //str1大
		}
		else
		{
			ret = -1; //str2大
		}
		return ret;
	}
}
int main()
{
	//注意,判断是否相等,是比较大小,不是比较长度
	const char *str1 = "123456";
	const char *str2 = "12345678";
	int eq = my_strcmp(str1, str2);
	printf("%d\n", eq);
	system("pause");
	return 0;
}

C语言库函数用于在字符串中查找子串。

函数原型:char *strstr(const char *s1, const char *s2)

函数的参数是两个字符串,函数返回s2在s1中第一次出现的位置。如果在s1中没有找到s2,返回空。

如果s2为空,则返回s1。 

#define _CRT_SECURE_NO_WARNINGS 0
#include <stdio.h>
#include <windows.h>
#include <assert.h>
char *my_strstr(const char *str, const char *subStr)
{
	assert(str);
	assert(subStr);
	assert(strlen(str) >= strlen(subStr));

	if (*subStr == '\0')
		return NULL;

	while (*str)
	{ 
		const char *start = str;
		const char *target = subStr;
		while (*target) 
		{
			if (*start && *target && (*start == *target))
			{
				start++;
				target++;
			}
			else
			{
				break;
			}
		} 
//到这里是遍历完所有subStr(或者target)所有字符,如果找到subStr(或者target)= \0
		if (*target == '\0')
		{
			return str; //找到
		}
		str++; //未找到
	}
//以上是对str一个字符的查找

	return NULL; //找完str里面所有字符,未找到
}
int main()
{

	char *s1 = my_strstr("abcdefg12345", "fg1");
	printf("%s\n", s1);

	char *s2 = my_strstr("abcdefg12345", "fg15");
	printf("%s\n", s2);

	system("pause");
	return 0;
}

函数原型:void *memcpy(void*dest, const void *src, size_t n);

功能:由src指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始地址的空间内。

头文件:#include<string.h>

返回值:函数返回一个指向dest的指针。

说明:

  1.source和destination所指内存区域不能重叠,函数返回指向destin的指针。

  2.与strcpy相比,memcpy并不是遇到'\0'就结束,而是一定会拷贝完n个字节。

memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度;

例:

  char a[100], b[50];

  memcpy(b, a,sizeof(b)); //注意如用sizeof(a),会造成b的内存地址溢出。

  strcpy就只能拷贝字符串了,它遇到'\0'就结束拷贝;例:

  char a[100], b[50];

       strcpy(a,b);

  3.如果目标数组destin本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。如果要追加数据,则每次执行memcpy后,要将目标数组地址增加到你要追加数据的地址。

注意:source和destination都不一定是数组,任意的可读写的空间均可。

#define _CRT_SECURE_NO_WARNINGS 0
#include <stdio.h>
#include <windows.h>
#include <assert.h>
void *my_memcpy(void *dst, const void *src, size_t count)
{
	assert(dst);
	assert(src);
	void *ret = dst;
	while (count--)
	{
		*((char*)dst) = *((char*)src); //强转成char*后再*(解引用)才能比较
		dst = (char*)dst + 1; //强转成char*后指针才能向后加1
		src = (char*)src + 1;
	}
	return ret;
}
int main()
{
	char *str = "hello world!";
	char arr[64];
	my_memcpy(arr, str, strlen(str) + 1);
	printf("%s\n", arr);
	system("pause");
	return 0;
}

memmove 函数原型:extern void *memmove(void *dest, const void *src, unsigned int count);

头文件:#include <string.h>

功能:由src所指内存区域复制count个字节到dest所指内存区域。

说明:src和dest所指内存区域可以重叠,但复制后src内容会被更改。函数返回指向dest的指针。

注意:

1、它的返回值是void*,参数类型也是void*,这样它才可以处理不同类型的数据。

2、目标dest不能加const,源src加const。原因是我们需要从源src中拷贝数据到dest中,需要对dest进行赋值。若用const保护                                 dest,便不能完成赋值操作。

               memmove的好处是可以处理dest与src发生内存重叠的情况

#define _CRT_SECURE_NO_WARNINGS 0
#include <stdio.h>
#include <windows.h>
#include <assert.h>
void *my_memmove(void *dst, const void *src, size_t count)
{
	assert(dst);
	assert(src);
	assert(count > 0);
	char *ret = (char*)dst;
	char *source = (char*)src;
	char *destination = (char*)dst;
	int i = 0;
	while (count > 0)
	{
		if (source < destination && source + count > destination)
		{
			*(destination + count - 1) = *(source + count - 1);
		}
		else
		{
			*(destination + i) = *(source + i);
			i++;
		}
		count--;
	}
}
int main()
{
	char str[64] = "hello world!";
	char arr[64];
	my_memmove(arr, str, strlen(str) + 1);
	printf("%s\n", arr);
	my_memmove(str + 3, str, strlen(str) + 1);
	printf("%s\n", str);
	system("pause");
	return 0;
}







电动汽车数据集:2025年3K+记录 真实电动汽车数据:特斯拉、宝马、日产车型,含2025年电池规格销售数据 关于数据集 电动汽车数据集 这个合成数据集包含许多品牌年份的电动汽车插电式车型的记录,捕捉技术规格、性能、定价、制造来源、销售安全相关属性。每一行代表由vehicle_ID标识的唯一车辆列表。 关键特性 覆盖范围:全球制造商车型组合,包括纯电动汽车插电式混合动力汽车。 范围:电池化学成分、容量、续航里程、充电标准速度、价格、产地、自主水平、排放、安全等级、销售保修。 时间跨度:模型跨度多年(包括传统即将推出的)。 数据质量说明: 某些行可能缺少某些字段(空白)。 几个分类字段包含同的、特定于供应商的值(例如,Charging_Type、Battery_Type)。 各列中的单位混合在一起;注意kWh、km、hr、USD、g/km额定值。 列 列类型描述示例 Vehicle_ID整数每个车辆记录的唯一标识符。1 制造商分类汽车品牌或OEM。特斯拉 型号类别特定型号名称/变体。型号Y 与记录关联的年份整数模型。2024 电池_类型分类使用的电池化学/技术。磷酸铁锂 Battery_Capacity_kWh浮充电池标称容量,单位为千瓦时。75.0 Range_km整数表示充满电后的行驶里程(公里)。505 充电类型主要充电接口或功能。CCS、NACS、CHAdeMO、DCFC、V2G、V2H、V2L Charge_Time_hr浮动充电的大致时间(小时),上下文因充电方法而异。7.5 价格_USD浮动参考车辆价格(美元).85000.00 颜色类别主要外观颜色或饰面。午夜黑 制造国_制造类别车辆制造/组装的国家。美国 Autonomous_Level浮点自动化能力级别(例如0-5),可能包括子级别的小
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值