首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

关于字符串分隔函数strtok的疑义

2013-07-08 
关于字符串分隔函数strtok的疑问本帖最后由 shimachao 于 2013-06-27 20:43:02 编辑MSDN上有一个strtok函

关于字符串分隔函数strtok的疑问
本帖最后由 shimachao 于 2013-06-27 20:43:02 编辑 MSDN上有一个strtok函数的例子:

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 ); // NULL和seps没有任何关于string的信息吧?那它怎么能处理string呢
     }
  }


这样就把一个字符串分隔了。可是,我有点疑问:while中的strtok函数调用没有字符串string的信息(没有用string作参数),它怎么知道是对string进行操作的?而且看不到有任何和strtok相关的结构体可以保存这些信息。
难道后面调用的strtok函数还能和最前面的strtok函数通信?

还有MSDN上说这个函数不安全,已经被抛弃,有替代它的函数。它的不安全是因为改写了字符串吗?替代品就没有吗?
strtok
[解决办法]
你把它理解成里面使用了全局变量或 static 变量就好了.
实际上, 它使用的是一个 TLS, 每个线程一份的变量, 在 crt 库中定义为:

/* Structure for each thread's data */

struct _tiddata {
    unsigned long   _tid;       /* thread ID */


    uintptr_t _thandle;         /* thread handle */

    int     _terrno;            /* errno value */


    unsigned long   _tdoserrno; /* _doserrno value */
    unsigned int    _fpds;      /* Floating Point data segment */
    unsigned long   _holdrand;  /* rand() seed value */
    char *      _token;         /* ptr to strtok() token */
    wchar_t *   _wtoken;        /* ptr to wcstok() token */
    unsigned char * _mtoken;    /* ptr to _mbstok() token */

    /* following pointers get malloc'd at runtime */
    char *      _errmsg;        /* ptr to strerror()/_strerror() buff */
    wchar_t *   _werrmsg;       /* ptr to _wcserror()/__wcserror() buff */
    char *      _namebuf0;      /* ptr to tmpnam() buffer */
    wchar_t *   _wnamebuf0;     /* ptr to _wtmpnam() buffer */
    char *      _namebuf1;      /* ptr to tmpfile() buffer */
    wchar_t *   _wnamebuf1;     /* ptr to _wtmpfile() buffer */

....
[解决办法]
估计是strtok函数内部对传入的string做了一份拷贝,当传入NULL时,继续在内部拷贝上进行处理。
[解决办法]
猜是猜不出来的,看源码就知道了,函数里有个static变量,存储了解析的最后一个token的结尾的位置

http://svnweb.freebsd.org/base/release/2.2.8/lib/libc/string/strtok.c?revision=42950&view=markup

这个是多线程的版本
http://svnweb.freebsd.org/base/release/8.4.0/lib/libc/string/strtok.c?revision=251259&view=markup

热点排行