3

我正在一个字符串中进行一系列搜索,沿着这条线的某个地方会丢失一个字符串,我的一组搜索应该会失败。

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

7 回答 7

10

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

basic_string::find应该返回最低位置xpos,使得pos <= xpos和控制的xpos + str.size() <= size()所有at(xpos + I) == str.at(I)元素。Istr

basic_string::npos是 -1 转换为无符号类型,因此必须是该无符号类型可表示的最大数。鉴于没有其他位置xpos可以满足npos<=的第一部分xpos并且find必须npos在失败时返回,据我所知,这是作为第二个参数传递时npos唯一有效的返回值。basic_string::findnpos

于 2009-06-18T10:05:43.113 回答
4

比较 string::find() 和 string::copy()。(在 N2798 中,即 21.3.7.2 和 21.3.6.7,第 686/687 页)两者都采用位置参数。然而只有 string::copy 有一个“Requires: pos <= size()”子句。因此,string::find不需要pos <= size()。

从那时起,查尔斯·贝利就有了正确的逻辑。查看有效返回值的范围,很明显只有与 rqeuirements 匹配的返回值是 string::npos。返回的任何其他值都小于 string::npos,失败 21.3.7.2/1。


从 N2798=08-0308,版权 ISO/IEC:

21.3.7.2basic_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))的所有元素。2 返回:函数是否可以确定. 否则,返回。3 备注:用途。Istrxposxposnpostraits::eq()

于 2009-06-18T10:54:30.597 回答
3

std::string::npos不是 的有效参数std::string::find

标准中的定义find仅提及npos可能的返回值,而不是起始位置。

于 2009-06-18T09:56:07.063 回答
3

您可能会发现在这种情况下,免费函数 std::search 更容易使用。例如

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() );
于 2009-06-18T10:53:25.640 回答
1

如果您通过,则行为未定义npos

[更新]
STL 文档(我能找到的两个复制品,无论如何)string::npos仅提及作为可能的返回值,而不是作为pos. 后者是搜索开始的索引。

但另请参阅下面的评论(我不是 ISO 标准的专家,我根据我拥有的文档限制了我的期望)。

STL 实现通常会使用明显超出范围的值(例如 ( (size_type)-1)。未明确说明如何将其作为参数处理,因此我不会依赖该行为。 [/update]

因此,您需要从 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
 }
于 2009-06-18T10:05:17.407 回答
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 风格,因为它更具可读性。

于 2009-06-18T09:54:00.737 回答
0

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

于 2009-06-18T09:54:40.517 回答