安全的易用的字符串分割函数

来源:互联网 发布:exchange2010多域名 编辑:程序博客网 时间:2024/04/29 08:24

《程序员修炼之道》在28节时间耦合里,主要讲的是尽量在设计时就考虑并发,中间提到c标准库string.h中strtok的糟糕设计:线程不安全,无法同时解析两个不同的字符串,会修改传入的字符串。这个函数确实设计的比较不好,虽然效率可能很好,但你要是不熟悉这个函数,极有可能会出错。这里我就以它为蓝本写一个新的函数。
原函数的线程不安全在于使用了静态数据,而且该静态数据没有受到针对并发访问的保护。无法同时解析两个不同的字符串在于每次调用都是动态查找。那我就直接将所有的结果都保存到一个vector<string>里就都OK了。代码如下:

// by 东方肖遥 http://blog.csdn.net/liuyuan185442111vector<string> split(const string &s, const char *token){    vector<string> result;    const char *sbegin = s.c_str();    const char *send = sbegin;    while(1)    {        sbegin += strspn(send, token);        send = sbegin + strcspn(sbegin, token);        result.push_back(string(sbegin, send));        if(!*send) break;        sbegin = ++send;    }    return result;}

嫌vector返回时会有拷贝的负担?c++11里的右值引用可以解决这个问题。

再附上几个相关的函数:

//从s1的开头搜索一个和s2中的任意元素都不匹配的字符,返回此字符的下标。size_t strspn(const char *s1, const char *s2){    const char *sc1, *sc2;    for(sc1 = s1; *sc1 != '\0'; ++sc1)        for(sc2 = s2; ; ++sc2)            if(*sc2 == '\0')                return sc1 - s1;            else if(*sc1 == *sc2)                break;    return sc1 - s1;}//查找两个字符串第一个相同的字符在s1中的位置,如果没有则返回终止的空字符的索引size_t strcspn(const char *s1, const char *s2){    const char *sc1, *sc2;    for(sc1 = s1; *sc1 != '\0'; ++sc1)        for(sc2 = s2; *sc2 != '\0'; ++sc2)            if(*sc1 == *sc2)                return sc1 - s1;    return sc1 - s1;}char *strtok(char *s1, const char *s2){    char *sbegin, *send;    static char *ssave = "";    sbegin = s1 ? s1 : ssave;    sbegin += strspn(sbegin, s2);    if(*sbegin == '\0')    {        ssave = "";        return NULL;    }    send = sbegin + strcspn(sbegin, s2);    if(*send != '\0')        *send++ = '\0';    ssave = send;    return sbegin;}

第27节“元程序设计”要表达的应该是参数化,比如标准库里经常用到的用宏来替代多次出现的常量。

0 0
原创粉丝点击