C语言库函数:strcspn和strspn的区别

1.函数原型

size_t strcspn(const char *str1, const char *str2);
size_t strspn(const char *str1, const char *str2);

2.函数功能

  • strcspn: 检索字符串 str1 中第一个在字符串 str2 中出现的字符下标。返回 str1 中第一个在字符串 str2 中出现的字符的下标。
  • strspn: 检索字符串 str1 中第一个不在字符串 str2 中出现的字符下标。返回 str1 中第一个不在字符串 str2 中出现的字符下标。

3.strcspn和strspn的区别

举例说明两者不同:

  • 假设str1[20] = “HelloWorld”; str2[20] = “eo”;
    使用strcspn(str1,str2),就是在str1中找到第一次出现“e”或者“o”的位置,返回应该是1;
    使用strspn(str1,str2),就是在str1中找到第一个不是“e”并且也不是“o”的位置,返回应该是0。
int main()
{
	char str1[20] = "HelloWorld";
	char str2[20] = "eo";

	printf("\r\nstrcspn test\r\n");
	printf("str1:%s\r\n",str1);
	printf("str2:%s\r\n",str2);
	printf("第一个匹配的字符是在 %d\n", strcspn(str1,str2));

	printf("\r\nstrspn test\r\n");
	printf("str1:%s\r\n",str1);
	printf("str2:%s\r\n",str2);
	printf("第一个不匹配的字符是在 %d\n", strspn(str1,str2));

	system("pause");
	return 0;
}

运行结果如下:
在这里插入图片描述
结果与预想一致。
注意: str1所查找的字符包含str2中的所有字符。

  • 当str1中没有str2中的字符时,显然,strspn(str1,str2)应该返回0,而strcspn(str1,str2)返回字符串str1的最大长度。
    假设str1[20] = “HelloWorld”; str2[20] = “a”;
    使用strcspn(str1,str2),就是在str1中找到第一次出现“a”的位置,返回应该是10(即strlen(str1));
    使用strspn(str1,str2),就是在str1中找到第一个不是“a”的位置,返回应该是0。
int main()
{
	char str1[20] = "HelloWorld";
	char str2[20] = "a";

	printf("\r\nstrcspn test\r\n");
	printf("str1:%s\r\n",str1);
	printf("str2:%s\r\n",str2);
	printf("第一个匹配的字符是在 %d\n", strcspn(str1,str2));

	printf("\r\nstrspn test\r\n");
	printf("str1:%s\r\n",str1);
	printf("str2:%s\r\n",str2);
	printf("第一个不匹配的字符是在 %d\n", strspn(str1,str2));

	system("pause");
	return 0;
}

运行结果如下:
在这里插入图片描述

  • 当str1中所有字符都在str2中,显然,strcspn(str1,str2)应该返回0,而strspn(str1,str2)返回字符串str1的最大长度。
    假设str1[20] = “HelloWorld”; str2[20] = “HelloWorld”;
    使用strspn(str1,str2),返回应该是10(即strlen(str1));
    使用strcspn(str1,str2),返回应该是0。

4.源码

/************************************************************************
 *功能:检索字符串 str1 开头连续有几个字符都不含字符串 str2 中的字符
 *输入:str1:要被检索的 C 字符串。
 *		str2:该字符串包含了要在 str1 中进行匹配的字符列表。
 *输出:无
 *返回:返回 str1 开头连续都不含字符串 str2 中字符的字符数。
************************************************************************/
size_t Mystrcspn(const char *str1, const char *str2)
{
	// map有32个字节的大小,也就是256个bit,可把map看做一个2维数组[32][8]
    unsigned char map[32] = {0};
	int count = 0;

    // 每个ASCII码(设为c)有7bit,共128个。
    // map数组作为位图记录每个ASCII码是否出现过。map一个字节可以记录8个ASCII码
	// 如“0”的ASCII码是48,那么map[48/8]就是“0”在位图中的第几个字节
	// 而48 & 7(换成二进制就是0011 0000 & 0000 0111,一个字节8bit,所以&7)可以定位到这个字节的第几个bit
    while(*str2)
    {
        map[*str2 >> 3] |= (1 << (*str2 & 7));
        str2++;
    }
    map[0] |= 1;//0在ascii中表示空,所以前面*str退出时一定是空,所以置位
    while(!(map[*str1 >> 3] & (1 << (*str1 & 7))))
    {
        count++;
        str1++;
    }
    return count;
}
/************************************************************************
 *功能:检索字符串 str1 中第一个不在字符串 str2 中出现的字符下标
 *输入:str1:要被检索的 C 字符串。
 *		str2:该字符串包含了要在 str1 中进行匹配的字符列表。
 *输出:无
 *返回:返回 str1 中第一个不在字符串 str2 中出现的字符下标。
************************************************************************/
size_t Mystrspn(const char *str1, const char *str2)
{
	// map有32个字节的大小,也就是256个bit,可把map看做一个2维数组[32][8]
    unsigned char map[32] = {0};
	int count = 0;

    // 每个ASCII码(设为c)有7bit,共128个。
    // map数组作为位图记录每个ASCII码是否出现过。map一个字节可以记录8个ASCII码
	// 如“0”的ASCII码是48,那么map[48/8]就是“0”在位图中的第几个字节
	// 而48 & 7(换成二进制就是0011 0000 & 0000 0111,一个字节8bit,所以&7)可以定位到这个字节的第几个bit
    while(*str2)
    {
        map[*str2 >> 3] |= (1 << (*str2 & 7));
        str2++;
    }
    //map[0] |= 1;//0在ascii中表示空,所以前面*str退出时一定是空,所以置位
    while((map[*str1 >> 3] & (1 << (*str1 & 7))))
    {
        count++;
        str1++;
    }
    return count;
}
  • 9
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fengwang0301

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值