天天看點

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

繼續閱讀