strspn

strspn

C99描述

#include <string.h>
size_t strspn(const char *s1, const char *s2);

The strspn function computes the length of the maximum initial segment of the string pointed to by s1 which consists entirely of characters from the string pointed to by s2.

函数的参数s2指向的字符串组成了一个接受字符集,注意不包含字符串结束标志 ‘\0’,这个字符比较特殊。s2中字符的重复出现并不影响函数的返回值。
函数完成的功能是根据接受字符集对s1指向的字符串从头开始匹配,直到发现一个不在接受字符集中的字符(或是到达字符串的结尾,这也意味着匹配结束),然后返回匹配字符的数量。

在查看C99标准的这段英文描述时,要注意一个词汇”the string pointed to by s1”中的”string”,指针指向的数据一般由三种情况:
- string
- array
- object
这三个词汇代表的含义略有不同。string一定是字符串,以’\0’结尾;array可能是字符串,也可能是普通的内存块,在函数实现中,如果遇到了’\0’,那么要将它当成字符串,知道目前已经到了结尾了;而object则看做内存块,实现中不会根据值为0的字节而武断的认为到了结尾。
例如:

void *memchr(const void *s, int c, size_t n);
/* ... the object pointed to by s ... */

int strncmp(const char *s1, const char *s2, size_t n);
/* ... the array pointed to by s1 ... */

可见C标准的措辞严谨。
掌握这些措辞的细节,对理解函数的实现和使用是有帮助的。

musl C中实现

#include <string.h>

#define BITOP(a,b,op) \
 ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))

size_t strspn(const char *s, const char *c)
{
    const char *a = s;
    size_t byteset[32/sizeof(size_t)] = { 0 };

    if (!c[0]) return 0;
    if (!c[1]) {
        for (; *s == *c; s++);
        return s-a;
    }

    for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++);
    for (; *s && BITOP(byteset, *(unsigned char *)s, &); s++);
    return s-a;
}

这段代码的难点在于BITOP宏的理解。
byteset数组大小为32个字节,32*8=256个位,我们知道char类型数据的长度是8位,最多有256个不同的char数据,而byteset恰是256位,每个位对应了一个char类型的字符,看到这你有可能猜到了函数的主体是如何实现的。
第一个for循环,根据s2指向的字串统计接受字符集。
试举一例,通过查ascii码我们知道
01100001 97 a
如果遇到了’a’,那么BITOP(…)操作的效果是byteset的第(97-1)位设置为1。这代表’a’是可接受字符。
第二个for循环是从头开始匹配s1中的每个字符。发生不匹配时立刻停止。
使用bitmap可以极大的节约存储空间,其中的位操作乍看之下让人眼花缭乱,但是读懂之后想要重构的更简单,貌似也没有更好的办法。这种算法比嵌套的两层循环要节约很多时间,值得花些时间来理解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值