Функциональные объекты: дополнительные возможности
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, найти начальную пару элементов (a, b) вектора 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 в данном случае является обязательным).
|