Читаем Thinking In C++. Volume 2: Practical Programming полностью

Consider how to write a program that converts strings representing floating-point numbers to their actual numeric values. To get things started, here’s a generator that creates the strings:.

//: C06:NumStringGen.h

// A random number generator that produces

// strings representing floating-point numbers

#ifndef NUMSTRINGGEN_H

#define NUMSTRINGGEN_H

#include

#include

#include

class NumStringGen {

  const int sz; // Number of digits to make

public:

  NumStringGen(int ssz = 5) : sz(ssz) {

    std::srand(std::time(0));

  }

  std::string operator()() {

    static char n[] = "0123456789";

    const int nsz = sizeof n / sizeof *n;

    std::string r(sz, ' ');

    for(int i = 0; i < sz; i++)

      if(i == sz/2)

        r[i] = '.'; // Insert a decimal point

      else

        r[i] = n[std::rand() % nsz];

    return r;

  }

};

#endif // NUMSTRINGGEN_H ///:~

You tell it how big the strings should be when you create the NumStringGen object. The random number generator selects digits, and a decimal point is placed in the middle.

The following program uses NumStringGen to fill a vector. However, to use the standard C library function atof( ) to convert the strings to floating-point numbers, the string objects must first be turned into char pointers, since there is no automatic type conversion from string to char*. The transform( ) algorithm can be used with mem_fun_ref( ) and string::c_str( ) to convert all the strings to char*, and then these can be transformed using atof.

//: C06:MemFun3.cpp

// Using mem_fun()

#include

#include

#include

#include

#include

#include

#include "NumStringGen.h"

using namespace std;

int main() {

  const int sz = 9;

  vector vs(sz);

  // Fill it with random number strings:

  generate(vs.begin(), vs.end(), NumStringGen());

  copy(vs.begin(), vs.end(),

    ostream_iterator(cout, "\t"));

  cout << endl;

  const char* vcp[sz];

  transform(vs.begin(), vs.end(), vcp,

    mem_fun_ref(&string::c_str));

  vector vd;

  transform(vcp, vcp + sz, back_inserter(vd),

    std::atof);

  copy(vd.begin(), vd.end(),

    ostream_iterator(cout, "\t"));

  cout << endl;

} ///:~

This program does two transformations: one to convert strings to C-style strings (arrays of characters), and one to convert the C-style strings to numbers via atof( ). It would be nice to combine these two operations into one. After all, we can compose functions in mathematics, so why not C++?.

The obvious approach takes the two functions as arguments and applies them in the proper order:

//: C06:ComposeTry.cpp

// A first attempt at implementing function composition

#include

#include

#include

#include

#include

using namespace std;

template

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

unary_composer compose(F1 f1, F2 f2) {

   return unary_composer(f1, f2);

}

int main()

{

  double x =

    compose(atof,

      mem_fun_ref(&string::c_str))("12.34");

  assert(x == 12.34);

} ///:~

The unary_composer object in this example stores the function pointers atof and string::c_str such that the latter function is applied first when its operator( ) is called. The compose( ) function adapter is a convenience, so we don’t have to supply all four template arguments explicitly—F1 and F2 are deduced from the call.

It would be much better, of course, if we didn’t have to supply any template arguments at all. This is achieved by adhering to the convention for type definitions for adaptable function objects; in other words, we will assume that the functions to be composed are adaptable. This requires that we use ptr_fun( ) for atof( ). For maximum flexibility, we also make unary_composer adaptable in case it gets passed to a function adapter. The following program does so and easily solves the original problem.

//: C06:ComposeFinal.cpp

// An adaptable composer

#include

#include

#include

#include

#include

#include

#include

#include

#include "NumStringGen.h"

using namespace std;

template

class unary_composer

Перейти на страницу:

Похожие книги

3ds Max 2008
3ds Max 2008

Одни уверены, что нет лучшего способа обучения 3ds Мах, чем прочитать хорошую книгу. Другие склоняются к тому, что эффективнее учиться у преподавателя, который показывает, что и как нужно делать. Данное издание объединяет оба подхода. Его цель – сделать освоение 3ds Мах 2008 максимально быстрым и результативным. Часто после изучения книги у читателя возникают вопросы, почему не получился тот или иной пример. Видеокурс – это гарантия, что такие вопросы не возникнут: ведь автор не только рассказывает, но и показывает, как нужно работать в 3ds Мах.В отличие от большинства интерактивных курсов, где работа в 3ds Мах иллюстрируется на кубиках-шариках, данный видеокурс полностью практический. Все приемы работы с инструментами 3ds Мах 2008 показаны на конкретных примерах, благодаря чему после просмотра курса читатель сможет самостоятельно выполнять даже сложные проекты.

Владимир Антонович Верстак , Владимир Верстак

Программирование, программы, базы данных / Программное обеспечение / Книги по IT