关于strtok的用法

1.引入问题,用strtok解决问题

长期处理sip的字符串,经常需要分析text文本,比如从url中取user info,host,url param等等。

例如,以下就是一个典型的tel url.

tel:9812340014;tgrp=tg-1;trunk-context=example.com;phone-context=example.lab

为了获得其中的url param, 比如tgrp而去单独去写一个函数,成本太高,于是想到python中对字符串的操作十分便捷,可以直接调用split()方法,分段成一个list。

于是打算也写一个类似的函数,并做简单ut测试发现如下:

#include <stdio.h>
#include <string>
#include <string.h>
#include <list>
#define ccLog(fmt, args...)\
        printf(fmt"\n",##args)
        
#define ccWarning(fmt, args...)\
        printf(fmt"\n",##args)
using namespace std;


void strSplit(char* str, const char* pattern, list<string>& subStrList)
{
    if(NULL == str || NULL == pattern) return;
    ccLog("input str:%s", str);
    char* pch = strtok(str, pattern);
    while (pch != NULL)
    {
        ccLog("%s",pch);
        string substr = pch;
        subStrList.push_back(substr);
        pch = strtok (NULL, pattern);
    }
}

int main()
{
    const char* uristr = "tel:9812340014;tgrp=tg-1;trunk-context=mavenir.com;phone-context=mavenir.lab";
    
    list<string> strlist;
    strSplit((char*)uristr, ":;", strlist);
    list<string>::iterator it = strlist.begin();
    list<string>::const_iterator itEnd = strlist.end();
    for(;it!=itEnd;++it)
    {
        ccLog("substr:%s", it->c_str());
    }
    
    return 0;
}


2.出现异常

看起来似乎没什么问题,但是编译运行后就发现segmentfault。

打开gdb调试发现问题出现在下面第一次调用strtok这一行。

Breakpoint 1, strSplit (str=0x401800 "tel:9812340014;tgrp=tg-1;trunk-context=example.com;phone-context=example.lab",
    pattern=0x40184d ":;", subStrList=empty std::list) at urlparam.cpp:17
17          char* pch = strtok(str, pattern);


3.分析问题

于是查看了C++ Reference的定义和例子http://www.cplusplus.com/reference/cstring/strtok/

发现,每次返回的指针pch都能直接打印,即使不知道源码,也能猜到,strtok是把每个匹配的字符直接替换成‘\0’, 而且是在原来的字符串上修改,于是问题迎刃而解。

如果更细心的话,也会发现,C++ Reference定义说明上关于入参str这么说:Notice that this string is modified by being broken into smaller strings (tokens).

而且例子里用的是

 char str[] ="- This, a sample string.";
而不是不可修改的字符串常量。


4.修改实现

修改strSplit函数如下:

void strSplit(string str, const char* pattern, list<string>& subStrList)
{
    if(str.empty() || NULL == pattern) return;
    ccLog("input str:%s", str.c_str());
    char* pch;
    pch = strtok ((char*)str.c_str(), pattern);
    while (pch != NULL)
    {
        //ccLog("%s",pch);
        string substr = pch;
        subStrList.push_back(substr);
        pch = strtok (NULL, pattern);
    }
}

5.得出期望结果

编译输出结果如下:

input str:tel:9812340014;tgrp=tg-1;trunk-context=example.com;phone-context=example.lab
substr:tel
substr:9812340014
substr:tgrp=tg-1
substr:trunk-context=example.com
substr:phone-context=example.lab



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值