Перейти к содержимому

S find c как работает

  • автор:

Использование функции set::find STL в Visual C++

В этой статье показано, как использовать функцию Стандартной set::find библиотеки шаблонов (STL) в Visual C++.

Исходная версия продукта: Visual C++
Исходный номер базы знаний: 158576

Обязательный заголовок

Прототип

template class set < public: // Function 1: const_iterator find(const _K& _Kv) const; >

Имена классов и параметров в прототипе могут не соответствовать версии в файле заголовка. Некоторые из них были изменены для повышения удобочитаемости.

Описание функции set::find

Функция find используется для поиска элемента в управляемой последовательности. Он возвращает итератор первому элементу управляемой последовательности, ключ сортировки которого соответствует его параметру. Если такого элемента не существует, возвращенный итератор равен end() .

Пример кода

В Visual C++ .NET и Visual C++ параметр /EHsc задается по умолчанию и эквивалентен /GX.

////////////////////////////////////////////////////////////////////// // Compile options needed: -GX // SetFind.cpp: // Illustrates how to use the find function to get an iterator // that points to the first element in the controlled sequence // that has a particular sort key. // Functions: // find Returns an iterator that points to the first element // in the controlled sequence that has the same sort key // as the value passed to the find function. If no such // element exists, the iterator equals end(). // Copyright (c) 1996 Microsoft Corporation. All rights reserved. ////////////////////////////////////////////////////////////////////// #pragma warning(disable:4786) #include #include #if _MSC_VER > 1020 // if VC++ version is > 4.2 using namespace std; // std c++ libs implemented in std #endif typedef set,allocator > SET_INT; void truefalse(int x) < cout void main() < SET_INT s1; cout 

Выходные данные программы

s1.insert(5) s1.insert(8) s1.insert(12) it=find(8) it!=s1.end() returned True it=find(6) it!=s1.end() returned False 

unixforum.org

Если же фрагмент обнаружить не удастся, функция выдаст -1 -- отрицательное число, которое, естественно, не может быть позицией символа в строке.

В качестве примера работы данной функции приводится программа:

#include #include using namespace std; int main ()

В результате на экран выводится число 12.

Ради интереса воткнул в программу строку: cout

#include #include using namespace std; int main ()

Потом решил посмотреть на выдачу -1, если функции find() подсунуть символ, отсутствующий в строке:

#include #include using namespace std; int main ()

И действительно, был выдан результат: -1.

Аналогично воткнул в программу строку: cout

#include #include using namespace std; int main ()

10% — это 0,1.
© Bizdelnick
Спасибо сказали:
Bizdelnick Модератор Сообщения: 20642 Статус: nulla salus bello ОС: Debian GNU/Linux

Re: C++: функция find()

Сообщение Bizdelnick » 21.10.2014 20:10

#include main()

Пишите правильно:

в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик

Спасибо сказали:
yoshakar Сообщения: 259 ОС: Debian Stretch

Re: C++: функция find()

Сообщение yoshakar » 21.10.2014 21:24

Книжки Крупника - очень хорошие, и эта тоже. Но он немножко соврал: find выдаёт не -1 в случае неудачи. Она вообще не может вернуть -1, поскольку возвращает беззнаковое целое. В случае неудачи она возврашает string::npos - это именно то число, которое вы видите на экране. Но! Во всех существующих реализациях стандартной библиотеки, в том числе и вашей, string::npos - это самое большое возможное число соответствующего типа (size_t) и как правило вообще самое большое представимое число. Поэтому будучи приведено к знаковому типу (а C++ к сожалению делает это без вопросов, неявно), оно (по правилам двоичной арифметики) превращается в -1 (см. программу постом выше). Конечно, лучше так не делать, а использовать эту самую константу string::npos, но придумать реалистичный вариант, когда приведение к знаковому типу не сработает, я не могу. Но вот код типа if(find(. ) < 0) не будет работать так, как ожидает тот, кто его написал - это точно. К счастью все нормальные компиляторы выдают на такой код предупреждение.

Спасибо сказали:
ArkanJR Сообщения: 1164 Статус: Профан

Re: C++: функция find()

Сообщение ArkanJR » 21.10.2014 21:42

Всё равно мне неясно, почему результат:

10% — это 0,1.
© Bizdelnick
Спасибо сказали:
yoshakar Сообщения: 259 ОС: Debian Stretch

Re: C++: функция find()

Сообщение yoshakar » 21.10.2014 21:48

Первая вариант выводит значение переменной p. Она типа int, то есть целое со знаком. Она не может быть равна 4294967295, так как максимальное значение, которое можно в неё запихнуть в два раза меньше. Поэтому такой код никак не может вывести 4294967295, он выводит -1.
Второй вариант выводит значение, которое вернула функция find. Оно типа unsigned int, то есть целое без знака. Оно не может быть равно -1, так оно без знака. Поэтому такой код никак не может вывести -1, он выводит 4294967295.

Спасибо сказали:
ArkanJR Сообщения: 1164 Статус: Профан

Re: C++: функция find()

Сообщение ArkanJR » 21.10.2014 21:52

21.10.2014 21:48

Первая вариант выводит значение переменной p. Она типа int, то есть целое со знаком. Она не может быть равна 4294967295, так как максимальное значение, которое можно в неё запихнуть в два раза меньше. Поэтому такой код никак не может вывести 4294967295, он выводит -1.
Второй вариант выводит значение, которое вернула функция find. Оно типа unsigned int, то есть целое без знака. Оно не может быть равно -1, так оно без знака. Поэтому такой код никак не может вывести -1, он выводит 4294967295.

Вот теперь понятно.
10% — это 0,1.
© Bizdelnick
Спасибо сказали:
Bizdelnick Модератор Сообщения: 20642 Статус: nulla salus bello ОС: Debian GNU/Linux

Re: C++: функция find()

Сообщение Bizdelnick » 21.10.2014 22:02

#include int main()

Так понятнее?
Upd. Долго отвечал. (-:
Пишите правильно:

в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик

Спасибо сказали:

drBatty Сообщения: 8735 Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит. ОС: Slackware-current Контактная информация:

Re: C++: функция find()

Сообщение drBatty » 25.10.2014 13:54

21.10.2014 21:24

это самое большое возможное число соответствующего типа (size_t) и как правило вообще самое большое представимое число.

увы. Сейчас нативное "самое большое" 2^64-1.
21.10.2014 21:24

Конечно, лучше так не делать, а использовать эту самую константу string::npos, но придумать реалистичный вариант, когда приведение к знаковому типу не сработает, я не могу.

например если мы приводим к int64_t, и это реальный случай, т.к. именно этот тип имеет ptrdiff_t, например индексы C массивов.
т.е. если мы хотим перейти в массиве, и ожидаем, что a[-1] это прошлый эл-т, то он окажется ВНЕЗАПНО 4294967295м.

PS: я согласен с основной вашей мыслью, что надо сравнивать с константой string::npos

Скоро придёт
Осень

Спасибо сказали:
yoshakar Сообщения: 259 ОС: Debian Stretch

Re: C++: функция find()

Сообщение yoshakar » 27.10.2014 22:47

25.10.2014 13:54
PS: я согласен с основной вашей мыслью, что надо сравнивать с константой string::npos

А я уже сомневаюсь. Похоже этот трюк стар как Си (точнее как ssize_t). И преобразование signed <->unsigned поэтому имплиситное. Идея типа ssize_t как раз в том, что мы возвращаем либо size_t либо -1 (то есть SIZE_T_MAX), а вызывающий код после проверки на равенство минус единице дальше кастит (как правило имплиситно) эту величину обратно к size_t. И обсуждаемый метод find похоже сделан под такой же workflow, разница только в том, что возвращаемый тип оставили unsigned, чтобы неявный кастинг был при сравнении с -1, а не при дальнейшем использовании. Но ведь и в C в качестве возвращаемого типа указывают ssize_t только для того, чтобы по определению функции сразу было понятно, что она возвращает SIZE_T_MAX в качестве ошибки. Единственное чего я не могу понять - как это работает, если отрицательные числа представлены не в дополнительном коде. В случае экзотичских архитектур с обратным, а не дополнительным кодом всё почти так же, только в качестве ошибки используется (SIZE_T_MAX - 1). Для архитектур с прямым кодом компиляторов C/C++ похоже вообще не существовало. Так что сравнение с -1 вместо string:npos - это по сути освящённая временем традиция.

S find c как работает

Функция find() возвращает индекс первого вхождения подстроки или отдельного символа в строке в виде значние я типа size_t :

#include #include int main() < std::string text ; std::cout 

Если строка или символ не найдены (как в примере выше в последнем случае), то возвращается специальная константа std::string::npos , которая представляет очень большое число (как видно из примера, число 18446744073709551615). И при поиске мы можем проверять результат функции find() на равенство этой константе:

if (text.find("banana") == std::string::npos)

Функция find имеет ряд дополнительных версий. Так, с помощью второго параметра мы можем указать индекс, с которого надо вести поиск:

#include #include int main() < std::string text ; // поиск с 10-го индекса std::cout 

Используя эту версию, мы можем написать программу для поиска количества вхождений строки в тексте, то есть выяснить, сколько раз строка встречается в тексте:

#include #include int main() < std::string text ; std::string word ; unsigned count<>; // количество вхождений for (unsigned i <>; i std::cout 

Здесь в цикле пробегаемся по тексту, в котором надо найти строку, пока счетчик i не будет равен text.length() - word.length() . С помощью функции find() получаем индекс первого вхождения слова в тексте, начиная с индекса i. Если таких вхождений не найдено, то выходим из цикла. Если же найден индекс, то счетчик i получает индекс, следующий за индексом найденного вхождения.

В итоге, поскольку искомое слово "friend" встречается в тексте два раза, то программа выведет

The word is found 2 times.

В качестве альтернативы мы могли бы использовать цикл while :

#include #include int main() < std::string text ; std::string word ; unsigned count<>; // количество вхождений size_t index<>; // начальный индекс while ((index = text.find(word, index)) != std::string::npos) < ++count; index += word.length(); // перемещаем индекс на позицию после завершения слова в тексте >std::cout

Еще одна версия позволяет искать в тексте не всю строку, а только ее часть. Для этого в качестве третьего параметра передается количество символов из искомой строки, которые программа будет искать в тексте:

#include #include int main() < std::string text ; std::string word ; // поиск с 10-го индекса 3 первых символов слова "endless", то есть "end" std::cout 

Стоит отметить, что в этом случае искомая строка должна представлять строковый литерал или строку в С-стиле (например, символьный массив с концевым нулевым байтом).

Функция rfind. Поиск в обратном порядке

Функция rfind() работает аналогично функции find() , принимает те же самые параметры, только ищет подстроку в обратном порядке - с конца строки:

#include #include int main() < std::string text ; std::cout 

Поиск любого из набора символов

Пара функций - find_first_of() и find_last_of() позволяют найти соответственно первый и последний индекс любого из набора символов:

#include #include int main() < std::string text ; std::string letters; // искомые символы std::cout 

В данном случае ищем в строке "Phone number: +23415678901" первую и последнюю позицию любого из символов из строки "0123456789". То есть таким образом мы найдем начальный и конечный индекс номера телефона.

Если нам, наоборот, надо найти позиции символов, которые НЕ представляют любой символ из набора, то мы можем использовать функции find_first_not_of() (первая позиция) и find_last_not_of() (последняя позиция):

#include #include int main() < std::string text ; std::string letters; // искомые символы std::cout 

Мы можем комбинировать функции. Например, найдем количество слов в строке:

#include #include int main() < std::string text ; // исходный текст const std::string separators< " ,;:.\"!?'*\n" >; // разделители слов unsigned count<>; // счетчик слов size_t start < text.find_first_not_of(separators) >; // начальный индекс первого слова while (start != std::string::npos) // если нашли слово < // увеличиваем счетчик слов count++; size_t end = text.find_first_of(separators, start + 1); // находим, где кончается слово if (end == std::string::npos) < end = text.length(); >start = text.find_first_not_of(separators, end + 1); // находим начальный индекс следующего слова и переустанавливаем start > // выводим количество слов std::cout 

Вкратце рассмотрим данный код. В качестве текста, где будем подсчитывать слова, определям переменную text. И также определяем строку разделителей, такие как знаки пунктуации, пробелы, символ перевода строки, которые не являются словами:

const std::string separators< " ,;:.\"!?'*\n" >; // разделители слов

Перед обработкой введенного текста фиксируем индекс первого символа первого слова в тексте. Для этого применяется функция find_first_not_of() , которая возвращает первый индекс любого символа, который не входит в строку separators:

size_t start < text.find_first_not_of(separators) >;

Далее в цикле while смотрим, является ли полученный индекс действительным индексом:

while (start != std::string::npos)

Например, если в строке одни только символы из набора separators, тогда функция find_first_not_of() возвратит значение std::string::npos , что будет означать, что в тексте больше нет непунктационных знаков.

И если start указывает на действительный индекс начала слова, то увеличиваем счетчик слово. Далее находим индекс первого символа из separators, который идет сразу после слова. То есть фактически это индекс после последнего символа слова, который помещаем в переменную end:

size_t end = text.find_first_of(separators, start + 1); // находим, где закончилось слово

Для нахождения позиции окончания слова используем функцию find_first_of() , которая возвращает первую позицию любого символа из separators, начиная с индекса start+1

Причем может быть, что функция find_first_of() не найдет ни одного символа из separators (например, слово является поседним в тексте, и после него нет никаких знаков пунктуации или пробелов), в этом случае конечный индекс равен длине текста.

if (end == std::string::npos) // если НЕ найден ни один из символов-разделителей end = text.length(); // устанавливаем переменную end на конец текста

После того, как мы нашли начальный индексы слова и его конец, переустанавливаем start на начальный индекс следующего слова и повторяем действия цикла:

start = text.find_first_not_of(separators, end + 1); // находим начальный индекс следующего слова и переустанавливаем start

В конце выводим количество найденных слов.

string::find в C++ (с примерами)

Привет! Сегодня мы подробно рассмотрим популярную функцию C++, которая помогает искать в строках - string::find . Начнем с ознакомления с этой функцией, объясним, как ее правильно использовать, продемонстрируем ее поведение на примерах и завершим урок созданием собственной простой функции поиска в строке.

Поиск подстрок в C++ с помощью string::find

Если вы хотите проверить, существует ли определенная последовательность символов или подстрока в другой строке в C++, вы можете использовать функцию string::find :

size_t string::find(const string& str, size_t pos = 0) const noexcept;
  • Эта функция принимает строку str , которую вы хотите найти.
  • У нее также есть необязательный параметр pos , указывающий, с какой позиции начать поиск.
  • Функция возвращает позицию первого вхождения подстроки. Если подстрока не найдена, она возвращает string::npos .

Рассмотрим базовую программу, использующую string::find для проверки позиции подстроки:

#include #include using namespace std; int main()  string mainStr = "Привет, это CodeLessons!"; size_t pos = mainStr.find("CodeLessons"); if(pos != string::npos)  cout  <"Найдено 'CodeLessons' на позиции: "   ; > else  cout  <"Не удалось найти 'CodeLessons'."  ; > return 0; >

Запустив вышеуказанный код, вы получите:

Найдено 'CodeLessons' на позиции: 21

Что происходит внутри string::find?

На первый взгляд функция может показаться сложной, но string::find работает по довольно простому принципу. Она сканирует основную строку и ищет первый символ подстроки. Найдя его, она проверяет, совпадают ли следующие символы с подстрокой. Если все символы совпадают, она возвращает позицию. Если нет, поиск продолжается.

Но что, если подстрока встречается в основной строке несколько раз? string::find вернет вам позицию только первого вхождения. Если вам нужно найти все вхождения, вам потребуется запустить string::find в цикле, обновляя параметр pos каждый раз.

Создаем простую функцию поиска в строке

Для развлечения и лучшего понимания давайте создадим простую собственную версию функции string::find . Назовем нашу функцию simpleFind .

#include #include using namespace std; size_t simpleFind(const string& mainStr, const string& subStr)  for(size_t i = 0; i  mainStr.length() - subStr.length(); i++)  size_t j; for(j = 0; j  subStr.length(); j++)  if(mainStr[i + j] != subStr[j])  break; > > if(j == subStr.length())  return i; > > return string::npos; > int main()  string text = "Добро пожаловать в урок CodeLessons!"; size_t found = simpleFind(text, "урок"); if(found != string::npos)  cout  <"Найдено 'урок' на позиции: "   ; > else  cout  <"Не удалось найти 'урок'."  ; > return 0; >

Запуск программы должен дать:

Найдено 'урок' на позиции: 35

Наша функция simpleFind работает, но имейте в виду, что это базовая версия. Встроенная функция string::find оптимизирована для производительности и лучше обрабатывает граничные случаи.

string::find - незаменимый инструмент для работы со строками в C++. Он предоставляет простой и эффективный способ поиска подстрок. Понимание ее работы, а также способа воссоздания ее базовой функциональности, важно для всех, кто работает с текстовыми данными в C++. Независимо от того, создаете ли вы поисковый движок или просто

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *