Programming Taskbook


E-mail:

Пароль:

Регистрация пользователя   Восстановление пароля

 

ЮФУ SMBU

Электронный задачник по программированию

©  М. Э. Абрамян (Южный федеральный университет, Университет МГУ-ППИ в Шэньчжэне), 1998–2024

 

PT for STL | Группы заданий | STL6Func

PrevNext


Функциональные объекты: дополнительные возможности

Задания группы STL6Func позволяют изучить дополнительные возможности, связанные с функциональными объектами. Эти возможности могут оказаться полезными при условии, что в используемых в программе объектах уже реализованы соответствующие функции-члены и/или необходимые операции.

В основном тексте каждого задания описываются средства, предусмотренные в стандарте C++11. Если эти средства отличаются от тех, которые были включены в предыдущий стандарт, то в примечании указываются их «старые» варианты. Следует иметь в виду, что большинство «старых» средств, связанных с функциональными объектами, в стандарте C++11 объявлены устаревшими, а в следующем стандарте будут исключены из языка.

STL6Func1°. Определить функциональный объект (объект-функцию, функтор) — структуру less_abs с операцией () — константной функцией-членом, имеющей два целочисленных параметра a и b и возвращающей результат сравнения |a| < |b|. Структура less_abs должна быть порождена от стандартной обобщенной структуры function<bool(int, int)>. Используя функциональный объект less_abs и алгоритм sort, отсортировать исходный вектор V целых чисел по возрастанию их абсолютных значений.

Примечание. Если компилятор не поддерживает стандарт C++11, то в качестве предка структуры less_abs используйте обобщенную структуру binary_function<int, int, bool>.

STL6Func2°. Дан вектор V целых чисел. Используя вызов алгоритма adjacent_find, найти начальную пару элементов (ab) вектора V, для которых выполняется неравенство |a| ≥ |b|, и вывести найденную пару элементов в порядке возрастания их индексов. Если подходящих пар нет, то вывести единственное число 0. Для поиска требуемой пары использовать функциональный адаптер not2 (инвертор), применив его к функциональному объекту less_abs, описанному в STL6Func1.

Примечание. Для возможности применения функционального адаптера к функциональному объекту необходимо, чтобы, во-первых, данный объект был порожден от соответствующего базового класса (в данном случае класса function или binary_function) и, во-вторых, имел реализацию операции () в виде константной функции-члена. Для непосредственного применения функционального объекта (без функциональных адаптеров) перечисленные условия не являются обязательными.

STL6Func3°. Дано целое число K (> 0) и вектор V, содержащий целые числа. Используя функциональный объект less_abs, описанный в STL6Func1, совместно с функциональным адаптером bind (связывателем) в алгоритме remove_if, а также метод erase, удалить из вектора V все элементы, абсолютная величина которых меньше K. Вывести размер преобразованного вектора V и его элементы. Для возможности использования параметра _1 адаптера bind в программу необходимо добавить директиву using namespace std::placeholders, указав ее после директивы #include <functional>.

Примечание. Если компилятор не поддерживает стандарт С++11, то вместо универсального связывателя bind следует использовать специализированный адаптер-связыватель для второго параметра bind2nd.

STL6Func4°. Дано целое число K (> 0) и вектор V, содержащий целые числа. Используя функциональный объект less_abs, описанный в STL6Func1, совместно с функциональным адаптером bind в алгоритме find_if, найти и вывести последний элемент вектора, абсолютная величина которого больше K. Если вектор не содержит требуемых элементов, то вывести 0.

Примечание. Если компилятор не поддерживает стандарт С++11, то вместо универсального связывателя bind следует использовать специализированный адаптер-связыватель для первого параметра bind1st.

STL6Func5°. Дано целое число K (> 0) и вектор V, содержащий целые числа. Используя функциональный объект less_abs, описанный в задаче STL6Func1, к которому последовательно применяются инвертор not2 и связыватель bind, построить унарный предикат для проверки условия K ≥ |x| и использовать его в качестве последнего параметра алгоритма count_if для нахождения количества элементов вектора, абсолютная величина которых меньше или равна K.

Примечания. (1) Если компилятор не поддерживает стандарт С++11, то вместо связывателя bind следует использовать bind1st.

(2) При использовании связывателя bind важен порядок вызова адаптеров: вначале not2, затем bind. Заметим, что старые варианты связывателей (bind1st и bind2nd) можно комбинировать с инверторами в любом порядке.

(3) В данном задании можно обойтись без применения инвертора (обеспечивающего преобразование строгого неравенства в нестрогое), так как для правильного решения достаточно использовать предикат со строгим неравенством вида K + 1 < |x|. Однако описанный прием может оказаться полезным в аналогичных ситуациях с более сложными функциональными объектами.

STL6Func6°. Даны векторы V1 и V2 с одинаковым количеством элементов — целых чисел. Используя алгоритм transform и стандартный функциональный объект multiplies, преобразовать вектор V2, умножив его элементы на соответствующие элементы вектора V1.

STL6Func7°. Дано целое число K и вектор V, содержащий целые числа. Используя алгоритм transform и стандартный объект-функцию minus со связывателем bind, преобразовать исходный вектор, уменьшив значения всех его элементов на величину K.

Примечание. Если компилятор не поддерживает стандарт С++11, то вместо связывателя bind следует использовать bind2nd.

STL6Func8°. Дано целое число K и два вектора V1 и V2 одинакового размера, содержащие целые числа. Используя алгоритм transform и стандартные функциональные объекты plus и multiplies с вложенными связывателями bind, преобразовать вектор V1, умножив каждый его элемент на число K и прибавив к результату значение соответствующего элемента вектора V2.

Примечание. Специализированные связыватели bind1st и bind2nd не позволяют сконструировать требуемый функциональный объект на основе стандартных. Если компилятор не поддерживает стандарт C++11, то решить задачу, не создавая новые функциональные объекты, можно с помощью двукратного применения алгоритма transform.

STL6Func9°. Определить структуру point с целочисленными членами x, y и строковым членом s. Предполагается, что строковый член s не содержит пробелов. Отношение порядка для данной структуры определяется следующим образом: A < B, если A.x < B.x или (A.x == B.x и A.y < B.y). Реализовать это отношение порядка в виде константной функции-члена bool operator<(const point& b) const. Кроме того, реализовать операцию istream& operator>>(istream& is, point& p), которая последовательно считывает из входного потока is члены x, y и s структуры p, и операцию ostream& operator<<(ostream& os, const point& p), которая записывает все члены структуры p в выходной поток os (члены записываются в том же порядке, в котором считываются; между ними вставляется пробел). Дан текстовый файл с именем name, содержащий текстовые представления элементов описанной выше структуры. Используя итератор чтения istream_iterator, заполнить этими данными вектор V с элементами типа point. Используя алгоритм stable_sort, отсортировать полученные данные с учетом заданного отношения порядка и с помощью алгоритма copy и итератора записи ostream_iterator записать отсортированный вектор в исходный файл, заменив его прежнее содержимое (при этом точки с одинаковыми координатами будут располагаться в том же порядке, что и в исходном файле, поскольку алгоритм stable_sort обеспечивает устойчивую сортировку). Каждая точка должна отображаться на новой строке.

Примечания. (1) Операции >> и << позволяют использовать для ввода и вывода объектов типа point стандартные потоковые итераторы чтения и записи.

(2) Благодаря явно определенной для структуры point операции <, в алгоритме сортировки не требуется указывать функциональный объект для сравнения элементов вектора: по умолчанию используется функциональный объект less<point>(), являющийся объектной оберткой для операции <.

(3) Следует заметить, что для сортировки по убыванию нельзя использовать (синтаксически допустимый) функциональный объект not2(less<point>()), так как в результате будет получен объект для нестрогого сравнения (a >= b), который не может использоваться в алгоритмах, связанных с сортировкой (для него нарушается условие строгого сравнения: если a «меньше» b то b не должно быть одновременно «меньше» a). В подобной ситуации надо использовать объект greater<point>(), предварительно определив для класса point операцию >.

STL6Func10°. Дан текстовый файл с именем name, содержащий текстовые представления элементов структуры point, реализованной в STL6Func9. Дополнить структуру point, включив в нее оператор преобразования operator string(), возвращающий строку с текстовыми представлениями членов x, y, s, разделенными пробелами. Кроме того, описать логическую функцию-член is_positive(), возвращающую значение true, если числа x и y являются положительными. Используя алгоритм replace_copy_if совместно с итератором чтения istream_iterator<point> и итератором записи ptout_iterator<string>, заменить те элементы из исходного текстового файла, которые имеют положительные члены x и y, на объект point (0, 0, "A"), и вывести текстовые представления всех элементов преобразованного набора. Вспомогательные контейнеры не применять. В качестве параметра-предиката алгоритма replace_copy_if использовать функцию-член is_positive, преобразовав ее в функциональный объект с помощью функционального адаптера mem_fn: mem_fn(&point::is_positive).

Примечания. (1) Если компилятор не поддерживает стандарт С++11, то вместо адаптера mem_fn следует использовать его старый вариант mem_fun_ref. Заметим, что адаптер mem_fn может применяться и в том случае, когда алгоритм обрабатывает контейнер, содержащий указатели на объекты (в то время как вместо mem_fun_ref в этой ситуации надо использовать другой функциональный адаптер: mem_fun).

(2) При реализации оператора преобразования в строку удобно использовать строковый поток ostringstream из заголовочного файла <sstream>.

(3) Если в классе или структуре определен оператор преобразования в строку, то объекты этого класса (структуры) можно указывать в качестве параметров функций Show и ShowLine, обеспечивающих вывод данных в раздел отладки окна задачника.

STL6Func11°. Дан текстовый файл с именем name, содержащий текстовые представления элементов структуры point, реализованной в STL6Func9. Используя вспомогательный вектор V с элементами типа point и алгоритм stable_partition, перегруппировать элементы в исходном наборе, переместив в начало набора все элементы, которые меньше точки с координатами (0, 0). Вывести текстовые представления всех элементов преобразованного набора (см. STL6Func10). В качестве параметра — функционального объекта в алгоритме stable_partition использовать объект less<point>(), применив к нему связыватель bind.

Примечание. Если компилятор не поддерживает стандарт С++11, то вместо связывателя bind следует использовать bind2nd.

STL6Func12°. Даны текстовые файлы с именами name1 и name2, содержащие текстовые представления элементов структуры point, реализованной в STL6Func9. Файлы содержат одинаковое количество элементов. Определить операцию сложения для объектов point, которая складывает значения соответствующих полей (как числовых, так и строковых), в виде перегруженной функции point operator+(const point& a, const point& b). Прочесть данные из файлов name1 и name2 в векторы V1 и V2 соответственно. Используя алгоритм transform с параметром plus<point>(), преобразовать элементы вектора V1, прибавив к ним соответствующие элементы вектора V2. Записать преобразованный вектор V1 в файл name1, заменив его прежнее содержимое.

STL6Func13°. Дан текстовый файл с именем name, содержащий текстовые представления элементов структуры point, реализованной в STL6Func9. Используя вспомогательный вектор V с элементами типа point и алгоритм transtorm с функциональным объектом plus (см. STL6Func12) и связывателем bind, преобразовать исходный набор, прибавив к каждому его элементу объект point (10, 20, "Z"). Вывести текстовые представления всех элементов преобразованного набора (см. STL6Func11).

Примечание. Если компилятор не поддерживает стандарт С++11, то вместо связывателя bind следует использовать bind2nd.

STL6Func14°. Дано целое число K и текстовые файлы с именами name1 и name2, содержащие текстовые представления элементов структуры point, реализованной в STL6Func10. Файлы содержат одинаковое количество элементов. Дополнить структуру point, добавив к ней функцию-член point mult(int k), выполняющую умножение объекта point на число: вызов p.mult(k) возвращает объект типа point, у которого члены x и y равны соответственно k*p.x и k*p.y, а член s совпадает со строкой p.s. Прочесть данные из файлов name1 и name2 в векторы V1 и V2. Используя алгоритм transform с подходящим функциональным объектом, содержащим два связывателя bind, объект plus (см. STL6Func12) и функцию-член mult, преобразовать элементы вектора V1, умножив каждый из них на число K и прибавив к результату умножения соответствующий элемент вектора V2. Вывести текстовые представления всех элементов преобразованного вектора V1 (см. STL6Func11).

Примечания. (1) Для связывания функции-члена mult с помощью bind достаточно указать в качестве параметра связывателя ссылку &point::mult; адаптер mem_fn (см. STL6Func10) в этом случае применять к ссылке не требуется (хотя и не запрещается).

(2) Специализированные связыватели bind1st и bind2nd не позволяют сконструировать требуемый функциональный объект на основе стандартных (ср. с STL6Func8). Если компилятор не поддерживает стандарт C++11, то решить задачу, не создавая новые функциональные объекты, можно с помощью двукратного применения алгоритма transform. При этом для выполнения умножения элементов первого вектора на K необходимо использовать связыватель bind2nd для объекта mem_fun_ref(&point::mult) (использование адаптера mem_fun_ref в данном случае является обязательным).


PrevNext

 

Рейтинг@Mail.ru

Разработка сайта:
М. Э. Абрамян, В. Н. Брагилевский

Последнее обновление:
01.01.2024