zoukankan      html  css  js  c++  java
  • C++primer_关联容器之map

    针对C++primer中关联容器11.9的问题

    先来一道程序看看吧。程序如下如题目要求是定义一个map,将单词与一个行号的list关联,list中保存单词出现的行号、现在继续

    //定义一个map,将单词与一个行号的list关联,list中保存单词出现的行号
    //map<string,list<int>>word_lineno
    #include <iostream>
    #include<fstream>
    #include<sstream>
    #include <map>
    #include<list>
    #include <string>
    #include <algorithm>
    using namespace std;
    string &tran(string &s)
    {
        for (int p = 0; p < s.size(); ++p)
        {
            if (s[p] >= 'A'&&s[p] <= 'Z')
            {
                s[p] -= ('A' - 'a');
            }
            else if (s[p] == ',' || s[p] == '.')
            {
                s.erase(p, 1);
            }
        }
        return s;
    }
    int main(int argc, char **argv)
    {
        map<string, list<int>>word_lineno;
        string line;
        string word;
        int leneno = 0;
        while (getline(cin, line))
        {
            leneno++;
            while (cin>>word)
            {
                tran(word);
                word_lineno[word].push_back(leneno);
            }
            cin.clear();
        }
        for (const auto &w:word_lineno)
        {
            cout << w.first <<"所在行:";
            for (auto v:w.second)
            {
                cout << v << " ";
            }
            cout << endl;
        }
        system("pause");
        return 0;
    } 

    这里写图片描述
    其中本来答案中需要in文件流绑定,我却用了两个cin来控制文件输入单词以及行号控制。在这里需要注意的是cin的状态,在我们按下一次CTRL+Z后cin状态已经为false了也就是说,在后面再有cin>>word这个语句是无效的,在这样的情况下,需要对cin的状态进行恢复,也就是代码中的cin.clear();

    1. 对于map

    针对在map中遇到什么问题使用count,在什么情况下使用find?

    1. find是查找关键字在容器中出现的位置,而count还会统计关键字出现的次数,因此:
      • 当我们需要知道(允许重复关键字出现的情况)容器中有多少元素的关键字相同时,我们使用count;
      • 但是当我们只关心这个关键字是否存在于这个容器内,那么,只需要find就足够了。
      • 总之,对于不允许重复关键字的容器,count和find能达到同样的效果;
      • 最后,说一下find和下标操作的区别,就是当给定关键字不在容器内时,下标操作会插入一个关键字并将他的值定为0,所以在这种情况下,我们应该使用find进行查找。

    2.如果给定的关键字不在容器内,upper_bound、lower_bound、equal_range分别会返回什么.

    • lower_bound返回第一个具有给定关键字的元素,upper_bound则返回第一个具有给定关键字的元素之后的位置,就是这两个迭代器构成包含所有给定关键字元素的范围。若是给定关键字不在容器内,两个操作显然应该构成一个空范围,他们返回相当的迭代器,指出关键字的正确插入位置,–还不影响关键字的排序。如果给定关键字比所有关键字都大,那么他插在原先end尾后区域。
    • equal_range返回的是一个pair,他的first成员相当于lower_bound返回的迭代器,second成员相当于upper_bound返回的迭代器。因此若是给定关键字不在容器内,first和second都指向关键字的正确插入位置,两个迭代器构成一个空范围。

    编程练习,编写程序,定义一个作者及其相关作品的multimap,使用find在容器内查找一个元素并用erase删除他,确保就算容器内没有这个元素也能运行成功。

    #include <iostream>
    #include<fstream>
    #include<string>
    #include<vector>
    #include <algorithm>
    #include<utility>
    #include<map>
    
    using namespace std;
    void remove_author(multimap<string, string>&book, const string &author)//删除某个作者及其所映射的书,可以理解成某个作者犯事了,然后被要求,这个作者的书必须的下架。就是这么个意思
    {
        auto pos = book.equal_range(author);
        if (pos.first == pos.second)
        {
            cout << "并没有" << "这个作者" << endl;
        }
        else
            book.erase(pos.first, pos.second);
    }
    void print_books(multimap<string, string>&book)
    {
        cout << "当前数目有:" << endl;
        for (auto v:book)
        {
            cout << v.first << ",《" << v.second << "》" << endl;
        }
        cout << endl;
    }
    int main(int argc, char **argv)
    {
        /*vector<pair<string, int>>data;//pair的vector
        string words;
        int v;
        while (cin>>words&&cin>>v)//在这里明显cin不可以用。需要读取文件,或许本来就应该按照文件流的方式读取,
        {
            data.push_back(pair<string, int>(words, v));
    
        }
        for (auto v:data)
        {
            cout << v.first <<"  "<< v.second << endl;
        }
    */
    
        multimap<string, string>books;
        books.insert({ "Barth,Jhon", "Sot-Weed Factor" });
        books.insert({ "金庸", "笑傲江湖" });
        books.insert({ "忘语", "凡人修仙传" });
        print_books(books);
        remove_author(books,"忘语");
        print_books(books);
        system("pause");
        return 0;
    }

    运行结果如下:

    这里写图片描述
    1. 这里做的操作就是插入三本书,输出,删除一本书,在输出的效果。
    2. 在这里还可以使用find和lower_bound、upper_bound也可以实现目标,但是相对而言没有上文简单


    单词计数程序

    #include <map>
    using std::map;
    
    #include <string>
    using std::string;
    
    #include <utility>
    using std::pair;
    
    #include <cstddef>
    using std::size_t;
    
    #include <iostream>
    using std::cin; using std::cout; using std::endl;
    
    int main() 
    {
        // count the number of times each word occurs in the input
        map<string, size_t> word_count; // empty map from string to size_t
        string word;
        while (cin >> word)
          ++word_count[word];
    
        for (const auto &w : word_count)
            cout <<  w.first << " occurs " << w.second << " times" << endl;
    
        // get an iterator positioned on the first element
        auto map_it = word_count.cbegin();
        // compare the current iterator to the off-the-end iterator
        while (map_it != word_count.cend()) {
            // dereference the iterator to print the element key--value pairs
            cout << map_it->first << " occurs " 
                 << map_it->second << " times" << endl;
            ++map_it;  // increment the iterator to denote the next element
        }
    
        return 0;
    }
    

    上述代码是C++primer最后一题的标准答案,由此可以看出人家总体的风格较好,比我这个菜鸟水平好多了,考虑的也很周全。


    单词转换函数

    #include <map>
    #include <vector>
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <stdexcept>
    #include <sstream>
    
    using std::map; using std::string; using std::vector;
    using std::ifstream; using std::cout; using std::endl;
    using std::getline; 
    using std::runtime_error; using std::istringstream;
    
    map<string, string> buildMap(ifstream &map_file)
    {
        map<string, string> trans_map;   // holds the transformations
        string key;    // a word to transform
        string value;  // phrase to use instead
        // read the first word into key and the rest of the line into value
        while (map_file >> key && getline(map_file, value))
            if (value.size() > 1) // check that there is a transformation
                trans_map[key] = value.substr(1); // skip leading space 
            else
                throw runtime_error("no rule for " + key);
        return trans_map;
    }
    
    const string &
    transform(const string &s, const map<string, string> &m)
    {
        // the actual map work; this part is the heart of the program
        auto map_it = m.find(s);
        // if this word is in the transformation map
        if (map_it != m.cend()) 
            return map_it->second; // use the replacement word
        else
            return s;              // otherwise return the original unchanged
    }
    
    // first argument is the transformations file; 
    // second is file to transform
    void word_transform(ifstream &map_file, ifstream &input)
    {
        auto trans_map = buildMap(map_file); // store the transformations
    
        // for debugging purposes print the map after its built
        cout << "Here is our transformation map: 
    
    ";
        for (auto entry : trans_map)
            cout << "key: "   << entry.first
                 << "	value: " << entry.second << endl;
        cout << "
    
    ";
    
        // do the transformation of the given text 
        string text;                    // hold each line from the input
        while (getline(input, text)) {  // read a line of input
            istringstream stream(text); // read each word 
            string word;
            bool firstword = true;      // controls whether a space is printed 
            while (stream >> word) {
               if (firstword)
                   firstword = false;
               else
                   cout << " ";  // print a space between words
               // transform returns its first argument or its transformation 
               cout << transform(word, trans_map); // print the output 
            }
            cout << endl;        // done with this line of input
        }
    }
    
    int main(int argc, char **argv)
    {
        // open and check both files
        if (argc != 3)
            throw runtime_error("wrong number of arguments");
    
        ifstream map_file(argv[1]); // open transformation file 
        if (!map_file)              // check that open succeeded
            throw runtime_error("no transformation file");
    
        ifstream input(argv[2]);    // open file of text to transform
        if (!input)                 // check that open succeeded
            throw runtime_error("no input file");
    
        word_transform(map_file, input);
    
        return 0;  // exiting main will automatically close the files
    }

    //其实代码风格也没有多好,如果仔细看的话。就先这样吧。

  • 相关阅读:
    spring 配置多个properties
    redis 一些使用过的命令
    ftpclient 遇到的一些问题
    tomcat+nginx 横向扩展
    easyui 刷新页面
    tomcat 发布本地文件
    java httpclient 跳过证书验证
    https增加临时证书,tomcat配置
    echarts getAttribute”的值: 对象为 null 或未定义 错误解决方法,
    数据的导入导出
  • 原文地址:https://www.cnblogs.com/VCctor/p/5100681.html
Copyright © 2011-2022 走看看