• cppPrimer学习11th



    title: cppPrimer学习11th
    date: 2020/1/11 14:07:51
    toc: true

    cppPrimer学习11th

    知识点

    • map与pair的关系: map的元素是pair,一个pair就是一个模版结构体,有两个数据对

    11.1

    描述map和vector的不同
    
    map 存储的是 name--value
    vector 存的是value
    

    11.2

    分别给出最适合使用list、vector、deque、map以及set的例子
    
    list 需要中间插入的
    vector 尾部插入,随机访问
    deque  头尾插入,随机访问
    map	   需要按照name查询的
    set	   单一序列,黑白名单
    

    11.3

    11.4

    /*
    11.3 编写你自己的单词计数程序
    11.4 忽略大小写和标点。例如,“example.”、"example,"和"Example"应该递增相同的计数器
    */
    
    #include "../include/include.h"
    #include <ctype.h>
    
    int main(int argc, char const *argv[])
    {
        map<string, size_t> dic;
        string ch;
    
        while (cin >> ch)
        {
            for (auto &c : ch)
                c = tolower(c);
    
            auto lst = find_if(ch.crbegin(), ch.crend(), [](const char &ch) { return !ispunct(ch); });
            ch.erase(lst.base(), ch.cend());
    
            //cout << ch << endl;
    
            dic[ch]++;
        }
    
        for (auto &ch : dic)
        {
            cout << ch.first << "  has " << ch.second << endl;
        }
        while (1)
            ;
    
        return 0;
    }
    
    

    11.5

    解释map和set的区别。你如何选择使用哪个
    
    map	  name--value  字典 
    set	  value
    

    11.6

    解释set和list的区别。你如何选择使用哪个
    
    set		唯一性,不支持push等操作
    list	非唯一性
    

    11.7

    /**
     * 定义一个map,关键字是家庭的姓,值是一个vector,保存家中孩子们的名。编写代码,实现添加新的家庭以及向已有家庭中添加新的孩子
     * 
     * family child input
        1 2
        2 21
        1 1
        3 123
        8 12345678
        1 5
        2 22
        ^Z
        family: 1
        chile: 2,1,5,
        family: 2
        chile: 21,22,
        family: 3
        chile: 123,
        family: 8
        chile: 12345678,
     * 
     * 
     * */
    
    
    
    #include "../include/include.h"
    #include <map>
    int main(int argc, char const *argv[])
    {
        map<string, vector<string>> people;
    
        string family, child;
    
        while (cin >> family >> child)
        {
            people[family].push_back(child);
        }
    
        for (auto ch : people)
        {
            cout << "family: " << ch.first << endl;
            cout << "chile: ";
            for (auto c : ch.second)
            {
                cout << c << ",";
            }
            cout << endl;
        }
    
        while (1)
            ;
        return 0;
    }
    
    

    11.8

    /*
    编写一个程序,在一个vector而不是一个set中保存不重复的单词。使用set的优点是什么
    */
    
    #include "../include/include.h"
    int main(int argc, char const *argv[])
    {
        vector<string> v;
        string ch;
        while (cin >> ch)
        {
            v.push_back(ch);
        }
    
        sort(v.begin(), v.end());
        auto lst = unique(v.begin(), v.end());
        v.erase(lst, v.end());
        print(v);
    
        while (1)
            ;
        return 0;
    }
    

    11.9

    //定义一个map,将单词与一个行号的list关联,list中保存的是单词所出现的行号。
    
    map<string, list<int> >
        
    

    11.10

    可以定义一个vector::iterator到int的map吗?         可以
        list::iterator到int的map呢 ?			不可以,因为list的it 没有 < 和=
     
    // 但是是可以编译过去的    
    map<vector<int>::iterator, int> m;
    map<list<int>::iterator, int> l;    
    

    11.11

    using Less = bool (*)(Sales_data const&, Sales_data const&);
    multiset<Sales_data, Less> bookstore(less);
    
    
    typedef bool (*pf) (const Sales_data &, const Sales_data &);
    multiset<Sales_data, pf> bookstore(compareTsbn)
    
    multiset< Sales_data, bool(*)(const Sales_data& a Sales_data& b) >
    

    11.12

    11.13

    /*写程序,读入string和int序列,将每个string和int序列存入一个pair中,pair保存在一个vector中*/
    /*至少有三种创建pair的方法*/
    /*vec.emplace_back(str, i); //!! easiest way.  我没想到的方法*/
    
    #include "../include/include.h"
    int main(int argc, char const *argv[])
    {
        vector<pair<string, int>> v;
    
        string s;
        int i;
    
        while (cin >> s >> i)
        {
            //v.push_back(make_pair(s, i));
            //v.push_back({s, i});
            v.push_back(pair<string, int>(s, i));
            /*vec.emplace_back(str, i); //!! easiest way.  我没想到的方法*/
        }
    
        for (auto ch : v)
        {
            cout << ch.first << "--" << ch.second << endl;
        }
        while (1)
        {
            /* code */
        }
    
        return 0;
    }
    
    

    11.14

    /*
    扩展你在11.7节练习中编写的孩子姓到名的map,添加一个pair的vector,保存孩子的名字和生日
    jack 1 11-12
    jack 2 11-13
    cc 1 1-5
    cc 5 5-8
    jack 21 15-55
    ^Z
    family: cc
    child: 1,1-5
    5,5-8
    
    family: jack
    child: 1,11-12
    2,11-13
    21,15-55
    */
    
    /**
     * 11.7 定义一个map,关键字是家庭的姓,值是一个vector,保存家中孩子们的名。编写代码,实现添加新的家庭以及向已有家庭中添加新的孩子
     * 
     * family child input
        1 2
        2 21
        1 1
        3 123
        8 12345678
        1 5
        2 22
        ^Z
        family: 1
        chile: 2,1,5,
        family: 2
        chile: 21,22,
        family: 3
        chile: 123,
        family: 8
        chile: 12345678,
     * 
     * 
     * */
    
    #include "../include/include.h"
    #include <map>
    int main(int argc, char const *argv[])
    {
        map<string, vector<pair<string, string>>> people; // modify
    
        string family, child, day;
    
        while (cin >> family >> child >> day) // modify
        {
            people[family].push_back(make_pair(child, day)); // modify
        }
    
        for (auto ch : people)
        {
            cout << "family: " << ch.first << endl;
            cout << "child: ";
            for (auto c : ch.second)
            {
                cout << c.first << "," << c.second << endl; // modify
                ;
            }
            cout << endl;
        }
    
        while (1)
            ;
        return 0;
    }
    
    

    11.15

    map<int, vector<int>>::mapped_type  vector<int>
    map<int, vector<int>>::key_type		int
    map<int, vector<int>>::value_type	pair<int, vector<int> >    
        
    

    11.16

    /*
    使用一个map迭代器编写一个表达式,将一个值赋予一个元素
    */
    
    #include "../include/include.h"
    #include <map>
    
    int main(int argc, char const *argv[])
    {
        map<int, string> v;
        v[10] = "123";
        auto it = v.begin();
        cout << it->second << endl;
    
        it->second = "555";
        cout << it->second << endl;
    
        while (1)
            ;
        return 0;
    }
    

    11.17

    假定c是一个string的multiset,v是一个string的vector,解释下面的调用。指出每个调用是否合法
    
    copy(v.begin(), v.end(), inserter(c, c.end()));		//不允许对set insert,非法
    copy(v.begin(), v.end(), back_inserter(c);			//不允许对set insert,非法
    copy(c.begin(), c.end(), inserter(v, v.end()));		//合法
    copy(c.begin(), c.end(), back_inserter(v);			//合法
    

    11.18

    写出第382页循环中map_it的类型,不要使用auto或decltype.
    pair<const string, size_t>::iterator
    

    11.19

    /*
    定义一个变量,通过11.2.2节中的名为bookstore的multiset的调用begin()来初始化这个变量。
    写出变量的类型,不要使用auto或decltype
    */
    //multiset<Sales_data,decltype(compareIsbn)*> bookstore(compareIsbn);
    
    using CompareFn =bool(*)(const Sales_data& a,const Sales_data& b);
    
    multiset<Sales_data,CompareFn>::iterator it=bookstore.begin();
    
    

    11.20

    
    /*
    重写11.1节练习的单词计数程序,使用inserter代替下标操作。你认为哪个程序更容易编写和阅读?
    */
    
    /*
    11.3 编写你自己的单词计数程序
    11.4 忽略大小写和标点。例如,“example.”、"example,"和"Example"应该递增相同的计数器
    */
    
    #include "../include/include.h"
    #include <ctype.h>
    
    int main(int argc, char const *argv[])
    {
        map<string, size_t> dic;
        string ch;
    
        while (cin >> ch)
        {
            for (auto &c : ch)
                c = tolower(c);
    
            auto lst = find_if(ch.crbegin(), ch.crend(), [](const char &ch) { return !ispunct(ch); });
            ch.erase(lst.base(), ch.cend());
    
            //dic[ch]++;
            auto it = dic.insert({ch, 1});
            if (false == it.second)
            {
                (it.first->second)++;
            }
        }
    
        for (auto &ch : dic)
        {
            cout << ch.first << "  has " << ch.second << endl;
        }
        while (1)
            ;
    
        return 0;
    }
    

    11.21

    假定word_count是一个string到size_t的map,word是一个string,解释下面循环的作用
        while(cin>>word)
         ++word_count.insert({word,0}).first->second;
    
    word_count.insert({word,0}).first 返回的是map的迭代器
        word_count.insert({word,0}).first->second;  map<1,2> 2就是mapped_type 值
         ++word_count.insert({word,0}).first->second;  值++
    
    若单词已存在容器中,它指向已有元素;否则,它指向新插入的元素。
    统计输入的单词次数
        
        
    

    11.22

    给定一个map<string, vextor<int>>, 对此容器的插入一个元素的insert版本,写出其参数类型和返回类型
        
     参数类型 pair<string,vextor<int> >
     返回类型 pair< map<string,vextor<int>>::iterator,bool>
    

    11.23

    /*
    11.7练习中的map以孩子的姓为关键字,保存他们的名的vector,用multimap重写此map。
    */
    
    /**
     * 定义一个map,关键字是家庭的姓,值是一个vector,保存家中孩子们的名。编写代码,实现添加新的家庭以及向已有家庭中添加新的孩子
     * 
    */
    
    #include "../include/include.h"
    #include <map>
    int main(int argc, char const *argv[])
    {
        //map<string, vector<string>> people;
        multimap<string, string> people;
    
        string family, child;
    
        while (cin >> family >> child)
        {
            people.insert({family, child});
        }
    
        for (auto ch : people)
        {
            cout << "family: " << ch.first << endl;
            cout << "chile: " << ch.second << endl;
        }
    
        while (1)
            ;
        return 0;
    }
    
    

    11.24

    下面的程序完成什么功能?
    map<int, int> m;
    m[0]=1;
    
    map 中如果有0关键字的话,赋值为1
    否则
    	1. 创建m[0]=0
    	2. 再赋值m[0]=1
    

    11.25

    对比下面程序与上一题程序
    vector<int> v;
    v[0]=1;
    
    直接赋值v[0],但是这里的vector的capacity是0 size也是0
    

    11.26

    /*可以用什么类型来对一个map进行下标操作?
    下标运算符返回的类型是什么?请给出一个具体例子 -- 
    即,定义一个map,然后写出一个可以用来对map进行下标操作的类型以及下标运算符会返回的类型*/
    
    #include "../include/include.h"
    
    int main(int argc, char const *argv[])
    {
        map<int, int> m;
    
        //map<int, int>::iterator in = m.begin();
        m[0] = 1;
        map<int, int>::mapped_type elem = m[0];
        cout << elem << endl;
    
        // 不懂
        //type to subscript: St3mapIiiSt4lessIiESaISt4pairIKiiEEE
        //returned from the subscript operator: i
        std::cout << "type to subscript: " << typeid(m).name() << std::endl;
        std::cout << "returned from the subscript operator: " << typeid(decltype(m[0])).name() << std::endl;
    
        while (1)
            ;
        return 0;
    }
    
    

    11.27

    对于什么问题你会使用count来解决?什么时候你又会选择find呢?
    
    find  关心是否有
    count 对于multimap,multiset 统计数量,或者打印
    

    11.28

    map<string, vector<int> >m;
    map<string, vector<int> >::iterator f=m.find(string)
    

    11.29

    如果给定的关键字不在容器中,upper_bound、lower_bound 和 equal_range 分别会返回什么
    upper_bound 和 lower_bound  返回相等的迭代器,指向一个不影响排序的关键字的插入位置,如果查找的元素大于所有元素则是end
    equal_range 返回 pair<it,it> 指向关键字可插入的位置
    
    

    11.30

    for(auto pos=authors.equal_range(xxx); pos.first != pos.second; ++pos.first)
     cout<<pos.first->second<<endl;
     
    pos.first 迭代器指向了查到的元素  迭代器是map的迭代器也就是 value_type=pair<key,value>
    pos.first->second  指向了 mapped_value
     
    

    11.32

    /*
    使用上一题定义的multimap编写一个程序,按字典序打印作者列表和他们的作品。
    **/
    
    /*编写程序,定义一个作者及其作品的multimap。使用find在multimap中查找一个元素并用erase删除它。确保你的程序在元素不在map中时也能正常运行。*/
    
    #include "../include/include.h"
    
    void printMap(const multimap<string, string> &m)
    {
        for (auto ch : m)
            cout << ch.first << ":" << ch.second << endl;
    }
    
    int main(int argc, char const *argv[])
    {
        multimap<string, string> m;
        m.insert({"a", "1"});
        m.insert({"b", "2"});
        m.insert({"c", "3"});
        m.insert({"d", "4"});
        m.insert({"a", "2"});
        m.insert({"a", "3"});
        m.insert({"a", "4"});
        printMap(m);
    
        map<string, multiset<string>> m2;
        for (auto ch : m)
        {
            m2[ch.first].insert(ch.second);
        }
        for (auto ch : m2)
        {
            cout << ch.first << ":" << endl;
            for (auto l : ch.second)
                cout << l << "+";
            cout << endl;
        }
    
        while (1)
            ;
        return 0;
    }
    
    

    11.33

    //实现你自己版本的单词转换程序
    #include "../include/include.h"
    #include <fstream>
    #include <sstream>
    
    map<string, string> build_map(ifstream &if_map)
    {
        map<string, string> m;
        string key, value;
        while (if_map >> key && getline(if_map, value))
        {
            // remove 只是移动元素 ,没有删除,返回的是最后的符合的迭代器
            auto it = remove_if(value.begin(), value.end(), [](const char ch) { return (ch == ' '); });
            value.erase(it, value.end());
    
            if (value.size() > 0)
            {
                m[key] = value;
            }
        };
    
        return m;
    }
    
    string transform(const map<string, string> &m, const string &txt)
    {
        auto it = m.find(txt);
        if (it != m.end())
            return it->second;
        else
            return txt;
    }
    
    void word_transform(ifstream &map, ifstream &input)
    {
        auto string_map = build_map(map);
        string txt_line;
        while (getline(input, txt_line))
        {
            istringstream words(txt_line);
            string ch;
            while (words >> ch)
            {
                cout << transform(string_map, ch) << " ";
            }
            cout << endl;
        }
    }
    
    int main(int argc, char const *argv[])
    {
        ifstream if_rules("E:\rules.txt");
        ifstream if_txt("E:\me.txt");
        if (if_rules && if_txt)
        {
            word_transform(if_rules, if_txt);
        }
        else
        {
            if (!if_rules)
                cout << " open rules " << endl;
            if (!if_txt)
                cout << " open txt " << endl;
        }
        while (1)
            ;
    }
    

    11.34

    如果你将transform函数中的find替换为下标运算符,会发生什么情况
        map中要查找的key不存在会添加
    

    11.35

    trans_map[key] = value.substr(1);
    	改为trans_map.insert({key, value.substr(1)})
            
    使用下标进行插入,则value是最后文件中key对应的最后一个短语。
    使用insert,则key对应的是第一个短语。        
    

    11.36

    我们的程序并没有检查输入文件的合法性,特别是,它假定转换规则文件中的规则都是有意义的。
        如果文件中的某一行包含一个关键字、一个空格,然后就结束了,会发生什么?
        预测程序的行为并进行验证,再与你的程序进行比较。
    
        我的程序有判断size,如果没有判断的话,测试一下
        //if (value.size() > 0)  没有发生任何异常,没有进来 不会添加映射,也就是 比如有规则 lo ,不会替换lo为空白的
        
    

    11.37

    无序版本通常性能更好
    有序版本的优势是维护了关键字的顺序。
    当元素的关键字类型没有明显的序关系,或是维护元素的序代价非常高时,无序容器非常有用。
    但当应用要求必须维护元素的序时,有序版本就是唯一的选择
    

    11.38

    /*
    用unordered_map重写单词计数程序和单词转换程序
    11.4.cpp
    11.33.cpp
    */
    
    /*
    11.3 编写你自己的单词计数程序
    11.4 忽略大小写和标点。例如,“example.”、"example,"和"Example"应该递增相同的计数器
    */
    
    #include "../include/include.h"
    #include <ctype.h>
    #include <fstream>
    #include <sstream>
    #include <unordered_map>
    
    void test11_4()
    {
        unordered_map<string, size_t> dic;
        string ch;
    
        while (cin >> ch)
        {
            for (auto &c : ch)
                c = tolower(c);
    
            auto lst = find_if(ch.crbegin(), ch.crend(), [](const char &ch) { return !ispunct(ch); });
            ch.erase(lst.base(), ch.cend());
    
            //cout << ch << endl;
    
            dic[ch]++;
        }
    
        for (auto &ch : dic)
        {
            cout << ch.first << "  has " << ch.second << endl;
        }
        while (1)
            ;
    }
    
    unordered_map<string, string> build_map(ifstream &if_map)
    {
        unordered_map<string, string> m;
        string key, value;
        while (if_map >> key && getline(if_map, value))
        {
            // remove 只是移动元素 ,没有删除,返回的是最后的符合的迭代器
            auto it = remove_if(value.begin(), value.end(), [](const char ch) { return (ch == ' '); });
            value.erase(it, value.end());
    
            if (value.size() == 0)
                ; //cout << "size=0" << endl;
            else
            {
                m[key] = value;
            }
        };
    
        return m;
    }
    
    string transform(const unordered_map<string, string> &m, const string &txt)
    {
        auto it = m.find(txt);
        if (it != m.end())
            return it->second;
        else
            return txt;
    }
    
    void word_transform(ifstream &map, ifstream &input)
    {
        auto string_map = build_map(map);
        string txt_line;
        while (getline(input, txt_line))
        {
            istringstream words(txt_line);
            string ch;
            while (words >> ch)
            {
                cout << transform(string_map, ch) << " ";
            }
            cout << endl;
        }
    }
    
    int main(int argc, char const *argv[])
    {
        ifstream if_rules("E:\rules.txt");
        ifstream if_txt("E:\me.txt");
        if (if_rules && if_txt)
        {
            word_transform(if_rules, if_txt);
        }
        else
        {
            if (!if_rules)
                cout << " open rules " << endl;
            if (!if_txt)
                cout << " open txt " << endl;
        }
        while (1)
            ;
    }
    
    
  • 相关阅读:
    Python基础语法精讲
    使用xlwt 库将数据导入为Excel 表格
    统计指定目录下所有mp4文件的时长(包含子目录下的文件)
    获取一个目录下所有文件(完整路径,要借助os.path.join()方法)
    中国参与MOOC 建设的大学有多少所?
    蒙特卡洛方法应用
    手欠,起了一卦,看那房子的风水,悲剧了
    好无聊,大半夜地找了份传世服务端源码,编着玩
    昨晚房屋的风水
    上午,写了个小东西
  • 原文地址:https://www.cnblogs.com/zongzi10010/p/12199019.html
Copyright © 2020-2023  润新知