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

发布于 2024-07-25 01:56:30 字数 585 浏览 5 评论 0原文

我正在一个字符串中进行一系列搜索,并且在该行的某个地方将错过其中一个字符串,并且我的一组搜索应该会失败。

我原以为一旦位置到达 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

I am doing a series of searches in a string, and somewhere along the line one of the strings will be missed, and my set of searches should fail.

I had expected that once the position reached std::string::npos it would stay there, but it does not. Passing std::string::npos to std::string.find seems to start the search at the beginning again

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

Why is it not being taken to indicate the end of the string?

Update:
The intention is search for a series of strings in order, and check the result at the end

pos = str.find(string1, pos)
pos = str.find(string2, pos)
pos = str.find(string3, pos)
if (pos != std:string::npos)
{ // All strings found

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

紫瑟鸿黎 2024-08-01 01:56:31

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

basic_string::find 应返回最低位置 xpos,使得 pos <= xposxpos + str.size() < ;= size()at(xpos + I) == str.at(I) 对于由 str 控制的所有元素 I代码>.

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

Looking at the spec, I think that there may be a bug in your implementation.

basic_string::find should return the lowest position xpos such that pos <= xpos and xpos + str.size() <= size() and at(xpos + I) == str.at(I) for all elements I controlled by str.

basic_string::npos is -1 converted to an unsigned type so must be the largest number representable by that unsigned type. Given that no other position xpos can satisfy even the first part of npos <= xpos and find must return npos on failure, as far as I can see npos is the only valid return value for basic_string::find when passed npos as the second parameter.

静谧 2024-08-01 01:56:31

比较 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.2 basic_string::find [string::find]

size_type find(const basic_string& str ,
size_type pos = 0) const;

1 效果:如果可能,确定最低位置 xpos,从而满足以下两个条件:
pos <= xposxpos + str.size() <= size();
traits::eq(at(xpos+I), str.at(I)) 用于 strI >。
2 如果函数可以确定 xpos 的值,则返回:xpos。 否则,返回npos
3 备注:使用traits::eq()

Compare string::find() and string::copy(). (In N2798, that's 21.3.7.2 and 21.3.6.7, pages 686/687) Both take a position argument. Yet only string::copy has a "Requires: pos <= size()" clause. Hence, string::find does not require pos <= size().

From that point on, Charles Bailey has the correct logic. Look at the range of valid return values, and it becomes clear that only the only return value which matches the rqeuirements is string::npos. Any other value returned is smaller than string::npos, failing 21.3.7.2/1.


From N2798=08-0308, copyright 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 Effects: Determines the lowest position xpos, if possible, such that both of the following conditions obtain:
pos <= xpos and xpos + str.size() <= size();
traits::eq(at(xpos+I), str.at(I)) for all elements I of the string controlled by str.
2 Returns: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
3 Remarks: Uses traits::eq().

缱绻入梦 2024-08-01 01:56:31

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

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

std::string::npos is not a valid argument for std::string::find.

The definition of find in the Standard only mentions npos as a possible return value, not a start position.

苯莒 2024-08-01 01:56:31

您可能会发现在这种情况下免费函数 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() );

You may find that the free function std::search is easier to use in this situation. 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() );
娇纵 2024-08-01 01:56:31

如果您传递 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
 }

Behavior is undefined if you pass npos:

[update]
STL documentation (the two reproductions I can find, anyway) mention string::npos only as possible return value, not as a valid value for pos. The latter is the index where search starts.

But see also comments below (I'm not an expert on the ISO standard, I am limiting my expectations based on the docs I have).

The STL implementation would typically use an clearly-out-of-range value (such as ((size_type)-1). How this is handled as parameter is not clearly stated, so I wouldn't rely on that behavior.
[/update]

So you need to start at 0, and check for pos != npos after every call to find:

 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
 }
冰魂雪魄 2024-08-01 01:56:31

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

You should rather use as starting position the length of the string.

一抹微笑 2024-08-01 01:56:31

将 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 风格,因为它更具可读性。

Passing std::string::npos as the second argument to find means "start finding on or after std::string::npos position in the string".

Clearly this is not what you intended.

EDIT:

This might do what you originally intended:

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
}

I haven't tested it but it should work, you might prefer peterchen style as it's more readable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文