Я работаю над книгой на C ++, и это только покрыто с помощью string::npos
проверить, существует ли позиция символа в строке. Я не понимаю, как этот механизм мог знать, к какой строке я обращаюсь! Этот конкретный код считает количество вхождений подстроки.
Код:
for (int i=cats.find("cat",0);i!=string::npos;i=cats.find("cat",i)) {
++catCount;
++i;
}
Я понимаю, что он запускает цикл при первом появлении слова, увеличивая счетчик при каждом проходе, чтобы избежать повторного подсчета одной и той же подстроки, а затем в конце каждого цикла счетчик переходит на позицию следующего появления подстрока. Цикл останавливается, когда счетчик не существует как символьный индекс для строки.
Строка называется cat, хотя, и «cats» нигде нет в «string :: npos», так как, черт возьми, он узнает, что это переменная, которую я даже ищу? Это просто потому, что это была последняя переменная для вызова .find()
?
Спасибо!
Если find
не может найти то, что вы ищете, он возвращает значение часового, 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
это просто статический член const, который представляет максимальное значение, представимое и в этом случае представляет и eror, если мы посмотрим, что cppreference говорит о станд :: basic_string :: НСС:
static const size_type npos = -1;
Это специальное значение, равное максимальному значению, представляемому типом size_type. Точное значение зависит от контекста, но обычно оно используется либо как индикатор конца строки функциями, которые ожидают строковый индекс, либо как индикатор ошибки функциями, которые возвращают индекс строки.
который соответствует определению для npos
в проект стандарта C ++ в разделе 21.4
Шаблон класса basic_string параграф 5:
static const size_type npos = -1;
что немного странно, так как с size_type является неподписанный но из-за интегральных правил преобразования в разделе 4.7
Интегральные преобразования который говорит:
Если тип назначения является беззнаковым, полученное значение является наименьшим целым числом без знака, соответствующим исходному целому числу (по модулю 2n, где n — число битов, используемых для представления типа без знака). […]
гарантирует, что -1
будет преобразовано в наибольшее значение без знака. Это может быть легче увидеть, используя формулировку из проекта стандарта C99, которая гласит:
В противном случае, если новый тип без знака, значение преобразуется путем многократного добавления или
вычитание больше, чем максимальное значение, которое может быть представлено в новом типе
пока значение не окажется в диапазоне нового типа.
что дает нам MAX + 1 -1
который MAX
,