使用 set 容器必须包含 set 头文件。map 容器是键-值对的集合,好比以人名为键的地址和电话号码。相反地,set 容器只是单纯的键的集合。当只想知道一个值是否存在时,使用 set 容器是最适合的。
set 容器支持大部分map 操作 ,包括:insert、cout、find、erase。但是 set 不支持下标操作,而且没有定义 mapped_type 类型。在 set 容器中,value_type 不是 pair 类型,而是与 key_type 相同的类型。与 map 一样,set 容器存储的键也必须唯一,而且不能修改。
在 set 中添加元素
可使用 insert 操作在 set 中添加元素,
set< string > set1;
set1.insert("WB");
与 map 容器的操作一样,带有一个键参数的 insert 版本返回 pair 类型对象, 包含一个迭代器和一个 bool 值, 迭代器指向拥有该键的元素, 而 bool 值表明是否添加了元素。
另一种用法是,调用 insert 函数时,提供一对迭代器实参,插入其标记范围内所有的元素,
set< int > iset2;
iset2.insert(ivec.begin(), ivec.end()) ;
该版本的 insert 函数类似于形参为一对迭代器的构造函数——对于一个键,仅插入一个元素。使用迭代器对的 insert 版本返回 void 类型。
获取 set 中元素
set 容器不提供下标操作符。为了通过键从 set 中获取元素,可使用 find运算。如果只需简单地判断某个元素是否存在,同样可以使用 count 运算,返回 set 中该键对应的元素个数。当然,对于 set 容器,count 的返回值只能是1(该元素存在)或 0(该元素不存在)。正如不能修改 map 中元素的键部分一样,set 中的键也为 const。在获得指向 set 中某元素的迭代器后,只能对其做读操作,而不能做写操作。
习题代码
以下为《c++ primer》关于这部分的两道习题:Exercise 10.24 和 Exercise 10.25 的代码。
Exercise 10.24 编写程序通过删除单词尾部的‘s’生成该单词的非复数版本。同时,建立一个单词排除集,用于识别以‘s’结尾、但这个结尾的‘s’又不能删除的单词。例如,放在该排除集中的单词可能有 success 和 class。使用这个排除集编写程序,删除输入单词的复数后缀,而如果输入的是排除集中的单词,则保持该单词不变。
#include<iostream>
#include<fstream>
#include<set>
#include<map>
#include<vector>
#include<string>
using namespace std;
//open files in which words ending with 's' are not plural
ifstream &open_file(ifstream &in, const string file){
in.close();//close file if it was open
in.clear();//clear the file state
in.open(file.c_str());
return in;
}
//transfer plural words to singular by deleting 's' in the end.
void plural_to_singular_word(ifstream &s_end_word, vector<string> &singular ){
set<string>excluded;
string word;
while(s_end_word >> word)
excluded.insert(word);//get the excluded words from file to store into set
// to debug
cout << "file contains: ";
for(set<string>::iterator iter = excluded.begin(); iter != excluded.end(); ++iter)
cout << *iter << " ";
cout << endl;
cout << "Input your strings: ";
string w;
while(cin >> w){
string::iterator it = w.end();
if(!excluded.count(w) && *--it == 's')
w.erase(it);//if the word is excluded in the files and end with 's', delete the 's'
singular.push_back(w);//store the singulars
}
}
int main(int argc, char *argv[]){
ifstream s_end_word;
vector<string> singular;
if(argc < 2)
throw range_error(" No 's' ending word file");
if(!open_file(s_end_word, argv[1]))
throw range_error("Unable to open wor file");
plural_to_singular_word(s_end_word, singular);
cout << "singular words: ";
for(vector<string>::iterator iter = singular.begin(); iter != singular.end(); ++iter)
cout << *iter << " ";
cout << endl;
return 0;
}
Exercise 10.25 定义一个 vector 的容器,存储你在未来六个月里要阅读的书,再定义一个 set,用于记录你已经看过的书名。编写程序从 vector 中为你选择一本没有读过而现在要读的书。当它为你返回选中的书名后,应该将该书名放入记录已读书目的 set 中。如果实际上你把这本书放在一边没有看, 则本程序应该支持从已读书目的 set 中删除该书的记录。在虚拟的六个月后,输出已读书目和还没有读的书目。
#include<iostream>
#include<fstream>
#include<string>
#include<vector>
#include<set>
#include<algorithm>
#include<iterator>// for ostream_iterator
using namespace std;
//open files
ifstream &open_file(ifstream &in, const string file){
in.close();
in.clear();
in.open(file.c_str());
return in;
}
//get all books from file to store into vector
void all_books(ifstream &allBooks, vector<string> &books){
string book;
while(allBooks >> book)
books.push_back(book);
}
int main(int argc, char *argv[]){
ifstream allBooks;
vector<string>books;//all books
set<string>finishBooks;//books already read
if(argc < 2)
throw range_error("No family names file given!");
if(!open_file(allBooks, argv[1]))
throw range_error("Unable to open family name file");
all_books(allBooks, books);
cout << "All books to read: ";
copy(books.begin(), books.end(), ostream_iterator<string>(cout, " "));//output vector by copy function
cout << endl << "Please input the books you have read: " << endl;
string bk;
while(cin >> bk)
finishBooks.insert(bk);//store finished books into finishBooks
cout << "You have read: ";
copy(finishBooks.begin(), finishBooks.end(), ostream_iterator<string>(cout, " "));
cout << endl;
string willBook;//the book will be read
//check books from all books by order, and if the book has not been read, recommend it to user
for(vector<string>::iterator iter = books.begin(); iter != books.end(); ++iter)
if(!finishBooks.count(*iter)){
willBook = *iter;
break;
}
cout << "You will read " << willBook << endl;
finishBooks.insert(willBook);//insert the chosen book into finishBooks
cout << "Have u read it ?(y/N) ";
cin.sync();//clear input buffer
char c;
c = getchar();
if(c == 'N' || c == 'n' ){
finishBooks.erase(willBook);// if the book hasnot been finished, delete it from finished books
cout << willBook << " has been deleted from finished book shelf" << endl;
}
//output finished books and unfinished books
cout << endl << "Six monthes has passed, and you have read books including: " << endl;
copy(finishBooks.begin(), finishBooks.end(), ostream_iterator<string>(cout, " "));
cout << endl;
cout << "Unfinished books are: " << endl;
for(vector<string>::iterator iter = books.begin(); iter != books.end(); ++iter)
if(!finishBooks.count(*iter))
cout << *iter << " ";
cout << endl;
return 0;
}
注意使用ostream_iterator需要包含头文件 itera