天天看点

C++primer(第五版)第十一章编程题

练习11.3

/******************************************************************************
 * 编写你自己的单词计数程序。
******************************************************************************/

#include <map>
#include <iostream>

using std::cin;
using std::cout;
using std::map;
using std::string;

int main()
{
    map<string, size_t> word_count;
    string word;
    while (cin >> word)
        ++word_count[word];
    for (auto &w : word_count)
        cout << w.first << ": " << w.second << "\n";
    return 0;
}
           

练习11.4

/******************************************************************************
 * 扩展你的程序,忽略大小写和标点。例如,“example.”、“example,”和“Example”应该递增相同的
 * 计数器。
******************************************************************************/

#include <map>
#include <iostream>

using std::cin;
using std::cout;
using std::map;
using std::string;

int main()
{
    map<string, size_t> word_count;
    string word;
    while (cin >> word)
    {
        if (ispunct(word[word.size() - 1]))
            word.erase(word.end() - 1);
        for (auto &c : word)
            c = tolower(c);
        ++word_count[word];
    }
    for (auto &w : word_count)
        cout << w.first << ": " << w.second << "\n";
    return 0;
}
}
           

练习11.7

/******************************************************************************
 * 定义一个map,关键字是家庭的姓,值是一个vector,保存家中的孩子(们)的名。编写代码,实现添
 * 加新的家庭以及向已有家庭中添加新的孩子。
 *****************************************************************************/
#include <map>
#include <iostream>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::map;
using std::string;
using std::vector;

int main()
{
    map<string, vector<string>> famliy;
    string famliy_name, child_name;
    size_t child_count;
    char c;
    bool FLAG = true;
    while (true)
    {

        cout << "A.添加家庭\tB.向已有家庭添加孩子\tC.查看所有家庭\t其他键.退出\n";
        cin >> c;
        if (c == 'A')
        {
            vector<string> children_name;
            cout << "输入家庭的姓:";
            cin >> famliy_name;
            cout << "输入该家庭中孩子的个数:";
            cin >> child_count;
            cout << "添加家庭中孩子(们)的名:\n";
            for (size_t i = 0; i != child_count; ++i)
            {
                cin >> child_name;
                children_name.push_back(child_name);
            }
            famliy[famliy_name] = children_name;
            cout << "添加成功!\n";
        }
        else if (c == 'B')
        {
            cout << "输入家庭的姓:";
            cin >> famliy_name;
            cout << "输入新增孩子个数:";
            cin >> child_count;
            cout << "输入新增孩子(们)的名:\n";
            for (size_t i = 0; i != child_count; ++i)
            {
                cin >> child_name;
                for (auto &f : famliy)
                    if (f.first == famliy_name)
                        f.second.push_back(child_name);
            }
            cout << "添加成功!\n";
        }
        else if (c == 'C')
        {
            for (const auto &f : famliy)
            {
                cout << f.first << endl;
                for (const auto &ch : f.second)
                    cout << ch << "\t";
                cout << endl;
            }
        }
        else
            break;
    }
    return 0;
}
           

练习11.8

/******************************************************************************
 * 编写一个程序,在一个vector而不是一个set中保存不重复的单词。使用set的优点是什么?
 *****************************************************************************/

#include <vector>
#include <iostream>
#include <algorithm>

using std::cin;
using std::cout;
using std::string;
using std::vector;
int main()
{
    vector<string> words;
    string word;
    while (cin >> word)
    {
        if (!count(words.begin(), words.end(), word))
            words.push_back(word);
    }
    for (const auto &w : words)
        cout << w << "\n";
    return 0;
}
           

练习11.9

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

#include <iostream>
#include <list>
#include <map>
#include <string>

using std::cin;
using std::cout;
using std::list;
using std::map;
using std::string;

int main()
{
    map<string, list<unsigned>> wordLineNumber; //存储单词-行号map
    string line, word;                          //存储一行和一个单词
    unsigned lineNum = 0;                       //行号
    while (getline(cin, line))                  //得到一行
    {
        bool wordExist = false;          //单词是否已在map中
        unsigned curpos = 0, prepos = 0; //当前、前一个非字母字符下标
        ++lineNum;
        line += " ";                                                          //行数目加一
        for (auto it = line.begin(); it != line.end(); ++it)                  //存储每行中的单词及单词所在行号
            if (ispunct(*it) || isspace(*it) || isdigit(*it) || iscntrl(*it)) //以非字母字符分隔为单词
            {
                curpos = it - line.begin(); //记录当前非字母字符下标
                if (curpos - prepos)    //两个非字母字符之间要有单词
                {
                    word = line.substr(prepos, curpos - prepos); //提取出单词
                    for (auto &w : wordLineNumber)               //在map中查找单词
                        if (w.first == word)                     //如果找到了
                        {
                            w.second.push_back(lineNum); //记录行号
                            wordExist = true;            //单词已在map中
                            break;                       //退出查找
                        }
                    if (!wordExist) //在map中未找到单词
                    {
                        list<unsigned> lineNums;         //存储行号的列表
                        lineNums.push_back(lineNum);     //将行号存进列表
                        wordLineNumber[word] = lineNums; //添加新单词及其对应的行号
                    }
                }
                prepos = curpos + 1; //记录前一个下标为当前下班
                wordExist = false;
            }
    }
    for (const auto &w : wordLineNumber) //打印结果
    {
        cout << w.first << ": ";
        for (const auto &l : w.second)
            cout << l << " ";
        cout << "\n";
    }
    return 0;
}
           

练习11.11

/******************************************************************************
 * 不使用decltype重新定义bookst。
 *****************************************************************************/

/*** Sales_data.h ***/
#ifndef SALES_DATA_H
#define SALES_DATA_H

#include <string>

class Sales_data
{
public:
    std::string bookNo;
    std::string isbn() const { return bookNo; }
};

#endif

/*** main.c ***/
#include <set>
#include <iostream>
#include "Sales_data.h"

using std::cout;
using std::multiset;

bool comparIsbn(const Sales_data &lhs, const Sales_data &rhs)
{
    return lhs.isbn() < rhs.isbn();
}

int main()
{
    multiset<Sales_data, bool (*)(const Sales_data &, const Sales_data &)> bookstore(comparIsbn);
    Sales_data book1, book2, book3;
    book1.bookNo = "qwrwqwvr2";
    book2.bookNo = "DFGNNJEU";
    book3.bookNo = "tyiytmy";
    bookstore = {book1, book2, book3};
    for (const auto &b : bookstore)
        cout << b.isbn() << "\n";
    return 0;

}
           

练习11.12

/******************************************************************************
 * 编写程序,读入string和int的序列,将每个string和int存入一个pair中,pair保存在一个
 * vector中。
 *****************************************************************************/

#include <iostream>
#include <vector>

using std::cin;
using std::cout;
using std::pair;
using std::string;
using std::vector;

int main()
{
    vector<pair<string, int>> vpsi;
    pair<string, int> stp;
    while (cin >> stp.first >> stp.second)
        vpsi.push_back(stp);
    for (const auto &p : vpsi)
        cout << p.first << "\t" << p.second << "\n";
    return 0;
}
           

练习11.13

/******************************************************************************
 * 在上一题的程序中,至少有三种创建pair的方法。编写此函数的三个版本,分别采用不同的方法创建
 * pair。解释你认为那种形式最易于编写和理解,为什么?
 *****************************************************************************/

/*** v1 ***/
#include <iostream>
#include <vector>

using std::cin;
using std::cout;
using std::pair;
using std::string;
using std::vector;

int main()
{

    vector<pair<string, int>> vpsi;
    pair<string, int> stp("", 0);
    while (cin >> stp.first >> stp.second)
        vpsi.push_back(stp);
    for (const auto &p : vpsi)
        cout << p.first << "\t" << p.second << "\n";
    return 0;
}

/*** v2 ***/
#include <iostream>
#include <vector>

using std::cin;
using std::cout;
using std::pair;
using std::string;
using std::vector;

int main()
{

    vector<pair<string, int>> vpsi;
    pair<string, int> stp = {"", 0};
    while (cin >> stp.first >> stp.second)
        vpsi.push_back(stp);
    for (const auto &p : vpsi)
        cout << p.first << "\t" << p.second << "\n";
    return 0;
}

/*** v3 ***/
#include <iostream>
#include <vector>
#include <utility>

using std::cin;
using std::cout;
using std::make_pair;
using std::pair;
using std::string;
using std::vector;

int main()
{
    vector<pair<string, int>> vpsi;
    pair<string, int> stp = make_pair("", 0); //此处用auto会将字符串识别为C语言型的,导致不能用cin,所以显示定义
    while (cin >> stp.first >> stp.second)
        vpsi.push_back(stp);
    for (const auto &p : vpsi)
        cout << p.first << "\t" << p.second << "\n";
    return 0;
}
           

练习11.14

/******************************************************************************
 * 扩展你在11.2.1节练习(第378页)中编写的孩子姓到名的map,添加一个pair的vector,保存孩子
 * 的名和生日。
 *****************************************************************************/
#include <map>
#include <iostream>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::map;
using std::pair;
using std::string;
using std::vector;

int main()
{
    map<string, vector<pair<string, string>>> famliy;

    string famliy_name, child_name, birthday;
    size_t child_count;
    pair<string, string> child_name_birthday;
    char c;
    while (true)
    {

        cout << "A.添加家庭\tB.向已有家庭添加孩子\tC.查看所有家庭\t其他键.退出\n";
        cin >> c;
        if (c == 'A')
        {
            vector<pair<string, string>> children_name_birthday;
            cout << "输入家庭的姓:";
            cin >> famliy_name;
            cout << "输入该家庭中孩子的个数:";
            cin >> child_count;
            cout << "添加家庭中孩子(们)的名及其生日:\n";
            for (size_t i = 0; i != child_count; ++i)
            {
                cin >> child_name >> birthday;
                child_name_birthday.first = child_name;
                child_name_birthday.second = birthday;
                children_name_birthday.push_back(child_name_birthday);
            }
            famliy[famliy_name] = children_name_birthday;
            cout << "添加成功!\n";
        }
        else if (c == 'B')
        {
            cout << "输入家庭的姓:";
            cin >> famliy_name;
            cout << "输入新增孩子个数:";
            cin >> child_count;
            cout << "输入新增孩子(们)的名及其生日:\n";
            for (size_t i = 0; i != child_count; ++i)
            {
                cin >> child_name >> birthday;
                child_name_birthday.first = child_name;
                child_name_birthday.second = birthday;
                for (auto &f : famliy)
                    if (f.first == famliy_name)
                        f.second.push_back(child_name_birthday);
            }
            cout << "添加成功!\n";
        }
        else if (c == 'C')
        {
            for (const auto &f : famliy)
            {
                cout << f.first << endl;
                for (const auto &ch : f.second)
                    cout << ch.first << ": " << ch.second << "\t";
                cout << endl;
            }
        }
        else
            break;
    }
    return 0;
}
           

练习11.16

/******************************************************************************
 * 使用一个map迭代器编写一个表达式,将一个值赋予一个元素。
 *****************************************************************************/
#include <map>
#include <iostream>

using std::cout;
using std::map;
using std::string;

int main()
{
    map<string, int> mapsn = {{" ", 0}};
    auto mapit = mapsn.begin();
    mapit->second = 1;
    cout << mapit->second << "\n";
    return 0;
}
           

练习11.19

/******************************************************************************
 * 不使用decltype重新定义bookst。
 *****************************************************************************/

/*** Sales_data.h ***/
#ifndef SALES_DATA_H
#define SALES_DATA_H

#include <string>

class Sales_data
{
public:
    std::string bookNo;
    std::string isbn() const { return bookNo; }
};

#endif

/*** main.c ***/
#include <set>
#include <iostream>
#include "Sales_data.h"

using std::cout;
using std::multiset;

bool comparIsbn(const Sales_data &lhs, const Sales_data &rhs)
{
    return lhs.isbn() < rhs.isbn();
}

int main()
{
    multiset<Sales_data, bool (*)(const Sales_data &, const Sales_data &)> bookstore(comparIsbn);
    multiset<Sales_data, bool (*)(const Sales_data &, const Sales_data &)>::iterator itb = bookstore.begin();
    cout << itb->bookNo;
    return 0;
}
           

练习11.20

/******************************************************************************
 * 重写11.1节练习(第376页)的单词计数程序,使用insert代替下标操作。你认为那个程序更容易编
 * 写和阅读?解释原因。
******************************************************************************/

#include <map>
#include <iostream>

using std::cin;
using std::cout;
using std::map;
using std::string;

int main()
{
    map<string, size_t> word_count;
    string word;
    while (cin >> word)
    {
        auto ret = word_count.insert({word, 1});
        if (!ret.second)
            ++ret.first->second;
    }
    for (auto &w : word_count)
        cout << w.first << ": " << w.second << "\n";
    return 0;
}
           

练习11.23

/******************************************************************************
 * 11.2.1节练习(第378页)中的multimap以孩子的姓为关键字,保存他们的名字的vector,用multimultimap
 * 重写此map
 *****************************************************************************/

#include <map>
#include <iostream>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::multimap;
using std::string;
using std::vector;

int main()
{
    multimap<string, vector<string>> famliy;
    string famliy_name, child_name;
    size_t child_count;
    char c;
    while (true)
    {

        cout << "A.添加家庭\tB.向已有家庭添加孩子\tC.查看所有家庭\t其他键.退出\n";
        cin >> c;
        if (c == 'A')
        {
            vector<string> children_name;
            cout << "输入家庭的姓:";
            cin >> famliy_name;
            cout << "输入该家庭中孩子的个数:";
            cin >> child_count;
            cout << "添加家庭中孩子(们)的名:\n";
            for (size_t i = 0; i != child_count; ++i)
            {
                cin >> child_name;
                children_name.push_back(child_name);
            }
            famliy.insert({famliy_name, children_name});
            cout << "添加成功!\n";
        }
        else if (c == 'B')
        {
            cout << "输入家庭的姓:";
            cin >> famliy_name;
            cout << "输入新增孩子个数:";
            cin >> child_count;
            cout << "输入新增孩子(们)的名:\n";
            for (size_t i = 0; i != child_count; ++i)
            {
                cin >> child_name;
                for (auto &f : famliy)
                    if (f.first == famliy_name)
                        f.second.push_back(child_name);
            }
            cout << "添加成功!\n";
        }
        else if (c == 'C')
        {
            for (const auto &f : famliy)
            {
                cout << f.first << endl;
                for (const auto &ch : f.second)
                    cout << ch << "\t";
                cout << endl;
            }
        }
        else
            break;
    }
    return 0;
}
           

练习11.26

/******************************************************************************
 * 可以用什么类型来对一个map进行下标操作?下标运算符返回的类型是什么?请给出一个具体例子--
 * 即--定义一个map,然后写出一个可以用来对map进行下标操作的类型以及下标运算符将会返回的类型。
 *****************************************************************************/
#include <map>
#include <iostream>

using std::cout;
using std::map;

int main()
{

    map<char, int> nums;                          //定义一个map
    char str = 'q';                               //写出一个可以用来对map进行下标操作的类型
    map<char, int>::mapped_type mn = ++nums[str]; //下标运算符将会返回的类型
    cout << mn;
    return 0;
}
           

练习11.28

/******************************************************************************
 * 对于一个string到int的vector的map,定义并初始化一个变量来保存在其上调用find所返回的结
 * 果。
 *****************************************************************************/

#include <iostream>
#include <vector>
#include <map>

using std::cout;
using std::map;
using std::string;
using std::vector;

int main()
{
    map<string, vector<int>> svt = {{"qwer", vector<int>(2, 1)}, {"tyui", vector<int>(4, 3)}};
    auto svit = svt.find("tyui");
    cout << svit->second[0] << "\n";
    return 0;
}
           

练习11.31

/******************************************************************************
 * 编写程序。定义一个作者及其作品的multimap。使用find在multimap中查找一个元素并用erase删
 * 除它。确保你的程序在元素不在map中时也能正常运行。
 *****************************************************************************/

#include <map>
#include <iostream>

using std::cin;
using std::cout;
using std::multimap;
using std::string;

int main()
{
    string find_elem;
    multimap<string, string> author_works = {{"qwer", "tyui"}, {"qwer", "opas"}, {"dfgh", "jklz"}, {"dfgh", "xcvb"}};
    cout << "输入你要查找的元素:";
    cin >> find_elem;
    auto ait = author_works.find(find_elem);
    if (ait != author_works.end())
    {
        author_works.erase(ait);
        cout << "已成功删除" + find_elem + "元素。\n";
    }
    else
        cout << "元素“" + find_elem + "”不在该multimap中\n";
    cout << "现在multimap中的元素为:\n";
    for (const auto &aw : author_works)
        cout << aw.first + ": " + aw.second + "\n";
    return 0;
}
           

练习11.32

/******************************************************************************
 * 使用上一题定义的multimap编写一个程序,按字典序打印作者列表和他们的作品。
 *****************************************************************************/

#include <map>
#include <iostream>

using std::cout;
using std::multimap;
using std::string;

int main()
{
    multimap<string, string> author_works = {{"qwer", "tyui"}, {"qwer", "opas"}, {"dfgh", "jklz"}, {"dfgh", "xcvb"}};
    for (const auto &aw : author_works)
        cout << aw.first + ": " + aw.second + "\n";
    return 0;
}
           

练习11.33

/*** exercise11_33.hpp ***/
#include <fstream>

using std::ifstream;
using std::string;

void word_transform(ifstream &map_file, ifstream &input);

/*** exercise11_33.cpp ***/
#include <sstream>
#include <map>
#include <iostream>
#include "exercise11_33.hpp"

using std::cout;
using std::endl;
using std::getline;
using std::istringstream;
using std::map;
using std::runtime_error;

map<string, string> build_map(ifstream &map_file)
{
    map<string, string> trans_map;
    string key;
    string value;
    while (map_file >> key && getline(map_file, value))
        if (value.size() > 1)
            trans_map[key] = value.substr(1);
        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);
    if (map_it != m.cend())
        return map_it->second;
    else
        return s;
}

void word_transform(ifstream &map_file, ifstream &input)
{
    auto trans_map = build_map(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 << " ";
            cout << transform(word, trans_map);
        }
        cout << endl;
    }
}

/*** main.cpp ***/
#include "exercise11_33.hpp"

int main()
{
    string map_convert_file = "exercise11_38/txt/word_convert_map.txt";
    string inputfile = "exercise11_38/txt/convert_text.txt";
    ifstream map_file(map_convert_file);
    ifstream input(inputfile);
    word_transform(map_file, input);
    return 0;
}
           

练习11.38

/******************************************************************************
 *用unordered_map重写单词计数程序(参见11.1节,第375页)和单词转换程序(参见11.3.6节,第
 *391页)。
 *****************************************************************************/

/*** 单词计数程序 ***/
#include <unordered_map>
#include <iostream>

using std::cin;
using std::cout;
using std::string;
using std::unordered_map;

int main()
{
    unordered_map<string, size_t> word_count;
    string word;
    while (cin >> word)
        ++word_count[word];
    for (auto &w : word_count)
        cout << w.first << ": " << w.second << "\n";
    return 0;
}

/*** 单词转换程序 ***/

/*** exercise11_38_2.hpp ***/
#include <fstream>

using std::ifstream;
using std::string;

void word_transform(ifstream &map_file, ifstream &input);

/*** exercise11_38_2.cpp ***/
#include <sstream>
#include <unordered_map>
#include <iostream>
#include "exercise11_38_2.hpp"

using std::cout;
using std::endl;
using std::getline;
using std::istringstream;
using std::runtime_error;
using std::unordered_map;

unordered_map<string, string> build_map(ifstream &map_file)
{
    unordered_map<string, string> trans_map;
    string key;
    string value;
    while (map_file >> key && getline(map_file, value))
        if (value.size() > 1)
            trans_map[key] = value.substr(1);
        else
            throw runtime_error("no rule for " + key);
    return trans_map;
}

const string &transform(const string &s, const unordered_map<string, string> &m)
{
    auto map_it = m.find(s);
    if (map_it != m.cend())
        return map_it->second;
    else
        return s;
}

void word_transform(ifstream &map_file, ifstream &input)
{
    auto trans_map = build_map(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 << " ";
            cout << transform(word, trans_map);
        }
        cout << endl;
    }
}

/*** main ***/
#include "exercise11_38_2.hpp"

int main()
{
    string map_convert_file = "exercise11_38_2/txt/word_convert_map.txt";
    string inputfile = "exercise11_38_2/txt/convert_text.txt";
    ifstream map_file(map_convert_file);
    ifstream input(inputfile);
    word_transform(map_file, input);
    return 0;
}
           

继续阅读