关于字符串分隔函数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