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
В конце выводим количество найденных слов.
Как проверить, существует ли какой-нибудь определённый символ в строке?
Пожалуйста добавьте этот код в вопрос, нажав на кнопку "Править" под вопросом. А так же напишите что не так с вашим кодом.
20 мар 2021 в 16:47
Хорошо, код у вас есть. Объясните, что с ним не так. Он не работает?
20 мар 2021 в 16:48
Может и есть другие способы, но это самый лучший (по крайней мере лично я лучше не знаю) способ. Но вы пишите if((stroka.find('@')) < 20) это условие будет возвращать true когда индекс первого вхождения '@' будет < 20. Функция find() возвращает string::npos если символ в строке не найден, иначе возвращает индекс первого вхождения переданного в него символа. if(stroka.find('@') != string::npos) будет правильней писать.
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 ()
— Да, это была ошибка, Кемп, огромная ошибка, что я взялся один за это дело. Напрасно потрачены силы, время, возможности. Один… Удивительно, как беспомощен человек, когда он один! Мелкая кража, потасовка — и всё.
© Г. Уэллс "Человек-невидимка"
Спасибо сказали:
Bizdelnick Модератор Сообщения: 20512 Статус: 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 Сообщения: 1159 Статус: Профан
Re: C++: функция find()
Сообщение ArkanJR » 21.10.2014 21:42
Всё равно мне неясно, почему результат:
— Да, это была ошибка, Кемп, огромная ошибка, что я взялся один за это дело. Напрасно потрачены силы, время, возможности. Один… Удивительно, как беспомощен человек, когда он один! Мелкая кража, потасовка — и всё.
© Г. Уэллс "Человек-невидимка"
Спасибо сказали:
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 Сообщения: 1159 Статус: Профан
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.
Вот теперь понятно.
— Да, это была ошибка, Кемп, огромная ошибка, что я взялся один за это дело. Напрасно потрачены силы, время, возможности. Один… Удивительно, как беспомощен человек, когда он один! Мелкая кража, потасовка — и всё.
© Г. Уэллс "Человек-невидимка"
Спасибо сказали:
Bizdelnick Модератор Сообщения: 20512 Статус: 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 - это по сути освящённая временем традиция.->
Функция find в C++: поиск элемента
Дорогие читатели, рад вас видеть! В этой статье разберем, как работает функция find из файла algorithm .
Как использовать find
Функция find принимает 3 параметра:
- указатель на начало массива
- указатель на конец массива
- значение, которое нужно найти
Функция find будет последовательно идти по массиву с начала до конца, пока не найдет элемент, который равен значению для поиска. Если значение не будет найдено, то find вернет указатель на конец массива. Вот пример использования данной функции:
#include #include using namespace std; int main() int arr[3] = 1, 2, 3>; auto pointer = find(arr, arr + 3, 2); if (pointer == end(arr)) cout <"элемент не найден" ; > else cout <"позиция: " - begin(arr) <" значение: " <*pointer ; > return 0; >
Результат выполнения программы:
позиция: 1 значение: 2

find можно применять не ко всему массиву, а только к его части. В этом случае нужно просто передать указатели на интересующую часть массива. Важно помнить, что при поиске указатель на конец массива не учитывается.
Как реализовать find самому
Для того чтобы лучше понять как работает find , давайте реализуем свою версию этой функции для массива чисел:
#include using namespace std; int* find(int* start, int* end, int value) while (start != end) if (*start == value) return start; start++; > return end; > int main() int arr[3] = 1, 2, 3>; auto pointer = find(arr, arr + 3, 2); cout <"позиция: " - arr <", значение: " <*pointer ; return 0; >
Вывод данной программы:
позиция: 1, значение: 2
Давайте разберемся что функция find делает:
- Мы запускаем цикл while до тех пор, пока указатель start не равен указателю end .
- Если значение, на которое указывает start равно значению, которое мы ищем, то можно радоваться, мы нашли то что искали.
- Иначе двинемся дальше увеличивая указатель.
- Если мы так и не нашли value , то возвращаем end .
Поскольку с указателями можно производить арифметические операции, мы можем получить позицию искомого значения, просто вычтя start из найденного указателя: pointer - arr .
Поздравляю! Вы реализовали свою версию функции find , аналогичной той, что предоставляется в стандартной библиотеке C++.
Как использовать find с vector, set и другими контейнерами
Так как find проходит массив линейно, анализируя каждый элемент, мы можем использовать итераторы для обхода любого контейнера в C++. Давайте посмотрим, как использовать find с vector :
#include #include #include using namespace std; int main() vectorint> vec 1, 2, 3>; auto it = find(vec.begin(), vec.end(), 2); cout <"позиция: " - vec.begin() <" значение: " <*it ; return 0; >
Вывод данной программы:
позиция: 1 значение: 2
Вывод программы снова не поменялся, однако мы теперь используем .begin() и .end() для того, чтобы указать границы поиска для find .
Поскольку все контейнеры позволяют нам использовать итераторы, мы можем применять find не только к векторам, но и к спискам, множествам и т.д. Вот пример с множествами:
setint> s 1, 2, 3>; auto it = find(s.begin(), s.end(), 2); cout <"значение: " <*it ;
Стоит отметить, что мы не можем определить позицию найденного элемента в set , так как множества не гарантируют порядок хранения элементов.
Вывод данной программы:
значение: 2
Таким образом, функция find совместима с различными контейнерами в C++.
Пример программы с использованием find
Для того, чтобы закрепить изученный материал, давайте напишем простую программу. Программа будет спрашивать нас, что мы хотим сделать. У нас будет 4 варианта:
- Показать все числа, которые сейчас находятся в массиве.
- Добавить число в конец массива.
- Найти число в массиве.
- Выйти из программы.
Для поиска мы будем использовать функцию find :
#include #include using namespace std; // Отображение списка чисел void displayList(const int numbers[], const int& size) cout <"Текущие числа в списке: "; for (int i = 0; i size; i++) cout [ i] <" "; > cout ; > int main() const int MAX_SIZE = 100; int numbers[MAX_SIZE] = 1, 2, 3, 4, 5>; int currentSize = 5; while (true) // Отображение меню для пользователя cout <"\nМеню:\n"; cout <"1. Показать числа\n"; cout <"2. Добавить число\n"; cout <"3. Найти число\n"; cout <"4. Выйти\n"; cout <"Введите ваш выбор: "; int choice; cin >> choice; switch (choice) case 1: displayList(numbers, currentSize); break; case 2: if (currentSize MAX_SIZE) int newNum; cout <"Введите число для добавления: "; cin >> newNum; numbers[currentSize] = newNum; currentSize++; cout <"Число добавлено.\n"; > else cout <"Список полон.\n"; > > break; case 3: displayList(numbers, currentSize); int num; cout <"Введите число для поиска: "; cin >> num; int* result = find(numbers, numbers + currentSize, num); if (result != numbers + currentSize) cout <"Число " <" найдено в списке!" ; > else cout <"Число " <" не найдено в списке." ; > > break; case 4: cout <"До свидания!\n"; return 0; default: cout <"Неверный выбор. Пожалуйста, выберите снова.\n"; break; > > return 0; >
Теперь давайте запустим данную программу:
Меню: 1. Показать числа 2. Добавить число 3. Найти число 4. Выйти Введите ваш выбор: 1 Текущие числа в списке: 1 2 3 4 5 Меню: 1. Показать числа 2. Добавить число 3. Найти число 4. Выйти Введите ваш выбор: 3 Текущие числа в списке: 1 2 3 4 5 Введите число для поиска: 8 Число 8 не найдено в списке. Меню: 1. Показать числа 2. Добавить число 3. Найти число 4. Выйти Введите ваш выбор: 2 Введите число для добавления: 8 Число добавлено. Меню: 1. Показать числа 2. Добавить число 3. Найти число 4. Выйти Введите ваш выбор: 3 Текущие числа в списке: 1 2 3 4 5 8 Введите число для поиска: 8 Число 8 найдено в списке! Меню: 1. Показать числа 2. Добавить число 3. Найти число 4. Выйти Введите ваш выбор: 4 До свидания!
- Реализация find для строки:
Напишите программу, где вы реализуете функцию find , похожую на ту, что описана в статье, но для работы со строками (тип std::string ). Ваша функция должна искать заданный символ в строке и возвращать итератор к этому символу. Если символ не найден, возвращайте итератор к концу строки. - Использование find с разными контейнерами:
Напишите программу, которая демонстрирует использование встроенной функции find с различными контейнерами C++ (например, std::list , std::deque ). Для каждого контейнера выводите позицию найденного элемента и его значение. - Сравнение производительности:
Реализуйте две версии функции find : одну, которую вы написали сами, и другую из стандартной библиотеки C++. Сравните их производительность на больших массивах данных (например, миллион элементов) и опишите разницу во времени выполнения.
Если у вас остались вопросы или есть замечания, оставьте комментарий ниже.
Читайте также
В этом уроке вы познакомитесь с функцией log в C++. Данная функция позволяет нам получить натуральный логарифм числа. Мы разберемся с тем как работает функция log в теории и закрепим изученное на практике.
Функция ceil используется в языках C и C++ для округления числа вверх. В статье будут разобраны примеры использования этой функции. Также в конце статьи есть упражнения.
Set и multiset в C++
В данном уроке вы познакомитесь с двумя контейнерами C++, которые очень важны - set и multiset. По другому их еще называют множеством и мультимножеством. Они автоматически сортируются при добавлении нового элемента. Но у каждого из них есть своя особенность, которую мы разбираем в этой статье.
В данном уроке вы узнаете: что такое map, как правильно его использовать, какими функциями можно оперировать, а также стоит ли его использовать у себя в проектах.
vector::push_back в C++
Язык C++ предоставляет различные способы работы с данными. Функция push_back - это популярный метод добавления элементов в вектор. В этой статье мы подробно рассмотрим эту функцию, разберемся, как и когда её использовать, и обсудим некоторые интересные моменты, связанные с ней.
Функция rand в C++
Язык C++ имеет несколько способов генерации случайных чисел. Функция rand - один из самых популярных способов получить случайное число. В этой статье мы научимся использовать эту функцию, генерировать случайные числа в диапазоне, а также реализуем свой простенький генератор случайных чисел.
Функция exp используется в языках C и C++ для вычисления экспоненты. В статье будут разобраны примеры использования этой функции. Также в конце статьи есть упражнения.
string::substr в C++
C++ предлагает различные методы работы со строками. Одной из таких функций является substr, которая позволяет извлекать определенные части строки. В этой статье мы рассмотрим функцию substr, узнаем, как она работает, и посмотрим на ее многочисленные применения.
Функция sqrt используется в языках C и C++ для вычисления квадратного корня числа. В статье будут разобраны примеры использования этой функции. Также в конце статьи есть упражнения.
printf в C/C++
Функция printf - это швейцарский нож для вывода на консоль в C/C++. Из-за этого эта функция поддерживает огромное количество разных флагов и модификаторов для стилизации вывода как вам угодно. В этой статье мы разберемся на примерах, как же ей, все-таки, пользоваться.
snprintf в C/C++
Функция snprintf используется в языках C и C++ для форматирования строки без вывода ее на экран. В статье будут разобраны примеры использования этой функции. Также в конце статьи есть упражнения.
Функция sort и компаратор в C++
Что такое сортировка, как ею управлять - все ответы находятся в этой статье. Вот что вы узнаете после прочтения данной статьи: что такое компаратор, как использовать стандартную сортировку, как сортировка работает для вектора или списка.
Векторы в C++
В этом уроке вы узнаете, что такое вектор в C++, а также если вы хотите узнать, как правильно пользоваться и какие функции к им применять - то вам сюда.
Функция copy в C++
В этом уроке вы узнаете что такое функция copy, как ее использовать. А также узнаете с какими контейнерами она работает.
Стек (stack) в C++
В этой статье вы познакомитесь с структурой данных стек. Мы разберем что это за зверь и как им пользоваться в своей программе. Также мы изучим стек через массив.
string::npos в C++
Разбираем std::string::npos в C++: что это такое, как использовать с методами std::string, а также практический пример использования этой константы.
Функция fabs в C++
В данной статье мы разберемся как работает функция fabs в C++. Также мы узнаем в чем отличие fabs от abs и реализуем свою версию данной функции.
В данном уроке пойдет речь о функции pow в C++. Мы рассмотрим с примерами, как возвести число в степень, а также какие есть альтернативы у данной функции.
string::size в C++
C++ предлагает разнообразные инструменты для работы со строками, и одна из самых важных функций - это string::size. В этой статье мы подробно рассмотрим эту функцию, поймем, как она измеряет строки, и исследуем ее практическое применение.
vector::erase в C++
C++ предлагает несколько способов управления элементами в контейнерах. Функция erase — это популярный способ удаления элементов из вектора. В этой статье мы подробно рассмотрим эту функцию, разберем ее особенности и покажем практические примеры ее использования.
vector::size в C++
В C++, контейнер std::vector представляет собой динамический массив, который может автоматически изм