string::npos如何知道我指的是哪个字符串
How does string::npos know which string I am referring to?
我正在阅读一本关于C++的书,它刚刚介绍了使用string::npos
来检查字符串中是否存在字符位置。我不明白这个机制怎么可能知道我指的是哪个字符串!此特定代码用于计算子字符串的出现次数。
代码:
for (int i=cats.find("cat",0);i!=string::npos;i=cats.find("cat",i)) {
++catCount;
++i;
}
我知道它是在单词的第一次出现时开始循环,每次通过都增加计数器以避免对同一个子串计数两次,然后在每个循环结束时,计数器跳到下一次出现子串的位置。当计数器不作为字符串的字符索引存在时,循环停止。
不过,这个字符串被称为cats,在"string::npos"中找不到"cats",所以它怎么知道这是我正在搜索的变量呢?这仅仅是因为那是调用.find()
的最后一个变量吗?
谢谢!
如果find
找不到您要查找的内容,它将返回一个sentinel值std::string::npos
。不需要知道任何关于字符串本身的信息。所需要的只是返回一个不能是有效索引的值。
例如,它可以实现为:
static const size_t npos = std::numeric_limits<size_t>::max();
size_t string::find(...)
{
// if we didn't find it...
return npos;
}
此外,您不应该使用int
来存储返回值,因为它不是find
返回的值。如果您有一个很长的字符串,并且返回的索引是>numeric_limits<int>.max()
,该怎么办?现在您已经调用了未定义的行为。
find
返回一个std::string::size_type
。std::string::npos
是当找不到值时返回的那种类型的常量。
请注意,std::string::size_type
是unsigned
值,int
是有符号的。如果std::string::npos
不能表示为int
,那么从std::string::npos
到int
的转换是未定义的行为。
因此,您真的不应该将std::string::find
的返回值存储在int
中。相反,您应该将它存储在std::string::size_type
中,或者在C++11中使用auto
。baisc_string<char>
size_type
就是std::size_t
,其他大多数专业也是如此。
它不知道你指的是什么字符串,npos
只是一个静态常量成员,它表示可表示的最大值,在这种情况下表示和eror,如果我们看看cppreference对std::basic_string::npos:的描述
static const size_type npos = -1;
这是一个特殊值,等于size_type类型所表示的最大值。确切的含义取决于上下文,但它通常被期望字符串索引的函数用作字符串结束指示符,或者被返回字符串索引的功能用作错误指示符。
它与21.4
类模板basic_string段落5中C++标准草案中npos
的定义相匹配:
static const size_type npos = -1;
这有点奇怪,因为size_type是无符号,但这是由于4.7
积分转换部分中的积分转换规则,该规则表示:
如果目标类型是无符号的,则得到的值是与源整数全等的最小无符号整数(模2n,其中n是用于表示无符号类型的位数)。[…]
保证-1
将被转换为最大的无符号值。使用C99标准草案中的措辞可能更容易看出:
否则,如果新类型是无符号的,则通过重复添加或比新类型中可以表示的最大值多减去一直到该值在新类型的范围内。
这给了我们MAX + 1 -1
,也就是MAX
。