1. 程式人生 > >【足跡C++primer】38、關聯容器操作(2)

【足跡C++primer】38、關聯容器操作(2)

關聯容器操作(2)

map的下標操作

map的下標操作
map和unordered_map容器提供了下標運算符合一個相應的at函式
對於一個map使用下標操作,其行為與陣列或vector上的下標操作非常不同樣:
使用一個不再容器中的keyword作為下標。會加入一個此keyword的元素到map中

map和unordered_map的下標操作
c[k] 返回keyword為k的元素。假設keywordk不再c中,加入一個keyword為k的元素,對其進行值初始化
c.at(k) 訪問keyword為k的元素,帶引數檢測,假設k不再c重那麼返回一個異常,out_of_range


與vector和string不同。map下標運算子返回的型別與解引用map迭代器得到的型別不同。

訪問元素

假設我們關心的僅僅只是是特定元素是否在容器中的時候,泛型演算法find是最佳的選擇
void fun1()
{
    set<int> iset={0,1,2,3,4,5,6,7,8,9};
    iset.find(1);   //返回一個迭代器。指向key==1的元素
    iset.find(11);  //返回一個迭代器,值指向iset.end()
    iset.count(1);  //返回1
    iset.count(11); //返回0
}

今天上傳的有點晚了,放假了,人也懶了- -

對map使用find取代下標操作

下標操作會自己主動加入元素,不好
void fun2()
{
    map<string, size_t> word_count;
    string word;
    while(cin>>word)
        ++word_count[word];

    if(word_count.find("foobar") == word_count.end())
        cout<<"foobar is not in the map "<<endl;
}

在multimap和multiset中查詢元素

當我們遍歷multimap和multiset的時候。保證能夠得到序列中全部具有給定keyword的元素
void fun3()
{
    multimap<string, string> authors;
    string search_item("Alain de Botton");  //要查詢的作者
    auto entries=authors.count(search_item);    //元素的數量
    auto iter=authors.find(search_item);     //此作者的第一本書
    //用一個迴圈查詢此作者的全部著作
    while(entries)
    {
        cout<<iter->second<<endl;   //列印書名
        ++iter;             //指向下一個
        --entries;          //記錄列印了多少書
    }
}

一種不同的,面向迭代器的解決方法

lower_bound返回迭代器可能指向一個具有給定keyword的元素。但也可能不指向。
假設keyword不在容器中,則lower_bound會返回keyword的第一個安全插入點--不影響
容器中元素順序的插入位置

void fun4()
{
    //authors和search_item的定義,和前面的程式一樣
    //beg和end表示相應此作者的元素的範圍
    multimap<string, string> authors;
    string search_item("Alain de Botton");  //要查詢的作者

    for(auto beg=authors.lower_bound(search_item),
             end=authors.upper_bound(search_item) ; beg != end; ++beg)
        cout<<beg->second<<endl;    //列印每一個題目

    //upper_bound呼叫將end指向最後一個匹配search_item的元素的後一位
}

有木有發現,我如今部落格越來越順暢啦,相信大家也看看出來了吧,嘿嘿,我每次都打好底稿。然後再上傳,邊傳邊改,這樣就不會像曾經那樣了,非常亂,並且有點趕時間的嫌疑。 大笑

equal_range函式

不用lower_bound和upper_bound直接呼叫equal_range就可以。
這個函式接受一個keyword。返回一個迭代器pair,第一個迭代器指向
第一個和keyword匹配的元素,第二個指向和最後一個匹配的元素的後一個位置

void fun5()
{
    //authors和search_item的定義,和前面的程式一樣
    //pos儲存迭代器對,表示keyword匹配的元素範圍
    multimap<string, string> authors;
    string search_item("Alain de Botton");  //要查詢的作者

    pair<multimap<string, string>::iterator, multimap<string, string>::iterator> pos;
    for(pos=authors.equal_range(search_item); pos.first != pos.second ; ++pos.first)
        cout<<pos.first->second<<endl;  //列印每一個題目

}

一個單詞轉換的map

施主。這次能看懂多少看個人造化了^_^。
單詞轉換檔案。我把它叫做map_file.txt
brb be right back
k okay?
y why
r are
u you
pic picture
thk thanks!
18r later
我們希望轉換的文字,這個叫做input.txt
where r u
y dont u send me a pic
k thk 18r
程式輸出生成這樣:
where are you
why dont you send me a picture
okay?

thanks! later


#include<iostream>
#include<fstream>
#include<sstream>
#include<map>
#include<set>
#include<string>
#include<utility>       //pair

using namespace std;

map<string, string> bulidMap(ifstream &map_file)
{
    map<string, string> trans_map;  //儲存轉換規則
    string key;     //要轉換的單詞
    string value;   //替換後的內容
    //讀取第一個單詞存入key中,行中剩餘內容存入value
    while(map_file>>key && getline(map_file, value))
    {
        if(value.size() > 1)    //堅持是否有轉換規則
        {
            value=value.substr(1);     //跳過前導空格
            //插入map
            trans_map.insert({key, value});
        }
        else
            throw runtime_error(" no rule for "+key);
    }
    return trans_map;
}

const string & transform(const string &s, const map<string, string> &m)
{
    //實際轉換工作;此部分是程式核心
    auto map_it=m.find(s);
    //假設單詞在轉換規則map中
    if(map_it != m.cend())
    {
        return map_it->second;      //使用替換短語
    }
    else
    {
        return s;       //返回原值
    }

}


void word_transform(ifstream &map_file, ifstream &input)
{
    auto trans_map=bulidMap(map_file);  //儲存轉換規則
    string text;        //儲存輸入中的沒一行
    while(getline(input, text)) //讀取輸入一行
    {
        istringstream stream(text);     //讀取每一個單詞
        string word;
        bool firstword=true;    //控制是否列印空格

        while(stream>>word)
        {
            if(firstword)
                firstword=false;
            else
                cout<<" ";      //在單詞之間列印一個空格

            //transform返回它的第一個引數或其轉換之後的形式
//            cout<<endl<<"-------------------------------------"<<endl;
//            cout<<"這個單詞是:"<<word<<endl;
//            cout<<"-------------------------------------"<<endl;
            cout<<transform(word, trans_map);   //列印輸出
        }
        cout<<endl;     //完畢一行的轉換
    }
}

int main()
{
    ifstream map_file,input;
    map_file.open("map_file.txt");
    input.open("input.txt");

    word_transform(map_file, input);

    map_file.close();
    input.close();

    return 0;
}

好的勞動了一上午的成果!!

/**
* 功能:關聯容器操作
* 時間:2014年6月27日09:55:55
* 作者:cutter_point
*/

#include<iostream>
#include<fstream>
#include<sstream>
#include<map>
#include<set>
#include<string>
#include<utility>       //pair

using namespace std;

//map的下標操作
//map和unordered_map容器提供了下標運算符合一個相應的at函式
//對於一個map使用下標操作。其行為與陣列或vector上的下標操作非常不同樣:
//使用一個不再容器中的keyword作為下標。會加入一個此keyword的元素到map中

/*
map和unordered_map的下標操作
c[k] 返回keyword為k的元素。假設keywordk不再c中,加入一個keyword為k的元素,對其進行值初始化
c.at(k) 訪問keyword為k的元素,帶引數檢測。假設k不再c重那麼返回一個異常,out_of_range
*/

//與vector和string不同,map下標運算子返回的型別與解引用map迭代器得到的型別不同。

//訪問元素 //假設我們關心的僅僅只是是特定元素是否在容器中的時候,find是最佳的選擇 void fun1() { set<int> iset={0,1,2,3,4,5,6,7,8,9}; iset.find(1); //返回一個迭代器。指向key==1的元素 iset.find(11); //返回一個迭代器,值指向iset.end() iset.count(1); //返回1 iset.count(11); //返回0 } //對map使用find取代下標操作 //下標操作會自己主動加入元素,不好 void fun2() { map<string, size_t> word_count; string word; while(cin>>word) ++word_count[word]; if(word_count.find("foobar") == word_count.end()) cout<<"foobar is not in the map "<<endl; } //在multimap和multiset中查詢元素 //當我們遍歷multimap和multiset的時候,保證能夠得到序列中全部具有給定keyword的元素 void fun3() { multimap<string, string> authors; string search_item("Alain de Botton"); //要查詢的作者 auto entries=authors.count(search_item); //元素的數量 auto iter=authors.find(search_item); //此作者的第一本書 //用一個迴圈查詢此作者的全部著作 while(entries) { cout<<iter->second<<endl; //列印書名 ++iter; //指向下一個 --entries; //記錄列印了多少書 } } //一種不同的,面向迭代器的解決方法 /* lower_bound返回迭代器可能指向一個具有給定keyword的元素,但也可能不指向。

假設keyword不在容器中。則lower_bound會返回keyword的第一個安全插入點--不影響 容器中元素順序的插入位置 */ void fun4() { //authors和search_item的定義,和前面的程式一樣 //beg和end表示相應此作者的元素的範圍 multimap<string, string> authors; string search_item("Alain de Botton"); //要查詢的作者 for(auto beg=authors.lower_bound(search_item), end=authors.upper_bound(search_item) ; beg != end; ++beg) cout<<beg->second<<endl; //列印每一個題目 //upper_bound呼叫將end指向最後一個匹配search_item的元素的後一位 } //equal_range函式 /* 不用lower_bound和upper_bound直接呼叫equal_range就可以。 這個函式接受一個keyword。返回一個迭代器pair。第一個迭代器指向 第一個和keyword匹配的元素,第二個指向和最後一個匹配的元素的後一個位置 */ void fun5() { //authors和search_item的定義,和前面的程式一樣 //pos儲存迭代器對。表示keyword匹配的元素範圍 multimap<string, string> authors; string search_item("Alain de Botton"); //要查詢的作者 pair<multimap<string, string>::iterator, multimap<string, string>::iterator> pos; for(pos=authors.equal_range(search_item); pos.first != pos.second ; ++pos.first) cout<<pos.first->second<<endl; //列印每一個題目 } //一個單詞轉換的map //施主。這次能看懂多少看個人造化了^_^。 /* 單詞轉換檔案 brb be right back k okay? y why r are u you pic picture thk thanks! 18r later 我們希望轉換的文字 where r u y dont u send me a pic k thk 18r 程式輸出生成這樣: where are you why dont you send me a picture okay? thanks! later */ map<string, string> bulidMap(ifstream &map_file) { map<string, string> trans_map; //儲存轉換規則 string key; //要轉換的單詞 string value; //替換後的內容 //讀取第一個單詞存入key中,行中剩餘內容存入value while(map_file>>key && getline(map_file, value)) { if(value.size() > 1) //堅持是否有轉換規則 { value=value.substr(1); //跳過前導空格 //插入map trans_map.insert({key, value}); } else throw runtime_error(" no rule for "+key); } return trans_map; } const string & transform(const string &s, const map<string, string> &m) { //實際轉換工作。此部分是程式核心 auto map_it=m.find(s); //假設單詞在轉換規則map中 if(map_it != m.cend()) { return map_it->second; //使用替換短語 } else { return s; //返回原值 } } void word_transform(ifstream &map_file, ifstream &input) { auto trans_map=bulidMap(map_file); //儲存轉換規則 string text; //儲存輸入中的沒一行 while(getline(input, text)) //讀取輸入一行 { istringstream stream(text); //讀取每一個單詞 string word; bool firstword=true; //控制是否列印空格 while(stream>>word) { if(firstword) firstword=false; else cout<<" "; //在單詞之間列印一個空格 //transform返回它的第一個引數或其轉換之後的形式 // cout<<endl<<"-------------------------------------"<<endl; // cout<<"這個單詞是:"<<word<<endl; // cout<<"-------------------------------------"<<endl; cout<<transform(word, trans_map); //列印輸出 } cout<<endl; //完畢一行的轉換 } } int main() { ifstream map_file,input; map_file.open("map_file.txt"); input.open("input.txt"); word_transform(map_file, input); map_file.close(); input.close(); return 0; }


這個
bulidMap(ifstream &map_file)
裡面的return記得要放到while迴圈的外面哦
我但是為了這個吃了不少苦頭。
PS:放假了。我預計最多把今天寫完了,明天開始大概要停更了。大家不要停止學習哦。一起加油,一起努力。這本書我還是會看下去的,僅僅是部落格可能更不了了。