Chinaunix首页 | 论坛 | 博客
  • 博客访问: 505487
  • 博文数量: 111
  • 博客积分: 3160
  • 博客等级: 中校
  • 技术积分: 1982
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-24 11:49
个人简介

低调、勤奋。

文章分类

全部博文(111)

文章存档

2014年(2)

2013年(26)

2012年(38)

2011年(18)

2010年(27)

分类: C/C++

2012-12-30 11:24:08

一、pair类型
pair包含两个数据值,与容器一样,pair也是一种模版类型。在创建pair对象时,必须提供两个类型名:pair对象所包含的两个数据成员各自对应的类型名字,这两个类型必须相同。

如:
pair anon;
pair word_count;
pair > line;

可采用typedef简化其声明:
如:typedef pair Author;
       Author proust("Marcel", "Proust");

二、pair对象的操作
   只需要使用普通的点操作符即可访问。first和second

如:author.first, autor.second

三、生成新的pair对象
pair next_auth;
string first, last;
cin >> first >> last;
next_auth = make_pair(first, last);

四、关联容器

1、map的构造函数
map m;  创建一个名为m的空map对象,其键和值的类型分别为k和v
map m(m2);  创建m2的副本m,m与m2必须有相同的键类型和值类型。
map m(b, e); 创建map类型的对象m,存储迭代器b和e标记范围内所有元素的副本。元素的类型
必须能转换为 pair

2、键类型的约束条件
键类型必须定义 < 操作符,而且该操作符必须能“正确地工作”

3、map定义的类型

map::key_type;    在map容器中,用做索引的键的类型
map::mapped_type;  在map容器中,键所关联的值的类型
map::value_type;   一个pair类型,它的first元素具有const map::key_type类型,而second元素则为map::mapped_type类型。它的值成员可以修改,键成员不能修改。

map迭代器进行解引用将产生pair类型的对象。
对迭代器进行解引用操作时,将获得一个引用,指向容器中一个value_type类型的值。

//在一个word_count容器中获取一个迭代器
map::iterator map_it = word_count.begin();

cout << "key = " <<  map_it->first << " value = " << map_it->second << endl;

map_it->first = "new key" ;// 错误,key is const
++map_it->second;           //正确,我们能够改变其值通过迭代器

对迭代器进行解引用将获得一个pair对象,它的first成员存放键,为const,而second成员存放值。

4、给map添加元素
 
下标行为的编程意义:
对于map容器,如果下标所表示的键在容器中不存在,则添加新元素。

map迭代器返回value_type类型的值,为pair对象,下标操作返回一个mapped_type类型的值。

5、map::insert 的使用

map容器提供的insert操作
m.insert(e); e是一个用在m上的value_type类型的值,如果键e.first不在m中,则插入一个值为e.second的新元素。如果该键在m中已存在,则保持m不变。该函数返回一个pair类型对象,包含指向键为e.first的元素的map迭代器,以及一个bool类型的对象,表示是否插入了该元素。

m.insert(beg, end) beg 和 end 是标记元素范围的迭代器,其中的元素必须为 
m.value_type 类型的键-值对。对于该范围内的所有元素,如果它的键在 m 中不存在,则将该键及其关联的值插入到 m。返回 void 类型

m.insert(iter, e)  e 是一个用在 m 上的 value_type 类型的值。如果键(e.first)不在 m 中,则创建新元素,并以迭代器 iter 为起点搜索新元素存储的位置。返回一个迭代器,指向 m 中具
有给定键的元素 

6、查找并读取map中的元素
用下标方法可以获取一个元素,但是当元素不存在时,就会插入一个元素,这点需要明白。所以一般
如果不是有目的,用下面的方法更合理。

m.count(k) //返回m中k出现的次数
m.find(k) //如果m容器中存在按K索引的元素,则返回指向该元素的迭代。不存在,则返回超出末端迭代器。

读取元素而不插入该元素
int occurs = 0;
map::iterator it = word_count.find("foobar");
if(it != word_count.end())
occurs = it->second;

7、从map对象中删除元素
m.erase(k);   删除m中键为k的元素,返回size_type类型的值,表示删除的元素的个数。
m.erase(p);   从m中删除迭代器p所指向的元素,p必须指向m中确实存在的元素,且不能等于m.end(),返回void
m.erase(b ,e); 从m中删除一段范围内的元素,该范围由迭代器b和e标记。

8、map对象的迭代遍历
map::const_itertor map_it = word_count.begin();

while (map_it != word_count.end())
{
cout << map_it->first << " occors " 
                << map_it->second << " times" << endl;
        ++map_it;  
}

实例,单词转换对,a文件包含单词转换的对,将b文件按a中的对应关系进行转换。


文本查询程序代码:
1、按行读取某个文件中的内容到vector,按顺序存储。
2、将单词存放到map中,键为单词,值为单词所在的行的集合(set)。
3、查询某个单词时,打印该单词所在的行,以及所在行的内容。

querrymain.cpp

点击(此处)折叠或打开

  1. #include "text_query.hpp"
  2. #include <string>
  3. #include <vector>
  4. #include <map>
  5. #include <set>
  6. #include <iostream>
  7. #include <fstream>
  8. #include <cctype>
  9. #include <cstring>
  10. #include <cstdlib>

  11. using std::set;
  12. using std::string;
  13. using std::map;
  14. using std::vector;
  15. using std::cerr;
  16. using std::cout;
  17. using std::cin;
  18. using std::ifstream;
  19. using std::endl;

  20. string make_plural(size_t, const string&, const string&);
  21. ifstream& open_file(ifstream&, const string&);

  22. string make_plural(size_t ctr, const string &word,
  23.      const string &ending)
  24. {
  25.     return (ctr != 1) ? word + ending : word;

  26. }

  27. ifstream& open_file(ifstream & in,const string & file)
  28. {
  29.     in.close();
  30.     in.clear();

  31.     in.open(file.c_str());

  32.     return in;
  33. }
  34.     
  35. void print_results(const set<TextQuery::line_no>& locs,
  36.                  const string& sought, const TextQuery &file)
  37. {
  38.    // if the word was found, then print count and all occurrences
  39.    typedef set<TextQuery::line_no> line_nums;
  40.    line_nums::size_type size = locs.size();
  41.    cout << "\n" << sought << " occurs "
  42.         << size << " "
  43.         << make_plural(size, "time", "s") << endl;

  44.    // print each line in which the word appeared
  45.    line_nums::const_iterator it = locs.begin();
  46.    for ( ; it != locs.end(); ++it) {
  47.      cout << "\t(line "
  48.             // don't confound user with text lines starting at 0
  49.             << (*it) + 1 << ") "
  50.             << file.text_line(*it) << endl;
  51.    }
  52. }

  53. int main(int argc, char **argv)
  54. {
  55.     ifstream infile;
  56.     if (argc < 2 || !open_file(infile, argv[1]))
  57.     {
  58.         cerr << "No input file!" << endl;
  59.         return EXIT_FAILURE;
  60.     }

  61.     TextQuery tq;
  62.     tq.read_file(infile);

  63.     tq.display_map();

  64.      // iterate with the user: prompt for a word to find and print results
  65.     // loop indefinitely; the loop exit is inside the while
  66.     while (true)
  67.     {
  68.         cout << "enter word to look for, or q to quit: ";
  69.         string s;
  70.         cin >> s;

  71.         // stop if hit eof on input or a 'q' is entered
  72.         if (!cin || s == "q") break;

  73.         // get the set of line numbers on which this word appears
  74.         set<TextQuery::line_no> locs = tq.run_query(s);

  75.         // print count and all occurrences, if any
  76.         print_results(locs, s, tq);
  77.      }
  78.     return 0;
  79. }
Text_query.hpp

点击(此处)折叠或打开

  1. #ifndef TEXTQUERY_HPP
  2. #define TEXTQUERY_HPP
  3. #include <string>
  4. #include <vector>
  5. #include <map>
  6. #include <set>
  7. #include <iostream>
  8. #include <fstream>
  9. #include <cstring>

  10. using std::ifstream;

  11. class TextQuery{

  12. public:
  13.     typedef std::string::size_type str_size;
  14.     typedef std::vector<std::string>::size_type line_no;

  15.     /* interface:
  16.      * read_file builds internal data structures for the given file
  17.      * run_query finds the given word and returns set of lines on which it appears
  18.      * text_line returns a requested line from the input file
  19.      */
  20.     void read_file(ifstream &is)
  21.         { store_file(is); build_map();}

  22.     std::set<line_no> run_query(const std::string&) const;  //形参表后跟上const 表示该函数为常量成员函数,const成员函数不能修改调用该函数的对象,
  23.     std::string text_line(line_no) const;
  24.     str_size size() const {return lines_of_text.size();}
  25.     void display_map();

  26. private:

  27.     void store_file(ifstream&);
  28.     void build_map();

  29.      //
  30.      std::vector<std::string> lines_of_text;

  31.      //set
  32.      std::map< std::string, std::set<line_no> > word_map;

  33.      static std::string whitespace_chars;

  34.      static std::string cleanup_str(const std::string&);

  35. };

  36. #endif
TextQuery.cpp

点击(此处)折叠或打开

  1. #include "text_query.hpp"
  2. #include <sstream>
  3. #include <string>
  4. #include <vector>
  5. #include <map>
  6. #include <set>
  7. #include <iostream>
  8. #include <fstream>
  9. #include <cctype>
  10. #include <cstring>
  11. #include <stdexcept>

  12. using std::istringstream;
  13. using std::set;
  14. using std::string;
  15. using std::getline;
  16. using std::map;
  17. using std::vector;
  18. using std::cerr;
  19. using std::cout;
  20. using std::cin;
  21. using std::ifstream;
  22. using std::endl;
  23. using std::ispunct;
  24. using std::tolower;
  25. using std::strlen;
  26. using std::out_of_range;

  27. string TextQuery::text_line(line_no line) const
  28. {
  29.     if (line < lines_of_text.size())
  30.     {
  31.         return lines_of_text[line];
  32.     }
  33.     throw std::out_of_range("line number out of range");
  34. }

  35. //×÷lines_of_text ò
  36. void TextQuery::store_file(ifstream &is)
  37. {
  38.     string textline;
  39.     while (getline(is, textline))
  40.         lines_of_text.push_back(textline);
  41. }

  42. // \v: vertical tab; \f: formfeed; \r: carriage return are
  43. // treated as whitespace characters along with space, tab and newline
  44. string TextQuery::whitespace_chars(" \t\n\v\r\f");

  45. //lines_of_texté··word_map
  46. void TextQuery::build_map()
  47. {
  48.     for (line_no line_num = 0;
  49.      line_num != lines_of_text.size();
  50.                  ++line_num)
  51.     {
  52.         istringstream line(lines_of_text[line_num]);
  53.      string word;
  54.         while (line >> word)
  55.         {
  56.             //printf("read word is [%s] \n", word.c_str());
  57.             //word_map[cleanup_str(word)]setàó÷insertset
  58.             word_map[cleanup_str(word)].insert(line_num); // cleanup_str±ê·
  59.         }
  60.     }
  61. }

  62. set<TextQuery::line_no>
  63. TextQuery::run_query(const string &query_word) const
  64. {
  65.     // Note: ±findé±íword_map


  66.     map<string, set<line_no> >::const_iterator
  67.      loc = word_map.find(cleanup_str(query_word));

  68.     if (loc == word_map.end())
  69.         return set<line_no>(); //return empty set
  70.     else
  71.         return loc->second;

  72. }

  73. void TextQuery::display_map()
  74. {
  75.     map< string, set<line_no> >::iterator iter = word_map.begin(),
  76.          iter_end = word_map.end();
  77.     for (; iter != iter_end; ++iter)
  78.     {
  79.         cout << "word: " << iter->first << " {";
  80.         
  81.      // fetch location vector as a const reference to avoid copying it
  82.      const set<line_no> &text_locs = iter->second;
  83.      set<line_no>::const_iterator loc_iter = text_locs.begin(),
  84.                                     loc_iter_end = text_locs.end();

  85.      // print all line numbers for this word
  86.      while (loc_iter != loc_iter_end)
  87.      {
  88.             cout << *loc_iter;

  89.             if (++loc_iter != loc_iter_end)
  90.                  cout << ", ";
  91.      }
  92.      cout << endl;
  93.     }
  94.     cout << endl;
  95. }

  96. string TextQuery::cleanup_str(const string &word)
  97. {
  98.     string ret;
  99.     for (string::const_iterator it = word.begin(); it != word.end(); ++it) {
  100.         if (!ispunct(*it))
  101.             ret += tolower(*it);
  102.     }
  103.     return ret;
  104. }


阅读(1557) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~