C++编程思想 第2卷 第7章 通用容器 集合

set容器仅接受每个元素的一个副本
也对元素排序
有人喜欢从书中所有单词开始创建
但每个单词只需要一个实例 并且希望排过序
容器set是理想的选择

//: C07:WordList.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.
// Display a list of words used in a document.
#include <algorithm>
#include <cctype>
#include <cstring>
#include <fstream>
#include <iostream>
#include <iterator>
#include <set>
#include <sstream>
#include <string>
#include "../require.h"
using namespace std;

char replaceJunk(char c) {
  // Only keep alphas, space (as a delimiter), and '
  return (isalpha(c) || c == '\'') ? c : ' ';
}

int main(int argc, char* argv[]) {
  char* fname = "WordList.cpp";
  if(argc > 1) fname = argv[1];
  ifstream in(fname);
  assure(in, fname);
  set<string> wordlist;
  string line;
  while(getline(in, line)) {
    transform(line.begin(), line.end(), line.begin(),
              replaceJunk);
    istringstream is(line);
    string word;
    while(is >> word)
      wordlist.insert(word);
  }
  // Output results:
  copy(wordlist.begin(), wordlist.end(),
       ostream_iterator<string>(cout, "\n"));
  getchar();
} ///:~

输出 把WordList.cpp放在工程目录下面
'
''
'License
All
Allison
Bruce
C
Chuck
Display
Eckel
From
Inc
MindView
Only
Output
Reserved
Rights
See
Thinking
Volume
WordList
a
algorithm
alphas
and
argc
argv
as
assure
at
available
begin
by
c
cctype
char
code
copy
cout
cpp
cstring
delimiter
distributed
document
end
file
fname
fstream
getchar
getline
h
if
ifstream
in
include
insert
int
iostream
is
isalpha
istringstream
iterator
keep
line
list
main
n
namespace
net
of
ostream
package
permissions
replaceJunk
require
results
return
set
source
space
sstream
stated
std
string
the
transform
txt'
use
used
using
while
with
word
wordlist
words
www

调用transform() 
以空白字符替换每个要被忽略掉的字符
容器set不但忽略重复的单词
而且根据函数对象less<string>比较它保存的那些单词


如何使用迭代器istreambuf_iterator来构建单词表
迭代器将字符从一个对方 输入流 移动到另一个地方 一个string对象
操作依赖标准C库函数isalpha()的返回值是否为真

//: C07:WordList2.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.
// Illustrates istreambuf_iterator and insert iterators.
#include <cstring>
#include <fstream>
#include <iostream>
#include <iterator>
#include <set>
#include <string>
#include "../require.h"
using namespace std;

int main(int argc, char* argv[]) {
  char* fname = "WordList2.cpp";
  if(argc > 1) fname = argv[1];
  ifstream in(fname);
  assure(in, fname);
  istreambuf_iterator<char> p(in), end;
  set<string> wordlist;
  while(p != end) {
    string word;
    insert_iterator<string> ii(word, word.begin());
    // Find the first alpha character:
    while(p != end && !isalpha(*p))
      ++p;
    // Copy until the first non-alpha character:
    while(p != end && isalpha(*p))
      *ii++ = *p++;
    if(word.size() != 0)
      wordlist.insert(word);
  }
  // Output results:
  copy(wordlist.begin(), wordlist.end(),
    ostream_iterator<string>(cout, "\n"));
  getchar();
} ///:~

输出 将WordList2.cpp 放入工程目录
All
Allison
Bruce
C
Chuck
Copy
Eckel
Find
From
Illustrates
Inc
License
MindView
Output
Reserved
Rights
See
Thinking
Volume
WordList
alpha
and
argc
argv
assure
at
available
begin
by
c
char
character
code
copy
cout
cpp
cstring
distributed
end
file
first
fname
fstream
getchar
h
if
ifstream
ii
in
include
insert
int
iostream
isalpha
istreambuf
iterator
iterators
main
n
namespace
net
non
ostream
p
package
permissions
require
results
set
size
source
stated
std
string
the
txt
until
use
using
while
with
word
wordlist
www

这个迭代器从一个流中逐字符地提取信息
虽然istreambuf_iterator的模板参数可能暗示提取例如以int型数据
而非char型数据
当事实不是这样

TokenIterator类具有双重灵活性
首先,可以选择产生char输入的迭代器的类型
其次TokenIterator不是仅说明什么字符表示分界符
而是使用一个函数对象判定函数

//: C07:TokenIterator.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.
#ifndef TOKENITERATOR_H
#define TOKENITERATOR_H
#include <algorithm>
#include <cctype>
#include <functional>
#include <iterator>
#include <string>

struct Isalpha : std::unary_function<char, bool> {
  bool operator()(char c) { return std::isalpha(c); }
};

class Delimiters : std::unary_function<char, bool> {
  std::string exclude;
public:
  Delimiters() {}
  Delimiters(const std::string& excl) : exclude(excl) {}
  bool operator()(char c) {
    return exclude.find(c) == std::string::npos;
  }
};

template<class InputIter, class Pred = Isalpha>
class TokenIterator : public std::iterator<
    std::input_iterator_tag, std::string, std::ptrdiff_t> {
  InputIter first;
  InputIter last;
  std::string word;
  Pred predicate;
public:
  TokenIterator(InputIter begin, InputIter end,
    Pred pred = Pred())
    : first(begin), last(end), predicate(pred) {
      ++*this;
  }
  TokenIterator() {} // End sentinel
  // Prefix increment:
  TokenIterator& operator++() {
    word.resize(0);
    first = std::find_if(first, last, predicate);
    while(first != last && predicate(*first))
      word += *first++;
    return *this;
  }
  // Postfix increment
  class CaptureState {
    std::string word;
  public:
    CaptureState(const std::string& w) : word(w) {}
    std::string operator*() { return word; }
  };
  CaptureState operator++(int) {
    CaptureState d(word);
    ++*this;
    return d;
  }
  // Produce the actual value:
  std::string operator*() const { return word; }
  const std::string* operator->() const { return &word; }
  // Compare iterators:
  bool operator==(const TokenIterator&) {
    return word.size() == 0 && first == last;
  }
  bool operator!=(const TokenIterator& rv) {
    return !(*this == rv);
  }
};
#endif // TOKENITERATOR_H ///:~

TokenIterator类派生自std::iterator模板
可能表现出某些来自std::itertor的功能
但它是纯粹对迭代器进行标记的一种方式

TokenIterator测试包含许多不同来源的输入字符
包括一个streambuf_iterator 一个char*和一个deque<char>::iterator
最后 最初的单词表问题解决如下

//: C07:TokenIteratorTest.cpp {-g++}
// 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.
#include <fstream>
#include <iostream>
#include <vector>
#include <deque>
#include <set>
#include "TokenIterator.h"
#include "../require.h"
using namespace std;

int main(int argc, char* argv[]) {
  char* fname = "TokenIteratorTest.cpp";
  if(argc > 1) fname = argv[1];
  ifstream in(fname);
  assure(in, fname);
  ostream_iterator<string> out(cout, "\n");
  typedef istreambuf_iterator<char> IsbIt;
  IsbIt begin(in), isbEnd;
  Delimiters delimiters(" \t\n~;()\"<>:{}[]+-=&*#.,/\\");
  TokenIterator<IsbIt, Delimiters>
    wordIter(begin, isbEnd, delimiters), end;
  vector<string> wordlist;
  copy(wordIter, end, back_inserter(wordlist));
  // Output results:
  copy(wordlist.begin(), wordlist.end(), out);
  *out++ = "-----------------------------------";
  // Use a char array as the source:
  char* cp = "typedef std::istreambuf_iterator<char> It";
  TokenIterator<char*, Delimiters>
    charIter(cp, cp + strlen(cp), delimiters), end2;
  vector<string> wordlist2;
  copy(charIter, end2, back_inserter(wordlist2));
  copy(wordlist2.begin(), wordlist2.end(), out);
  *out++ = "-----------------------------------";
  // Use a deque<char> as the source:
  ifstream in2("TokenIteratorTest.cpp");
  deque<char> dc;
  copy(IsbIt(in2), IsbIt(), back_inserter(dc));
  TokenIterator<deque<char>::iterator,Delimiters>
    dcIter(dc.begin(), dc.end(), delimiters), end3;
  vector<string> wordlist3;
  copy(dcIter, end3, back_inserter(wordlist3));
  copy(wordlist3.begin(), wordlist3.end(), out);
  *out++ = "-----------------------------------";
  // Reproduce the Wordlist.cpp example:
  ifstream in3("TokenIteratorTest.cpp");
  TokenIterator<IsbIt, Delimiters>
    wordIter2(IsbIt(in3), isbEnd, delimiters);
  set<string> wordlist4;
  while(wordIter2 != end)
    wordlist4.insert(*wordIter2++);
  copy(wordlist4.begin(), wordlist4.end(), out);
  getchar();
} ///:~


输出 把TokenIteratorTest.cpp放目录
C07
TokenIteratorTest
cpp
g
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
include
fstream
include
iostream
include
vector
include
deque
include
set
include
TokenIterator
h
include
require
h
using
namespace
std
int
main
int
argc
char
argv
char
fname
TokenIteratorTest
cpp
if
argc
1
fname
argv
1
ifstream
in
fname
assure
in
fname
ostream_iterator
string
out
cout
n
typedef
istreambuf_iterator
char
IsbIt
IsbIt
begin
in
isbEnd
Delimiters
delimiters
t
n
TokenIterator
IsbIt
Delimiters
wordIter
begin
isbEnd
delimiters
end
vector
string
wordlist
copy
wordIter
end
back_inserter
wordlist
Output
results
copy
wordlist
begin
wordlist
end
out
out
Use
a
char
array
as
the
source
char
cp
typedef
std
istreambuf_iterator
char
It
TokenIterator
char
Delimiters
charIter
cp
cp
strlen
cp
delimiters
end2
vector
string
wordlist2
copy
charIter
end2
back_inserter
wordlist2
copy
wordlist2
begin
wordlist2
end
out
out
Use
a
deque
char
as
the
source
ifstream
in2
TokenIteratorTest
cpp
deque
char
dc
copy
IsbIt
in2
IsbIt
back_inserter
dc
TokenIterator
deque
char
iterator
Delimiters
dcIter
dc
begin
dc
end
delimiters
end3
vector
string
wordlist3
copy
dcIter
end3
back_inserter
wordlist3
copy
wordlist3
begin
wordlist3
end
out
out
Reproduce
the
Wordlist
cpp
example
ifstream
in3
TokenIteratorTest
cpp
TokenIterator
IsbIt
Delimiters
wordIter2
IsbIt
in3
isbEnd
delimiters
set
string
wordlist4
while
wordIter2
!
end
wordlist4
insert
wordIter2
copy
wordlist4
begin
wordlist4
end
out
getchar
-----------------------------------
typedef
std
istreambuf_iterator
char
It
-----------------------------------
C07
TokenIteratorTest
cpp
g
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
include
fstream
include
iostream
include
vector
include
deque
include
set
include
TokenIterator
h
include
require
h
using
namespace
std
int
main
int
argc
char
argv
char
fname
TokenIteratorTest
cpp
if
argc
1
fname
argv
1
ifstream
in
fname
assure
in
fname
ostream_iterator
string
out
cout
n
typedef
istreambuf_iterator
char
IsbIt
IsbIt
begin
in
isbEnd
Delimiters
delimiters
t
n
TokenIterator
IsbIt
Delimiters
wordIter
begin
isbEnd
delimiters
end
vector
string
wordlist
copy
wordIter
end
back_inserter
wordlist
Output
results
copy
wordlist
begin
wordlist
end
out
out
Use
a
char
array
as
the
source
char
cp
typedef
std
istreambuf_iterator
char
It
TokenIterator
char
Delimiters
charIter
cp
cp
strlen
cp
delimiters
end2
vector
string
wordlist2
copy
charIter
end2
back_inserter
wordlist2
copy
wordlist2
begin
wordlist2
end
out
out
Use
a
deque
char
as
the
source
ifstream
in2
TokenIteratorTest
cpp
deque
char
dc
copy
IsbIt
in2
IsbIt
back_inserter
dc
TokenIterator
deque
char
iterator
Delimiters
dcIter
dc
begin
dc
end
delimiters
end3
vector
string
wordlist3
copy
dcIter
end3
back_inserter
wordlist3
copy
wordlist3
begin
wordlist3
end
out
out
Reproduce
the
Wordlist
cpp
example
ifstream
in3
TokenIteratorTest
cpp
TokenIterator
IsbIt
Delimiters
wordIter2
IsbIt
in3
isbEnd
delimiters
set
string
wordlist4
while
wordIter2
!
end
wordlist4
insert
wordIter2
copy
wordlist4
begin
wordlist4
end
out
getchar
-----------------------------------
!
'License
1
1995
2
2004
All
Allison
Bruce
C
C07
Chuck
Delimiters
Eckel
From
Inc
IsbIt
It
MindView
Output
Reproduce
Reserved
Rights
See
Thinking
TokenIterator
TokenIteratorTest
Use
Volume
Wordlist
a
argc
argv
array
as
assure
at
available
back_inserter
begin
by
c
char
charIter
code
copy
cout
cp
cpp
dc
dcIter
delimiters
deque
distributed
end
end2
end3
example
file
fname
fstream
g
getchar
h
if
ifstream
in
in2
in3
include
insert
int
iostream
isbEnd
istreambuf_iterator
iterator
main
n
namespace
net
ostream_iterator
out
package
permissions
require
results
set
source
stated
std
string
strlen
t
the
txt'
typedef
use
using
vector
while
with
wordIter
wordIter2
wordlist
wordlist2
wordlist3
wordlist4
www

使用istreambuf_iterator时 
创建一个附属于istream的对象
并与默认构造函数一起作为超越末尾标记
两者用于创建将产生标识符TokenIterator
而默认构造函数创建一个伪TokenIterator超越末尾的标记
 

猜你喜欢

转载自blog.csdn.net/eyetired/article/details/82530103