strtok与strtok_r是字符串操作经常会用到的两个函数. 下面是它们的源码. 但是这两个函数都有个缺点, 如果字符串为Test1:Test2::Test3:::Test4:::: 则用::作为分割符号仍然能得到Test1 Test2 Test3 Test4四个字符串.
另外由于传入的第一个参数会被修改('/0'), 故使用前需要拷贝原来字符串以备份.
char * strtok(char *string, const char * ctrl)
{
assert(ctrl != NULL);
char *str;
static char *token = 0;
unsigned char map[32];
int count = 0;
for (; count < 32; count++)
{
map[count] = 0;
}
do
{
map[*ctrl++ >> 3] |= (1 << (7 & *ctrl)); //由于字符串最大为256, 除以8, 正好为32;
} while (*ctrl);
if (string != NULL)
{
str = string;
}
else
{
str = token;
}
while(*str && (map[*str] & (1 << (7 & *str)))) str++; // 跳过字符串可能含有的匹配部分
for (; *str; str++)
{
if (*str && map[*str] & (1 << (7 & *str)))
{
*str++ = '/0'; //截断字符串并往往下移动一个字符串.
break;
}
}
nexttoken = str; // 保存位置
if (str == string)
{
return NULL;
}
return str;
}
bool is_character_in_string(char ch, char *string)
{
assert(string != NULL);
while (*string)
{
if (ch == *string++)
{
return true;
}
}
return false;
}
char * tortok_r(char *string, const char *ctrl, char **savePtr)
{
assert(ctrl != NULL);
if (string == NULL)
{
string = *savePtr;
}
while (*string && is_character_in_string(*string, ctrl)) string++; // 跳过可能含有的匹配部分
if (!*string)
{
return NULL;
}
char *token = string;
while(*string && !is_character_in_string(*string, ctrl)) string++; // 找到匹配部分
if (!*string)
{
*savePtr = string;
}
else
{
*string = '/0'; // 截断字符串
*savePtr = string + 1; // savePtr指向下一个字符串
}
return token;
}