[英]Why strtok takes a char* and not a const char*?
據我所知, strtok()
不會修改底層字符串,那么為什么不使用 const char*
指針而不是const char*
指針呢? 此外,在標記化時,您不希望字符串更改,對嗎?
更新: https ://godbolt.org/z/3SPvRB 很明顯 strtok() 確實修改了底層字符串。 非變異標記器的替代方案是什么?
但是strtok
確實會更改字符串。
取以下代碼:
char sz[] = "The quick brown fox";
char* token = strtok(sz, " ");
它會將數組的內容更改為:
"The\0quick brown fox";
第一個發現的分隔符被替換為空字符。 在內部(通過線程本地存儲或全局變量),指向發現的分隔符之后的下一個字符的指針被存儲,以便隨后對strtok(NULL, " ")
調用將從原始字符串中解析下一個標記。
它確實修改了底層字符串。 請參閱: http : //www.cplusplus.com/reference/cstring/strtok/
標記的這一結尾會自動替換為空字符,並且標記的開頭由函數返回。
證明:
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
/* note this line... */
printf ("str = \"%s\"\n",str);
return 0;
}
印刷:
Splitting string "- This, a sample string." into tokens:
This
a
sample
string
str = "- This"
更新: https :
strtok()
很明顯strtok()
確實修改了底層字符串。 非變異標記器的替代方案是什么?
如評論中所述,您可以:
strtok()
標記副本; 或者strspn
向前掃描到第一個非分隔符字符,這將是令牌的開頭,然后使用strcspn
向前掃描到標記令牌結尾的下一個分隔符,.find_first_not_of()
向前掃描到第一個非分隔符字符,然后使用.find_first_of()
來定位標記.find_first_of()
的分隔符。 在每種情況下,您都將把標記字符復制到一個新字符串(使用memcpy
進行 C 類型實現——不要忘記nul-terminate )或 C++11 只需使用.substr()
成員函數。
一個非常基本的 C++11 實現看起來類似於:
std::vector<std::string> stringtok (const std::string& s, const std::string& delim)
{
std::vector<std::string> v {}; /* vector of strings for tokens */
size_t beg = 0, end = 0; /* begin and end positons in str */
/* while non-delimiter char found */
while ((beg = s.find_first_not_of (delim, end)) != std::string::npos) {
end = s.find_first_of (delim, beg); /* find delim after non-delim */
v.push_back (s.substr (beg, end - beg)); /* add substr to vector */
if (end == std::string::npos) /* if last delim, break */
break;
}
return v; /* return vector of tokens */
}
如果您遵循邏輯,它會准確跟蹤函數定義上面描述的內容。 將其組合成一個簡短的示例,您將擁有:
#include <iostream>
#include <string>
#include <vector>
std::vector<std::string> stringtok (const std::string& s, const std::string& delim)
{
std::vector<std::string> v {}; /* vector of strings for tokens */
size_t beg = 0, end = 0; /* begin and end positons in str */
/* while non-delimiter char found */
while ((beg = s.find_first_not_of (delim, end)) != std::string::npos) {
end = s.find_first_of (delim, beg); /* find delim after non-delim */
v.push_back (s.substr (beg, end - beg)); /* add substr to vector */
if (end == std::string::npos) /* if last delim, break */
break;
}
return v; /* return vector of tokens */
}
int main (void) {
std::string str = " my dog has fleas ",
delim = " ";
std::vector<std::string> tokens;
tokens = stringtok (str, delim);
std::cout << "string: '" << str << "'\ntokens:\n";
for (auto s : tokens)
std::cout << " " << s << '\n';
}
示例使用/輸出
$ ./bin/stringtok
string: ' my dog has fleas '
tokens:
my
dog
has
fleas
注意:這只是實現不修改原始字符串標記化的眾多方法之一。 仔細檢查一下,如果您還有其他問題,請告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.