strtok()這個(gè)函數(shù)大家都應(yīng)該碰到過(guò),但好像總有些問(wèn)題, 這里著重講下它 首先看下MSDN上的解釋: char *strtok( char *strToken, const char *strDelimit ); Parameters strToken String containing token or tokens. strDelimit Set of delimiter characters. Return Value Returns a pointer to the next token found in strToken. They return NULL when no more tokens are found. Each call
modifies strToken by substituting a
NULL character for each delimiter that is encountered. Remarks The strtok function finds the
next token in strToken. The set of
characters in strDelimitspecifies possible
delimiters of the token to be found in strToken on the current call. Security Note These
functions incur a potential threat brought about by a buffer overrun problem.
Buffer overrun problems are a frequent method of system attack, resulting in an
unwarranted elevation of privilege. For more information, see Avoiding Buffer Overruns. On the first call to strtok, the function skips
leading delimiters and returns a pointer to the first token in strToken, terminating the token with a null
character. More tokens can be broken out of the remainder of strToken by a series of calls
to strtok. Each call tostrtok modifies strToken by inserting a null
character after the token returned by that call. To read the next token from strToken, call strtok with a NULL value for the strTokenargument. The NULL strToken argument causes strtok to search for the
next token in the modified strToken. The strDelimit argument can take any
value from one call to the next so that the set of delimiters may vary. Note Each
function uses a static variable for parsing the string into tokens. If
multiple or simultaneous calls are made to the same function, a high potential for
data corruption and inaccurate results exists. Therefore, do not attempt to
call the same function simultaneously for different strings and be aware of
calling one of these functions from within a loop where another routine may be
called that uses the same function. However, calling this function
simultaneously from multiple threads does not have undesirable effects. 很暈吧? 呵呵。。。 簡(jiǎn)單的說(shuō),就是函數(shù)返回第一個(gè)分隔符分隔的子串后,將第一參數(shù)設(shè)置為NULL,函數(shù)將返回剩下的子串。 下面我們來(lái)看一個(gè)例子: int main() { char test1[] =
"feng,ke,wei"; char *test2 = "feng,ke,wei";
char *p; p = strtok(test1, ","); while(p) {
printf("%s\n", p); p
= strtok(NULL, ","); }
return 0; } 運(yùn)行結(jié)果: feng ke wei 說(shuō)明: 函數(shù)strtok將字符串分解為一系列標(biāo)記(token),標(biāo)記就是一系列用分隔符(delimiting chracter,通常是空格或標(biāo)點(diǎn)符號(hào))分開(kāi)的字符。注意,此的標(biāo)記是由delim分割符分割的字符串喔。 例如,在一行文本中,每個(gè)單詞可以作為標(biāo)記,空格是分隔符。 函數(shù)strtok保存string中標(biāo)記后面的下一個(gè)字符的指針,并返回當(dāng)前標(biāo)記的指針。
如果調(diào)用strtok時(shí)已經(jīng)沒(méi)有標(biāo)記,則strtok返回NULL。注意strtok修改輸入字符串,因此,如果調(diào)用strtok之后還要在程序中使用這個(gè)字符串,則應(yīng)復(fù)制這個(gè)字
符串。 但如果用p = strtok(test2, ",")則會(huì)出現(xiàn)內(nèi)存錯(cuò)誤,這是為什么呢?是不是跟它里面那個(gè)靜態(tài)變量有關(guān)呢? 我們來(lái)看看它的原碼: /*** *strtok.c - tokenize a string with given delimiters * * Copyright (c)
Microsoft Corporation. All rights reserved. * *Purpose: * defines strtok() -
breaks string into series of token * via repeated calls. * *******************************************************************************/ #include #include #ifdef _MT #include #endif /* _MT */ /*** *char *strtok(string, control) - tokenize string with
delimiter in control * *Purpose: * strtok considers
the string to consist of a sequence of zero or more * text tokens
separated by spans of one or more control chars. the first * call, with string
specified, returns a pointer to the first char of the * first token, and
will write a null char into string immediately * following the
returned token. subsequent calls with zero for the first * argument (string)
will work thru the string until no tokens remain. the * control string may
be different from call to call. when no tokens remain * in string a NULL
pointer is returned. remember the control chars with a * bit map, one bit
per ascii char. the null char is always a control char. * //這里已經(jīng)說(shuō)得很詳細(xì)了!!比MSDN都好! *Entry: * char *string -
string to tokenize, or NULL to get next token * char *control -
string of characters to use as delimiters * *Exit: * returns pointer to
first token in string, or if string * was NULL, to next
token * returns NULL when
no more tokens remain. * *Uses: * *Exceptions: * *******************************************************************************/ char * __cdecl strtok ( char * string, const char *
control ) { unsigned char
*str; const unsigned
char *ctrl = control; unsigned char
map[32]; int count; #ifdef _MT _ptiddata ptd
= _getptd(); #else /* _MT */ static char *nextoken;
//保存剩余子串的靜態(tài)變量 #endif /* _MT */ /* Clear
control map */ for (count =
0; count < 32; count++)
map[count] = 0; /* Set bits in
delimiter table */ do {
map[*ctrl >> 3] |= (1 << (*ctrl & 7)); } while
(*ctrl++); /* Initialize
str. If string is NULL, set str to the saved *
pointer (i.e., continue breaking tokens out of the string * from
the last strtok call) */ if (string) str =
string;
//第一次調(diào)用函數(shù)所用到的原串 else #ifdef _MT
str = ptd->_token; #else /* _MT */
str =
nextoken;
//將函數(shù)第一參數(shù)設(shè)置為NULL時(shí)調(diào)用的余串 #endif /* _MT */ /* Find beginning of token (skip over leading delimiters). Note that * there is no token iff this loop sets str to point to the terminal * null (*str == '\0') */ while ( (map[*str >> 3] & (1 << (*str & 7))) && *str ) str++; string = str; //此時(shí)的string返回余串的執(zhí)行結(jié)果 /* Find the end of the token. If it is not the end of the string, * put a null there. */ //這里就是處理的核心了, 找到分隔符,并將其設(shè)置為'\0',當(dāng)然'\0'也將保存在返回的串中 for ( ; *str ; str++ ) if ( map[*str >> 3] & (1 << (*str & 7)) ) { *str++ = '\0'; //這里就相當(dāng)于修改了串的內(nèi)容 ① break; } /* Update nextoken (or the corresponding field in the per-thread data * structure */ #ifdef _MT ptd->_token = str; #else /* _MT */ nextoken = str; //將余串保存在靜態(tài)變量中,以便下次調(diào)用 #endif /* _MT */ /* Determine if a token has been found. */ if ( string == str ) return NULL; else return string; }
原來(lái), 該函數(shù)修改了原串. 所以,當(dāng)使用char
*test2 = "feng,ke,wei"作為第一個(gè)參數(shù)傳入時(shí),在位置①處, 由于test2指向的內(nèi)容保存在文字常量區(qū),該區(qū)的內(nèi)容是不能修改的,所以會(huì)出現(xiàn)內(nèi)存錯(cuò)誤. 而char
test1[] = "feng,ke,wei" 中的test1指向的內(nèi)容是保存在棧區(qū)的,所以可以修改. 看到這里 大家應(yīng)該會(huì)對(duì)文字常量區(qū)有個(gè)更加理性的認(rèn)識(shí)吧..... |
|
來(lái)自: wsglibrary > 《網(wǎng)絡(luò)編程》