C++ Advanced STL Programming (5)
其它算法配合 iterator
计算文件行数:
int line_count =
count(istreambuf_iterator<char>(ifs.rdbuf()),
istreambuf_iterator<char>(),
'\n');
当然确切地说,这是在计算文件中回车符的数量,同理,你也可以计算文件中任何字符的数量,或者某个 token 的数量:
int token_count =
count(istream_iterator<string>(ifs),
istream_iterator<string>(),
"#include");
注意上面计算的是 “#include” 作为一个 token 的数量,如果它和其他的字符连起来,是不算数的。
=====================================================
Manipulator
Manipulator 是什么?简单的说,就是一个接受一个 stream 作为参数,并且返回一个 stream 的函数,比如上面的 unskipws ,它的定义是这样的:
inline ios_base&
noskipws(ios_base& __base)
{
__base.unsetf(ios_base::skipws);
return __base;
}
这里它用了更通用的 ios_base 。知道了这一点,你大概不会对自己写一个 manipulator 有什么恐惧感了,下面这个无聊的 manipulator 会忽略 stream 遇到第一个分号之前所有的输入(包括那个分号):
template <class charT, class traits>
inline std::basic_istream<charT, traits>&
ignoreToSemicolon (std::basic_istream<charT, traits>& s)
{
s.ignore(std::numeric_limits<int>::max(), s.widen(';'));
return s;
}
不过注意,它不会忽略以后的分号,因为 ignore 只执行了一次。更通用一点,manipulator 也可以接受参数的,下面这个就是 ignoreToSemicolon 的通用版本,它接受一个参数, stream 会忽略遇到第一个该参数之前的所有输入,写起来稍微麻烦一点:
struct IgnoreTo {
char ignoreTo;
IgnoreTo(char c) : ignoreTo(c)
{}
};
std::istream& operator >> (std::istream& s, const IgnoreTo& manip)
{
s.ignore(std::numeric_limits<int>::max(), s.widen(manip.ignoreTo));
return s;
}
但是用法差不多:
copy(istream_iterator<char>(ifs >> noskipws >> IgnoreTo(';')),
istream_iterator<char>(),
ostream_iterator<char>(cout)
);
其效果跟 IgnoreToSemicolon 一样。
=====================================================