【足跡C++primer】38、關聯容器操作(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:放假了。我預計最多把今天寫完了,明天開始大概要停更了。大家不要停止學習哦。一起加油,一起努力。這本書我還是會看下去的,僅僅是部落格可能更不了了。