编写一个把表示浮点数的字符串转化为相应实际数字值的程序
有个创建字符串的发生器
//: C06:NumStringGen.h
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// 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 ///:~
使用NumStringGen来填写一个vector<string>
要使用标准C库函数atof()来把字符串转换为浮点数型
string类型对象必须首先转化为char类型指针
这是因为从string到char*没有自动类型转换
//: C06:MemFun3.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// 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;
getchar();
} ///:~
输出
48.87 71.75 20.40 78.39 17.11 87.56 38.51 40.74 63.00
48.87 71.75 20.40 78.39 17.11 87.56 38.51 40.74 63.00
做了两个转换:一是将C++字符串转换成C风格字符串 字符数组
另一个是通过atof()将C风格的字符串转换成数值
用两个函数作为参数并按合适的顺序应用它们
//: C06:ComposeTry.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// 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);
} ///:~
无异常对话框
unary_composer对象存储函数指针atof和string::c_str
在调用该对象的operator()时首先要应用后面的函数如果无需提供任何模板参数就更好了
这是对合适的函数对象坚持类型定义转换来完成
//: C06:ComposeFinal.cpp {-edg}
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// 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;
getchar();
} ///:~
输出
67.40 94.88 84.55 87.11 82.76 14.23 52.16 95.76 38.92
67.4 94.88 84.55 87.11 82.76 14.23 52.16 95.76 38.92
再次使用typename来使编译器知道涉及的成员是一个嵌套类型
一些实现将函数对象的组合作为一个扩展来支持