为什么std :: string.find(text,std :: string:npos)不返回npos?

时间:2009-06-18 09:43:03

标签: c++ std

我正在一个字符串中进行一系列搜索,并且在某个地方某个字符串将被遗漏,我的搜索集将失败。

我曾预料到一旦位置达到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

7 个答案:

答案 0 :(得分:10)

查看规范,我认为您的实施中可能存在错误。

basic_string::find应该返回xpos的最低位置,pos <= xposxpos + str.size() <= size()以及at(xpos + I) == str.at(I)返回由{{1}控制的所有元素I }}

str -1转换为无符号类型,因此必须是该无符号类型可表示的最大数字。鉴于即使basic_string::npos&lt; = xpos的第一部分也没有其他职位npos可以满足,xpos必须在失败时返回find可以看到nposnpos作为第二个参数传递时唯一有效的返回值。

答案 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 <= xposxpos + 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)

您应该将字符串的长度用作起始位置。