C++ primer 【笔记】关联容器 set

本文介绍如何在C++编程中使用set和map容器,详细解释了它们的功能、操作方法以及如何获取元素。并通过两道习题演示了实际应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值