当前位置:编程学习 > C/C++ >>

字符串分割函数strtok

前天晚上和 xiaofazhen 看程序, 突然间看到他的代码里有 strtok 这么一个函数, 网上查了一下, 居然是用来做字符串分割的;
原来 C 下还是有这函数的, 以前还一直抱怨 C 下没有字符串分割函数, 很不方便, 看来还是自己孤陋寡闻胃(如果是 C++ 的话, 参照 这里, 使用 copy+istringstream 来实现); 不多说, 既然看到了, 就要好好学习一下.
以下代码测试环境为:  Windows7 + Visual Studio 2010
函数原型:
1 char *strtok(
2    char *strToken,
3    const char *strDelimit
4 );

参数说明:
    strToken:   包含 token 的字符串, 即待分割串

    strDelimit: token 的集合, strToken 会根据这里的每个字符进行分割
 
返回值:
    返回指向第一段被截取出来的字符串的指针(根据 strDelimit 内的字符进行截取). 如果没有找到, 那么就返回 NULL.
 
调用说明:
    (1). 第一次调用 strtok 时, 第一个参数是 strToken, 以后再调用时, 第一个参数必须是 NULL;

    (2). 调用 strtok 后, 原字符串会被修改;

    (3). strtok 不是一个线程安全的函数.
 
源代码分析:
    从 这里 贴出的 Linux 下的 string.h 的实现可以看出:

    (1). strtok 使用一个全局定义的 char * ___strtok; 来指向截取后的剩余字符串, 所以从第二次开始调用 strtok 后, 第一个参数就只需要设为 NULL 就可以了;

    (2). strtok 函数会在一开始就判断其第一个参数, 若不为 NULL, 就取其第一个参数进行截取, 并将 ___strtok 指向截取后的字符串; 若为NULL, 则使用 ___strtok 进行截取, 并将 ___strtok 指向截取后的字符串;

    (3). strtok 使用 sbegin 指向待截取的字符串, 当找到 strDelimit 里的字符时, 就在这个字符前面插入 '\0', 这样就相当于从 sbegin 指向的字符串里截取出前面一段了. 而后面一段, 则由 ___strtok 指向, 等待下一次截取.
 
测试代码:
原始代码摘自 msdn, 有扩改.
01 // crt_strtok.c
02 // compile with: /W3
03 // In this program, a loop uses strtok
04 // to print all the tokens (separated by commas
05 // or blanks) in the string named "string".
06 //
07 #include <string.h>
08 #include <stdio.h>
09 #include <Windows.h>
10 
11 char string[] = "A string\tof ,,tokens\nand some  more tokens";
12 char seps[]   = " ,\t\n";
13 char chinese[] = "中国,吃饭";
14 char *token;
15 
16 int main( void )
17 {
18     printf( "英文测试:\n" );
19 
20     // Establish string and get the first token:
21     token = strtok( string, seps ); // C4996
22     // Note: strtok is deprecated; consider using strtok_s instead
23     while( token != NULL )
24     {
25         // While there are tokens in "string"
26         printf( " %s\n", token );
27 
28         // Get next token:
29         token = strtok( NULL, seps ); // C4996
30     }
31 
32 
33     printf("原字符串: %s\n", string);   // 结果为 A, 说明原字符串已发生改变
34 
35 
36     printf( "\n中文测试:\n");
37 
38     token = strtok( chinese, ",");
39     while(token != NULL )
40     {
41         printf( "%s\n", token);
42 
43         token = strtok( NULL, ",");
44     }
45 
46     printf("\n");
47     system("pause");
48 
49 }

运行结果:
可以看到, 即使是全中文组成的字符串, 也是能正确分割的; 还要注意的一点是, 调用 strtok 后, 原字符串会被修改.
 
 
 
最后, 百度百科说明在新的 Linux 2.6.29 下, 不再使用 strtok 函数, 而是改为使用更快的 strsep 替代. 但是在 windows 环境下(当前版本 Visual Studio 2010), 并未提供 strsep 函数.
在 这里 可以看到 strsep 的函数实现, 所以可以自己写一个 strsep, 然后再调用即可. 在 strtok 函数定义处也可以看到以下说明"WARNING: strtok is deprecated, use strsep instead.".
作者: Sailtseng 
 

补充:软件开发 , C语言 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,