根据 c++ 教程和有关 find()
的教学,实现了以下代码以搜索 string
中所有出现的“cat”:
std::string input;
std::size_t i = 0, x_appearances = 0;
std::getline(std::cin,input);
for(i = input.find("cat",0); i != std::string::npos; i=input.find("cat", i))
{
++x_appearances;
++i; //Move past the last discovered instance to avoid finding the same string
}
然后教程挑战学徒将find()
改成rfind()
,这就是问题所在,首先我尝试了看似显而易见的方法:
for(i = input.rfind("cat",input.length()); i != std::string::npos; i=input.rfind("cat", i))
{
++x_appearances;
--i; //Move past the last discovered instance to avoid finding the same string
}
但是有了这个解决方案,我陷入了无限循环。然后我发现它正在发生,因为增量是在条件检查之前执行的,并且增量 rfind()
总是找到匹配项,即使 i==std::string::npos
(如果匹配位于字符串的开头,例如“cats”)。我的最终解决方案是:
int n=input.length();
for(i = input.rfind("cat",input.length()); n>0 && i!=std::string::npos; i=input.rfind("cat", i))
{
++x_appearances;
n=i;
--i; //Move past the last discovered instance to avoid finding the same string
}
使用 n
我可以跟踪 string
中的位置,并在整个 结束时退出
已被搜索。for 循环
>string
所以我的问题是:我的方法是否正确?我是否需要一个额外的变量或是否有任何其他更简单的方法来做到这一点?
最佳答案
for(i = input.rfind("cat",input.length()); i != std::string::npos; i=input.rfind("cat", i))
{
++x_appearances;
--i; //Move past the last discovered instance to avoid finding the same string
}
上面的问题是循环内的--i
。假设输入字符串以“cat”开头。您的算法最终会找到 i
为 0 的“猫”。由于您已将 i
声明为 std::size_t
,减去 1从 0 开始产生最大可能的 std::size_t
。没有警告,没有溢出,没有未定义的行为。根据标准,这正是无符号整数必须工作的方式。
您需要以某种方式处理这种特殊情况。您可以在循环中使用辅助变量和更复杂的测试。另一种方法是让您的代码保持简单,同时让您清楚地知道您正在明确处理这种特殊情况:
for (i = input.rfind("cat"); i != std::string::npos; i=input.rfind("cat", i-1))
{
++x_appearances;
// Finding "cat" at the start means we're done.
if (i == 0) {
break;
}
}
另请注意,我对循环语句做了一些更改。 pos
的默认值为std::string::npos
,表示从字符串末尾开始搜索。初始化程序不需要第二个参数。我还将 --i
移动到 for 循环的更新部分,将 input.rfind("cat",i)
更改为 input.rfind("猫”,我-1)
。由于此时 i
始终为正,因此减一没有危险。
关于c++ - 使用 rfind 查找所有事件,流程挑战?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23959560/