我正在一个字符串中进行一系列搜索,并且在某个地方某个字符串将被遗漏,我的搜索集将失败。
我曾预料到一旦位置达到std :: string :: npos,它就会留在那里,但事实并非如此。将std :: string :: npos传递给std :: string.find似乎再次开始搜索
std::string str("frederick");
std::string::size_type pos = str.find("der",std::string::npos);
TS_ASSERT_EQUALS(pos, std::string::npos); // FAIL, 3 is returned
为什么不指示字符串的结尾?
更新: 目的是按顺序搜索一系列字符串,并在结尾检查结果
pos = str.find(string1, pos)
pos = str.find(string2, pos)
pos = str.find(string3, pos)
if (pos != std:string::npos)
{ // All strings found
答案 0 :(得分:10)
查看规范,我认为您的实施中可能存在错误。
basic_string::find
应该返回xpos
的最低位置,pos <= xpos
和xpos + str.size() <= size()
以及at(xpos + I) == str.at(I)
返回由{{1}控制的所有元素I
}}
str
-1转换为无符号类型,因此必须是该无符号类型可表示的最大数字。鉴于即使basic_string::npos
&lt; = xpos
的第一部分也没有其他职位npos
可以满足,xpos
必须在失败时返回find
可以看到npos
是npos
作为第二个参数传递时唯一有效的返回值。
答案 1 :(得分:4)
比较string :: find()和string :: copy()。 (在N2798中,那是21.3.7.2和21.3.6.7,第686/687页)两者都采取了位置论证。但是只有string :: copy有一个“Requires:pos&lt; = size()”子句。因此,string :: find确实不需要pos&lt; = size()。
从那时起,Charles Bailey就有了正确的逻辑。查看有效返回值的范围,很明显只有与rqeuirements匹配的唯一返回值是string :: npos。返回的任何其他值都小于string :: npos,失败的是21.3.7.2/1。
从N2798 = 08-0308,版权ISO / IEC:
21.3.7.2 basic_string::find [string::find]
size_type find(const basic_string<charT,traits,Allocator>& str,
size_type pos = 0) const;
1效果:如果可能,确定最低位置xpos
,以便满足以下两个条件:
- pos <= xpos
和xpos + str.size() <= size();
- traits::eq(at(xpos+I), str.at(I))
由I
控制的字符串的所有元素str
。
2如果函数可以确定xpos
的这样的值,则返回xpos
。否则,返回npos
。
3备注:使用traits::eq()
。
答案 2 :(得分:3)
std::string::npos
不是std::string::find
的有效参数。
标准中find
的定义仅提及npos
作为可能的返回值,而不是起始位置。
答案 3 :(得分:3)
您可能会发现自由函数std :: search在这种情况下更容易使用。 E.g。
std::string::const_iterator iter = str.begin();
iter = std::search( iter, str.end(), string1.begin(), string1.end() );
iter = std::search( iter, str.end(), string2.begin(), string2.end() );
iter = std::search( iter, str.end(), string3.begin(), string3.end() );
答案 4 :(得分:1)
如果您传递npos
:
<强> [更新] 强>
STL文档(我可以找到的两个复制品)仅提及string::npos
作为可能的返回值,而不是pos
的有效值。后者是搜索开始的索引。
但请参阅下面的评论(我不是ISO标准的专家,我根据我的文档限制了我的期望。)
STL实现通常会使用明显超出范围的值(例如((size_type)-1)
。如何处理这个因为参数没有明确说明,所以我不会依赖于这种行为。
的 [/更新] 强>
所以你需要从0开始,并在每次调用之后检查pos != npos
:
pos = str.find(string1, 0)
if (pos != std:string::npos)
pos = str.find(string2, pos)
if (pos != std:string::npos)
pos = str.find(string3, pos)
if (pos != std:string::npos)
{
// All strings found
}
答案 5 :(得分:0)
将std :: string :: npos作为第二个参数传递给find意味着“开始在字符串中的std :: string :: npos位置上或之后查找”。
显然,这不是你想要的。
编辑:
这可能会达到您原定的目的:
string s;
string::size_type pos;
if ((pos = s.find(s1)) != string::npos && (pos = s.find(s2, pos)) != npos &&
(pos = s.find(s3,pos)) != string::npos)
{
// okay
}
我没有测试它但它应该可以工作,你可能更喜欢peterchen风格,因为它更具可读性。
答案 6 :(得分:0)
您应该将字符串的长度用作起始位置。