[英]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.