//: C06:NumStringGen.h // A random number generator that produces // strings representing floating-point numbers. #ifndef NUMSTRINGGEN_H #define NUMSTRINGGEN_H #include <cstdlib> #include <string> class NumStringGen { const int sz; // Number of digits to make public: NumStringGen(int ssz = 5) : sz(ssz) {} std::string operator()() { std::string digits("0123456789"); const int ndigits = digits.size(); std::string r(sz, ' '); // Don't want a zero as the first digit r[0] = digits[std::rand() % (ndigits - 1)] + 1; // Now assign the rest for(int i = 1; i < sz; ++i) if(sz >= 3 && i == sz/2) r[i] = '.'; // Insert a decimal point else r[i] = digits[std::rand() % ndigits]; return r; } }; #endif // NUMSTRINGGEN_H ///:~
Listado 7.24. C06/NumStringGen.h
//: C06:MemFun3.cpp // Using mem_fun(). #include <algorithm> #include <cstdlib> #include <ctime> #include <functional> #include <iostream> #include <iterator> #include <string> #include <vector> #include "NumStringGen.h" using namespace std; int main() { const int SZ = 9; vector<string> vs(SZ); // Fill it with random number strings: srand(time(0)); // Randomize generate(vs.begin(), vs.end(), NumStringGen()); copy(vs.begin(), vs.end(), ostream_iterator<string>(cout, "\t")); cout << endl; const char* vcp[SZ]; transform(vs.begin(), vs.end(), vcp, mem_fun_ref(&string::c_str)); vector<double> vd; transform(vcp, vcp + SZ, back_inserter(vd), std::atof); cout.precision(4); cout.setf(ios::showpoint); copy(vd.begin(), vd.end(), ostream_iterator<double>(cout, "\t")); cout << endl; } ///:~
Listado 7.25. C06/MemFun3.cpp
//: C06:ComposeTry.cpp // A first attempt at implementing function composition. #include <cassert> #include <cstdlib> #include <functional> #include <iostream> #include <string> using namespace std; template<typename R, typename E, typename F1, typename F2> class unary_composer { F1 f1; F2 f2; public: unary_composer(F1 fone, F2 ftwo) : f1(fone), f2(ftwo) {} R operator()(E x) { return f1(f2(x)); } }; template<typename R, typename E, typename F1, typename F2> unary_composer<R, E, F1, F2> compose(F1 f1, F2 f2) { return unary_composer<R, E, F1, F2>(f1, f2); } int main() { double x = compose<double, const string&>( atof, mem_fun_ref(&string::c_str))("12.34"); assert(x == 12.34); } ///:~
Listado 7.26. C06/ComposeTry.cpp
//: C06:ComposeFinal.cpp {-edg} // An adaptable composer. #include <algorithm> #include <cassert> #include <cstdlib> #include <functional> #include <iostream> #include <iterator> #include <string> #include <vector> #include "NumStringGen.h" using namespace std; template<typename F1, typename F2> class unary_composer : public unary_function<typename F2::argument_type, typename F1::result_type> { F1 f1; F2 f2; public: unary_composer(F1 f1, F2 f2) : f1(f1), f2(f2) {} typename F1::result_type operator()(typename F2::argument_type x) { return f1(f2(x)); } }; template<typename F1, typename F2> unary_composer<F1, F2> compose(F1 f1, F2 f2) { return unary_composer<F1, F2>(f1, f2); } int main() { const int SZ = 9; vector<string> vs(SZ); // Fill it with random number strings: generate(vs.begin(), vs.end(), NumStringGen()); copy(vs.begin(), vs.end(), ostream_iterator<string>(cout, "\t")); cout << endl; vector<double> vd; transform(vs.begin(), vs.end(), back_inserter(vd), compose(ptr_fun(atof), mem_fun_ref(&string::c_str))); copy(vd.begin(), vd.end(), ostream_iterator<double>(cout, "\t")); cout << endl; } ///:~
Listado 7.27. C06/ComposeFinal.cpp