cppPrimer学习11th

目录

  • cppPrimer学习11th

    • 知识点
    • 11.1
    • 11.2
    • 11.3
    • 11.4
    • 11.5
    • 11.6
    • 11.7
    • 11.8
    • 11.9
    • 11.10
    • 11.11
    • 11.12
    • 11.13
    • 11.14
    • 11.15
    • 11.16
    • 11.17
    • 11.18
    • 11.19
    • 11.20
    • 11.21
    • 11.22
    • 11.23
    • 11.24
    • 11.25
    • 11.26
    • 11.27
    • 11.28
    • 11.29
    • 11.30
    • 11.32
    • 11.33
    • 11.34
    • 11.35
    • 11.36
    • 11.37
    • 11.38


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)
        ;
}

原文地址:https://www.cnblogs.com/zongzi10010/p/12199019.html

时间: 2024-10-20 12:28:29

cppPrimer学习11th的相关文章

11th 单元测试工具JUnit的学习

1.写好一个简易的四则运算的程序 UnitTest类文件: public class UnitTest { int a; int b; int answer;//正确答案 public int plus(int a,int b){ answer = a + b; return answer; } public int minus(int a,int b){ answer = a - b; return answer; } public int multiply(int a,int b){ ans

c++ primer 5th学习时间轴[ 100% ]

学习参考: 1.Mooophy/Cpp-Primer. GitHub上star最多的一个答案,英文版,但是编程用到的单词也不多,查查就懂了.但是到第IV部分,很多题目的没有答案,或者不完整. 2.huangmingchuan/Cpp_Primer_Answers. 中文版的答案,和上一个答案差不多. 3.chihyang/CPP_Primer. 学到第IV部分才发现的一个答案,最后一部分内容很全.我猜前面应该也不错.就是star少了点,不容易被搜到. 感觉上面三个仓库都没人维护了,要是能整合就好

Vue.js学习笔记:属性绑定 v-bind

v-bind  主要用于属性绑定,Vue官方提供了一个简写方式 :bind,例如: <!-- 完整语法 --> <a v-bind:href="url"></a> <!-- 缩写 --> <a :href="url"></a> 绑定HTML Class 一.对象语法: 我们可以给v-bind:class 一个对象,以动态地切换class.注意:v-bind:class指令可以与普通的class特

Java多线程学习(吐血超详细总结)

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 目录(?)[-] 一扩展javalangThread类 二实现javalangRunnable接口 三Thread和Runnable的区别 四线程状态转换 五线程调度 六常用函数说明 使用方式 为什么要用join方法 七常见线程名词解释 八线程同步 九线程数据传递 本文主要讲了java中多线程的使用方法.线程同步.线程数据传递.线程状态及相应的一些线程函数用法.概述等. 首先讲一下进程和线程

微信小程序学习总结(2)------- 之for循环,绑定点击事件

最近公司有小程序的项目,本人有幸参与其中,一个项目做下来感觉受益匪浅,与大家做下分享,欢迎沟通交流互相学习. 先说一下此次项目本人体会较深的几个关键点:微信地图.用户静默授权.用户弹窗授权.微信充值等等. 言归正传,今天分享我遇到的关于wx:for循环绑定数据的一个tips:  1. 想必大家的都知道wx:for,如下就不用我啰嗦了: <view class="myNew" wx:for="{{list}}">{{item.title}}<view

【安全牛学习笔记】

弱点扫描 ╋━━━━━━━━━━━━━━━━━━━━╋ ┃发现弱点                                ┃ ┃发现漏洞                                ┃ ┃  基于端口五福扫描结果版本信息(速度慢)┃ ┃  搜索已公开的漏洞数据库(数量大)      ┃ ┃  使用弱点扫描器实现漏洞管理            ┃ ╋━━━━━━━━━━━━━━━━━━━━╋ [email protected]:~# searchsploit Usage:

winform学习日志(二十三)---------------socket(TCP)发送文件

一:由于在上一个随笔的基础之上拓展的所以直接上代码,客户端: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net.Sockets; using Sys

零基础的人该怎么学习JAVA

对于JAVA有所兴趣但又是零基础的人,该如何学习JAVA呢?对于想要学习开发技术的学子来说找到一个合适自己的培训机构是非常难的事情,在选择的过程中总是 因为这样或那样的问题让你犹豫不决,阻碍你前进的步伐,今天就让小编为您推荐培训机构新起之秀--乐橙谷Java培训机构,助力你成就好未来. 选择java培训就到乐橙谷 北京有什么好的Java培训机构?来乐橙谷北京学Java,零基础走起,乐橙谷Java基础班授课老师经验非常丰富,课程内容安排合理,适合于有一点点Java基础甚至一点都不会Java的同学学

最全解析如何正确学习JavaScript指南,必看!

划重点 鉴于时不时,有同学私信问我:怎么学前端的问题.这里统一回复一下,如下次再遇到问我此问题同学,就直接把本文链接地址发给你了. "前端怎么学"应该因人而异,别人的方法未必适合自己.就说说我的学习方法吧:我把大部分时间放在学习js上了.因为这个js的学习曲线,先平后陡.项目实践和练习啥的,我不说了,主要说下工作之外的时间利用问题.我是怎么学的呢,看书,分析源码.个人这几天统计了一下,前端书籍目前看了50多本吧,大部分都是js的.市面上的书基本,差不多都看过. 第一个问题:看书有啥好处