c++ primer 4 中10.6节算法改正

来源:互联网 发布:种植牙的利与弊 知乎 编辑:程序博客网 时间:2024/05/22 02:30

最近又在看c++了。

说又,是因为自己很早就开始看c++了,但是都没有认真学,看看断断,这次终于算是想好好看一下了。

其实,这也是我研二生活的写照。到了所里,分配了研究方向,是有关云计算OpenStack的,没接触过,并且出了我们这届的2个新生,只有一个师兄在做这方面的东西。师兄也在忙着找工作,我就只能自己一个人摸索。说是摸索,其实大部分时间就是在上网浪费了,没啥个进展。我自认为不是很适合搞研究,究其根本,是自控力太差,看一点就烦,烦了就不想看。

可是,一天天过去了,妹子也已经找到工作了,自己离找工作的日子一天天临近了,可是自己还什么也不会,有时候会感觉到压力!大学本科已经这么荒废了,从算是一流的大学,去了二流的研究所,再不努力,就只能找三流工作了!

不废话了,开始正题了。

c++ primer 4 中第10张讲了关联容器map,set,multimap,multiset,书中对multiset没怎么将,只是提一下,但是有时候,multiset还比较有用。书中提到multiset一个键可以对应多个实例,而set容器又只是单纯键的集合,这似乎有些矛盾。我的理解是,multiset就是一个键可以重复出现计算的集合。关于multimap和multiset,有几个非常有用的操作:

  1. m.lower_bound(k),返回一个迭代器,指向键不小于k的第一个元素
  2. m.upper_bound(k),返回一个迭代器,指向键大于k的第一个元素
  3. m.equal_range(k),返回一个迭代器的pair对象,它的first成员等价于m.lower_bound(k),second成员则是等价于m.upper_bound(k)

这三个操作在查找的时候非常管用,下面例子中再叙述。

再说书中10.6节的那个算法。要求实现一个文本查询程序,程序读取用户的任意文本文件,然后允许用户从该文件中查找单词,查询结果是该单词出现次数,并列出每次出现所在的行。如果某单词在同一行中刚出现多次,程序将只显示该行一次。

书中的算法简而言之就是首先分析每个单词出现的行,再查找单词,从而就知道该单词所在行了,然后输出出现个数以及行内容。书中用map<单词,行set容器>保存每个单词的信息。这里就发现了点问题!使用set容器保存行号,由于set容器中键不能重复出现,这就会出现这样的问题:如果一行中重复出现两个或更多查找的单词,而此算法只能计第一个单词,此行后面的单词就无法记录!实际测试也是这样的问题。这是set容器的限制,这里就需要使用multiset!用multiset保存行号,同一行中多次出现的单词会不遗漏的被记录。下面就需要改写输出函数print,要求如果某单词在同一行多次出现,程序将只显示该行一次。这里就用到了lower_bound操作:

for(multiset<vector<string>::size_type>::iterator iter = locs.begin();iter != locs.end();iter++){if(iter != locs.lower_bound(*iter)){continue;}else{cout<<"(line "<<*iter + 1<<") "<<file.text_line(*iter)<<endl;}}
改过之后,测试没问题,基本满足要求。

这里还有一个问题。

如果使用书上的clearup_str行数来去除开头的标点,以及把开头的大写变成小写,就会出现Debug Assertion Failed报错,

自己也是刚接触c++,也不是很明白这是什么原因,求高手指点!

原创粉丝点击