自己实现strtok

来源:互联网 发布:java super不需要 编辑:程序博客网 时间:2024/05/16 12:48

strtok在MSDN上的定义

char *strtok(   char *strToken,   const char *strDelimit );

参数

strToken 包含标记或标记的字符串
strDelimit 设置分隔符

返回值

返回指向在 strToken中的下一个标记。当未找到时,它们返回 NULL 没有其他标记。每个调用都通过替换 NULL 字符修改 strToken 用在返回的标记后面的第一个分隔符。

示例

// crt_strtok.c// compile with: /W3// In this program, a loop uses strtok// to print all the tokens (separated by commas// or blanks) in the string named "string".//#include <string.h>#include <stdio.h>char string[] = "A string\tof ,,tokens\nand some  more tokens";char seps[]   = " ,\t\n";char *token;int main( void ){   printf( "Tokens:\n" );   // Establish string and get the first token:   token = strtok( string, seps ); // C4996   // Note: strtok is deprecated; consider using strtok_s instead   while( token != NULL )   {      // While there are tokens in "string"      printf( " %s\n", token );      // Get next token:       token = strtok( NULL, seps ); // C4996   }}

是用Bing翻译的吧

简单版本的实现

bool rav_chrInStr(char chr, const char* str) {    while (*str) {        if (chr == *str) return true;        str++;    }    return false;}char* rav_strtok(char* s, const char* delim) {    static char* text = NULL;    if (text == NULL) text = s;    if (text == NULL) return NULL;    char *head = text;    while (*text&&!rav_chrInStr(*text, delim)) {        text++;    }    while (*text&&rav_chrInStr(*text, delim)) {        *text = '\0';        text++;    }    if (*text == '\0') text = NULL;    return head;}

这个版本的问题有两个。

  • 每次调用后,用’\0’替换了之后所有连续的分隔符,虽然效果相同,但是与定义不符
  • 用逐个遍历的方法判断是否为分割符,效率过低

大致的思路是正确的,即用静态局部变量储存待分割的字符串,扫描字符串,找到分隔符后进行分割。

修正版

char* rav_strtok(char* strToken, const char* strDelimit) {    //定义局部变量    static char* text = NULL;    unsigned char table[32];    const unsigned char* delimit;    unsigned char* str;    char *head;    //更新静态字符串    if (strToken) text = strToken;    //对不合法输入进行特殊判断    if (text == NULL) return NULL;    if (strDelimit == NULL) return text;    //改变 char 为 unsigned char 以便进行位运算    str = (unsigned char*)text;    delimit = (const unsigned char*)strDelimit;    //初始化位表    for (int i = 0; i < 32; i++) table[i] = 0;    for (; *delimit; delimit++) {        table[*delimit >> 3] |= 1 << (*delimit & 7);    }    // 跳过分隔符直到起始位置    while (*str && (table[*str >> 3] & (1 << (*str & 7)))) str++;    head = (char*)str;    // 找到第一个分隔符    for (; *str; str++) {        if (table[*str >> 3] & (1 << (*str & 7))) {            *str++ = '\0';            break;        }    }    // 更新结果    text = (char*)str;    if (*text == '\0') text = NULL;    return head;}

修正版用一个长度为32的byte数组压缩了256个分隔符。

0 0
原创粉丝点击