使用 strtok 查找子字符串
Using strtok to find substring
我有一串很多字母
string path = "cxzaserds";
和一个目标词
string word = "cars";
在我的函数 match()
中,如果在路径中找到(按顺序)来自 word
的字符,我想 return 为真,在这种情况下它将 return true('c' 在 'a' 之前在 'r' 在 path
字符串中的 's' 之前出现)。
我正在尝试使用 strtok()
逐个查找每个字符,分隔符是当前索引的字母。
我的进步:
bool match (string path, string word)
{
char * cstr = new char [path.length()+1]; //workaround for strtok on string
std::strcpy (cstr, path.c_str());
char *p;
for (int i = 0 ; i < path.length(); i++)
{
//error here, "invalid conversion from 'char' to 'const char*'
p = strtok (cstr, word[i]);
if (p != NULL) //if strtok found word[i]
continue;
else return false; //was NULL, word not found
}
return true; //made it through, return true
}
在 C++ 页面上,分隔符下显示:
这些可以与另一个调用不同。
http://www.cplusplus.com/reference/cstring/strtok/
如何将分隔符更改为 strtok returns 非空? 或其他(更简单的)解决方案?
我已经回答了这个问题,所以我不想在这里完全重复。这个问题是在这里问的,但我找不到。
但是您可以在 my personal forum
看到答案
虽然答案是用俄语写的,但代码是用英语写的。:) 此外,您可以使用网络服务翻译来翻译描述。
至于将标准 C 函数 strtok
与 std::string
类型的对象一起使用,那只是一个坏主意,不应使用。
另一种方法是使用标准算法 std::all_of
以及标准 C 函数 strchr
您写了:
p = strtok(cstr, word[i]);
作为第二个参数,您要传递第 i
个字符(类型为 char
)。
但是,如文档所述,第二个参数必须是 const char *
类型,这意味着它是一个分隔符数组。所以你的类型不匹配。
最简单的解决方案是创建一个分隔符数组(注意它是 NUL
终止的,它实际上是一个只有一个字母的 C 风格字符串):
char delimiters[] = { word[i], '[=11=]' };
然后像这样使用它:
p = strtok(cstr, delimiters);
另一方面,这种方法是非 C++ 风格的,在现实生活中您可能想要别的东西。
strchr
在这个问题上比 strtok
好多了;实际上,正如其他人提到的那样,strtok
的设计确实很糟糕,很难想象在哪些情况下使用它是个好主意。
strchr
查找 C 字符串中某个字符的第一次出现。
即使在 C:
中,这个使用 strchr
的问题也变成了一行
int match(const char *needle, const char *haystack) {
while (haystack && *needle) {
haystack = strchr(haystack, *needle++);
}
return haystack != NULL;
}
正如 Vlad 提到的,您不应该混合使用 STL 代码 (std::string
) 和经典 C 代码 (strtok()
)。
您可以使用 std::string
成员,例如 find()
或 find_first_of()
来解决您的问题:
bool match(const std::string &path, const std::string &word) {
std::size_t pos = 0; // position of the last match
// iterate over all characters in 'word'
for (std::size_t i = 0; i < word.length(); ++i) {
// look for the next character and store the new position
if ((pos = path.find(word[i], pos)) == std::string::npos)
return false; // return false if it couldn't be found
}
return true; // all characters have been found in order
}
考虑到您的问题以及 C/C++ 允许您使用普通下标处理单个字符的事实,那么 strtok 似乎只会使解决方案复杂化。
类似于(未经测试的代码!):
boolean hasWord ( char * needle, char * haystack) {
int nlen = strlen(needle);
int npos = 0;
int hlen = strlen(haystack);
int hpos = 0;
for (hpos = 0 ; hpos < hlen ; hpos++) {
if (needle[npos] == haystack[hpos]) {
// got a match now look for next letter
npos++;
if (npos >= nlen) {
// all letters now matched in sequence
return true;
}
}
}
return false;
}
我有一串很多字母
string path = "cxzaserds";
和一个目标词
string word = "cars";
在我的函数 match()
中,如果在路径中找到(按顺序)来自 word
的字符,我想 return 为真,在这种情况下它将 return true('c' 在 'a' 之前在 'r' 在 path
字符串中的 's' 之前出现)。
我正在尝试使用 strtok()
逐个查找每个字符,分隔符是当前索引的字母。
我的进步:
bool match (string path, string word)
{
char * cstr = new char [path.length()+1]; //workaround for strtok on string
std::strcpy (cstr, path.c_str());
char *p;
for (int i = 0 ; i < path.length(); i++)
{
//error here, "invalid conversion from 'char' to 'const char*'
p = strtok (cstr, word[i]);
if (p != NULL) //if strtok found word[i]
continue;
else return false; //was NULL, word not found
}
return true; //made it through, return true
}
在 C++ 页面上,分隔符下显示:
这些可以与另一个调用不同。
http://www.cplusplus.com/reference/cstring/strtok/
如何将分隔符更改为 strtok returns 非空? 或其他(更简单的)解决方案?
我已经回答了这个问题,所以我不想在这里完全重复。这个问题是在这里问的,但我找不到。 但是您可以在 my personal forum
看到答案虽然答案是用俄语写的,但代码是用英语写的。:) 此外,您可以使用网络服务翻译来翻译描述。
至于将标准 C 函数 strtok
与 std::string
类型的对象一起使用,那只是一个坏主意,不应使用。
另一种方法是使用标准算法 std::all_of
以及标准 C 函数 strchr
您写了:
p = strtok(cstr, word[i]);
作为第二个参数,您要传递第 i
个字符(类型为 char
)。
但是,如文档所述,第二个参数必须是 const char *
类型,这意味着它是一个分隔符数组。所以你的类型不匹配。
最简单的解决方案是创建一个分隔符数组(注意它是 NUL
终止的,它实际上是一个只有一个字母的 C 风格字符串):
char delimiters[] = { word[i], '[=11=]' };
然后像这样使用它:
p = strtok(cstr, delimiters);
另一方面,这种方法是非 C++ 风格的,在现实生活中您可能想要别的东西。
strchr
在这个问题上比 strtok
好多了;实际上,正如其他人提到的那样,strtok
的设计确实很糟糕,很难想象在哪些情况下使用它是个好主意。
strchr
查找 C 字符串中某个字符的第一次出现。
即使在 C:
中,这个使用strchr
的问题也变成了一行
int match(const char *needle, const char *haystack) {
while (haystack && *needle) {
haystack = strchr(haystack, *needle++);
}
return haystack != NULL;
}
正如 Vlad 提到的,您不应该混合使用 STL 代码 (std::string
) 和经典 C 代码 (strtok()
)。
您可以使用 std::string
成员,例如 find()
或 find_first_of()
来解决您的问题:
bool match(const std::string &path, const std::string &word) {
std::size_t pos = 0; // position of the last match
// iterate over all characters in 'word'
for (std::size_t i = 0; i < word.length(); ++i) {
// look for the next character and store the new position
if ((pos = path.find(word[i], pos)) == std::string::npos)
return false; // return false if it couldn't be found
}
return true; // all characters have been found in order
}
考虑到您的问题以及 C/C++ 允许您使用普通下标处理单个字符的事实,那么 strtok 似乎只会使解决方案复杂化。
类似于(未经测试的代码!):
boolean hasWord ( char * needle, char * haystack) {
int nlen = strlen(needle);
int npos = 0;
int hlen = strlen(haystack);
int hpos = 0;
for (hpos = 0 ; hpos < hlen ; hpos++) {
if (needle[npos] == haystack[hpos]) {
// got a match now look for next letter
npos++;
if (npos >= nlen) {
// all letters now matched in sequence
return true;
}
}
}
return false;
}