|
Программирование >> Разработка устойчивых систем
В этом примере алгоритм findjf() ищет первую пустую строку в заданном интервале, используя адаптер mem fun ref() с функцией string::empty(). После открытия файла и загрузки его содержимого в вектор этот процесс повторяется для всех пустых строк в файле. Найденные пустые строки заменяются символьной последовательностью А BLANK LINE . Все, что для этого нужно, - разыменовать итератор для выборки текущей строки. Написание пользовательских адаптеров для объектов функ14ий Попробуем написать программу, которая бы преобразовывала строковые представления вещественных чисел в их фактические числовые значения. Начнем с генератора строк: : C06:NumStringGen.h Генератор случайных вещественных чисел в строковом формате. #ifndef NUMSTRINGGEN H #define NUMSTRINGGEN H #include <string> #inc1ude <cstd1ib> #inc1ude <ctime> class NumStringGen { const int sz: Количество цифр public: NumStringGen(int ssz = 5) : sz(ssz) {} std::string operatorO() { std::string digits( 0123456789 ): const int ndigits = digits.sizeO: std::string r(sz. *): Первая цифра должна быть отлична от нуля г[0] = digits[std::rand() % *(ndigits - 1)3 + 1: Заполнение остальных цифр forCint i = 0: i < sz: i++) ifCsz >= 3 && i =- sz/2) r[i] = .: Вставка десятичной точки else r[i] = digits[std::randC) % ndigits]: return r: #endif NUMSTRINGGEN H /:- Размер строк указывается при создании объекта NumStringGen. Генератор случайных чисел выбирает цифры, а десятичная точка вставляется в середину. В следующей программе генератор NumStringGen служит для заполнения контейнера vector<string>. Но чтобы использовать стандартную библиотечную функцию atof() языка С для преобразования строк в целые числа, объекты string сначала приходится преобразовывать в char*, поскольку автоматическое преобразование типа из string в char* не поддерживается. Алгоритм transform() в сочетании с mem fun ref() и string::c str() преобразует все объекты string в char*, после чего результаты преобразуются в вещественные числа функцией atof. : C06:MemFun3.cpp Использование mem funC) linclude <algorithm> linclude <cstdlib> linclude <ctimG> linclude <functional> linclude <iostream> linclude <iterator> linclude <string> linclude <vGCtor> linclude NumStringGen.h using namespace std: int mainO { const int SZ = 9: vector<string> vs(SZ): Заполнение вектора случайными строками: srand(time(0)): Раскрутка генератора случайных чисел generate(vs.beginO. vs.endO. NumStringGenO): copy(vs.begin(). vs.endO. ostrGam iterator<string>(cout, \t )): cout endl: const char* vcpLSZ]: transform(vs.begin(), vs.endO. vcp. mem fun ref(&string::c str)): vGCtor<doublG> vd: transform(vcp. vcp + SZ. back inserter(vd). std::atof); cout.precision(4): cout.setf(ios::showpoint): copy(vd.beginO. vd.endO. ostream iterator<double>(cout. \t )): cout endl: } III- Программа выполняет две трансформации. В ходе одной объекты string преобразуются в строки С (массивы символов), а в ходе другой строки С преобразуются в числа функцией atof(). Было бы неплохо объединить эти две операции. В конце концов, если композиция функций существует в математике, почему бы ей не поддерживаться в С++? В наиболее очевидном решении шаблон композиции получает две функции в аргументах и применяет их в нужном порядке: : C06:ComposeTry.cpp Первая попытка реализовать композицию функций linclude <cassert> linclude <cstdlib> linclude <functional> linclude <iostream> linclude <string> using namespace std: tempiate<typename R. typename E. typename FI. typename F2> class unary composer { FI fl: F2 f2: public: unary composer(Fl fone. F2 ftwo) : fl(fone). f2(ftwo) {} R operatorO(E x) { return fl(f2(x)): tempiate<typename R. typename E, typename FI. typename F2> unary composer<R. E. FI. F2> composeCFl fl. F2 f2) { return unary composer<R. E. Fl. F2>(fl. f2): int mainO { double X = compose<double. const string&>(atof. mem fun ref(&stri ng::c str))( 12.34 ); assert(X == 12.34): } III:- В объекте unary composer сохраняются указатели на функции atof и string::c str, причем последняя функция применяется первой при вызове operator(). Адаптер composeO упрощает вызов, чтобы нам не приходилось явно передавать все четыре аргумента щаблона - F1 и F2 определяются на основании вызова. Однако было бы гораздо удобнее, если бы мы могли вообще обойтись без передачи аргументов щаблона. Чтобы это стало возможным, следует обеспечить наличие необходимых определений типов для адаптируемых объектов функций. Иначе говоря, мы будем предполагать, что функции, входящие в композицию, являются адаптируемыми. Для этого функция atof() должна использоваться с ptr fun(). А чтобы добиться максимальной гибкости, мы также сделаем адаптируемым щаблон unary composer на случай, если он будет передан адаптеру функции. Следующая программа использует этот подход и легко решает исходную задачу: : C06:ComposeFinal.Срр Адаптируемый шаблон композиции linclude <a1gorithm> linclude <cassert> linclude <cstdlib> linclude <functional> linclude <iostream> linclude <iterator> linclude <string> linclude <vector> linclude NumStringGen.h using namespace std: tempiate<typename Fl. typename F2> class unary composer : public unary function<typename F2::argument type. typename Fl::result type> { Fl fl: F2 f2: public: unary composer(Fl fl. F2 f2) : fl(fl). f2(f2) {} typename Fl::result type OperatorO(typename F2::argument type x) { return fl(f2(x)): tempiate<typename Fl, typename F2> unary composer<Fl. F2> compose(Fl fl. F2 f2) { return unary composer<Fl. F2>(fl. f2):
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |