1、使用tinyXml2解析RSS文件,并生成一个网页库pagelib.dat。

tinyXml2 -- https://github.com/leethomason/tinyxml2
rss      -- https://coolshell.cn/feed
         -- http://www.runoob.com/rss/rss-tutorial.html

正则表达式 进行过滤

参考接口:

struct RssItem
{string title;string link;string description;string content;
};class RssReader
{
public:RssReader();void parseRss();//解析void dump(const string & filename);//输出
private:vector<RssItem> _rss;};   

要求:最后生成一个 pagelib.txt, 其格式:

<doc>
    <docid>1</docid>
    <title>...</title>
    <link>...</link>
    <description>...</description>
    <content>...</content>
</doc>
<doc>
    <docid>2</docid>
    <title>...</title>
    <link>...</link>
    <description>...</description>
    <content>...</content>
</doc>
<doc>
  ...
</doc>

RSS文件解析作业思路:xml -->rss-->tinyxml2(使用该库对rss文件进行解析)--> boost::regex/std::regex(使用正则表达式去除html标签)

提示:首先去读coolshell.xml文件,因为是一个rss文件,而我们需要找到rss的channel节点下面的item节点的title节点、link节点中间的文本,至于这些文本可以使用tinyxml2这个第三方库进行解析,所以这里需要看看timyxml2如何解析第三方库(可以看看timyxml2的源码),解析完成一个item后,可以将其存到vector中(也可以将这些原始信息经过后面正则表达式去除标签后再存起来),然后再去读第二个item(其实就是一个循环操作),其实第二个item是第一个item的兄弟节点(可以使用tinyxml2里面的函数进行跳转到第二个item),这样就可以解析coolshell.xml文档了。接着,因为description信息中包含html的标签,所以需要去除这样的html标签,如<p></p>,这个可以使用正则表达式,也就是std::regex进行去除,这个可以在cppreference.html中进行查找使用方法。

最后就是遍历vector,讲读取到的信息存到另外一个文件,格式需要自己定义,使用我们自定义的<doc> </doc>格式

date_11/13作业总结:

wd老师已把作业实现思路讲的很清楚了,陌生的只是对RSS/HTML不了解,对第三方库tinyxml2的使用不了解,对正则表达式不了解。一开始觉得难,但是去了解了RSS/tinyxml2/正则表达式知识后,才发现,咦,原来不难啊,找到了处理html标签的正则表达式之后,作业基本完成-end.

1.了解RSS语言基本组成:RSS 教程 | 菜鸟教程

2.简单学习tinyxml2库,用于读取xml文件,用XMLElement类里面定义的函数可以获取RSS结点指针,tinyxml2库的安装和学习:参考:https://www.codenong.com/cs106726476/

1.复习:
    git clone https://github.com/leethomason/tinyxml2.git
    cd tinyxml2/
     make 
     ./xmltest
     sudo make install
2.把tinyxml2.cpp从github下载,放到自己的项目文件夹

3.简单学习XMLDocument类:
    1.XMLDocument xml;
     xml.LoadFile("coolshell.xml");//1.从当前文件夹读取xml文件

2.XMLElement *category = xml.RootElement();//2.拿到根结点rss

3.XMLElement *channel = category->FirstChildElement("channel");//根节点的第一个孩子就是channel

4.XMLElement *title = channel->FirstChildElement("title");//拿到channel的孩子结点title
   5.XMLElement *item = channel->FirstChildElement("item");//channel结点有很多个item子结点
    //作业的要求就是拿到item结点下的title,link,description,content,存入到结构体中,再用vector保存
    item = item->NextSiblingElement();//找下一个兄弟结点item

3.正则表达式处理网页html标签,C++Primer第五版简单了解了下语法,网上找去除html标签的正则表达式,拿来用即可。

1.正则表达式:regex reg("<[^>]*>");
2.regex_replace(str,reg,"")的使用。

代码实现:

01_RssHeader.h

#include <iostream>
#include <regex>
#include <fstream>
#include "tinyxml2.h"
#include <vector>
using namespace std;
using namespace tinyxml2;
#include <string>struct RssItem
{string title;string link;string description;string content;
};
class RssReader
{
public:RssReader(){};void parseRss(const char *filename);//1.读取xml文件,解析相应内容,把每个结构体存入vectorvoid read(); //2.把解析的内容输出到控制台void dump(const string & filename);//3.输出到文件private:vector<RssItem> _rss;};

02_Rss_main.cc

#include "01_RssHeader.h"int main()
{RssReader s1;s1.parseRss("coolshell.xml");s1.dump("pagelib.dat");return 0;
}

03_parseData.cc

#include "01_RssHeader.h"//获取Rss文件中channel结点下item结点的有用内容:title/link/descirption/content,保存到结构体vector
void RssReader::parseRss(const char *filename)//解析
{XMLDocument xml; //1.声明xml类,用来读取xml文件xml.LoadFile("coolshell.xml");//2.读取xml文件XMLElement *category = xml.RootElement();//3.拿到xml文件的根节点RssXMLElement *channel = category->FirstChildElement("channel");//4.拿到channel结点指针XMLElement *title = channel->FirstChildElement("title");XMLElement *item = channel->FirstChildElement("item");//5.拿到item结点while(item)//6.设置循环,遍历channel下的每个item结点{RssItem rss_item;//7.把数据保存到结构体regex reg("<[^>]*>"); //8.正则表达式去除网页html标签//9.获取title结点指针,把内容保存到结构体相应的变量XMLElement *item_title = item->FirstChildElement("title");//title结点rss_item.title = item_title->GetText(); //保存结点的内容//10.获取link结点指针,把内容保存到结构体相应的变量XMLElement *item_link = item->FirstChildElement("link");rss_item.link= item_link->GetText();//cout<<Rss.link<<endl;//11.获取desc结点指针,数据用正则去除html标签后,把内容保存到结构体相应的变量XMLElement *item_description = item->FirstChildElement("description");rss_item.description= item_description->GetText();rss_item.description = regex_replace(rss_item.description,reg,"");//去除html标签//11.获取content结点指针,数据用正则去除html标签后,把内容保存到结构体相应的变量XMLElement *item_content = item->FirstChildElement("content:encoded");rss_item.content= item_content->GetText();rss_item.content = regex_replace(rss_item.content,reg,"");//去除网页标签//12.把每个结构体保存进 vector,每个结构体都是一篇文章了_rss.push_back(rss_item);item = item->NextSiblingElement();//找下一个item结点}}void RssReader::read()//内容输出到控制台
{for(int i=0;i<_rss.size();i++){cout<<_rss[i].title<<endl;cout<<_rss[i].link<<endl;cout<<_rss[i].description<<endl;cout<<_rss[i].content<<endl;}
}//把内容按指定格式输出到指定文件
void RssReader::dump(const string & filename)
{ofstream ofs(filename);if(!ofs.good()){cerr<<"ofstream is not good!"<<endl;return;}for(int i=0;i<_rss.size();i++){ofs<<"<doc>"<<"\n"<<"\t"<<"<docid>"<<i+1<<"</docid>"<<"\n"<<"\t"<<"<title>"<<_rss[i].title<<"</title>"<<"\n"<<"\t"<<"<link>"<<_rss[i].link<<"</link>"<<"\n"<<"\t"<<"<description>"<<_rss[i].description<<"</description>"<<"\n"<<"\t"<<"<content>"<<_rss[i].content<<"</content>"<<endl;}ofs.close();
}

Ubuntu下对代码进行编译:

g++ tinyxml2.cpp 01_RssHeader.h 02_Rss_main.cc 03_parseData.cc -o demo1 -std=c++11

部分输出结果:RSS文件来自Coolshell:Go编程模式 : 泛型编程 | 酷 壳 - CoolShell

<doc><docid>1</docid><title>Go编程模式 : 泛型编程</title><link>https://coolshell.cn/articles/21615.html</link><description>Go语言的1.17版本发布了,其中开始正式支持泛型了。虽然还有一些限制(比如,不能把泛型函数export),但是,可以体验了。我的这个《Go编程模式》的系列终于...Read More  Read More
The post Go编程模式 : 泛型编程 first appeared on 酷 壳 - CoolShell.</description><content>Go语言的1.17版本发布了,其中开始正式支持泛型了。虽然还有一些限制(比如,不能把泛型函数export),但是,可以体验了。我的这个《Go编程模式》的系列终于有了真正的泛型编程了,再也不需要使用反射或是go generation这些难用的技术了。周末的时候,我把Go 1.17下载下来,然后,体验了一下泛型编程,还是很不错的。下面,就让我们来看一下Go的泛型编程。(注:不过,如果你对泛型编程的重要性还不是很了解的话,你可以先看一下之前的这篇文章《Go编程模式:Go Generation》,然后再读一下《Go编程模式:MapReduce》)
本文是全系列中第10 / 10篇:Go编程模式Go编程模式:切片,接口,时间和性能Go 编程模式:错误处理Go 编程模式:Functional OptionsGo编程模式:委托和反转控制Go编程模式:Map-ReduceGo 编程模式:Go GenerationGo编程模式:修饰器Go编程模式:PipelineGo 编程模式:k8s Visitor 模式Go编程模式 : 泛型编程&laquo; 上一篇文章
初探
我们先来看一个简单的示例:package mainimport "fmt"func print[T any] (arr []T) {for _, v := range arr {fmt.Print(v)fmt.Print(" ")}fmt.Println("")
}func main() {strs := []string{"Hello", "World",  "Generics"}decs := []float64{3.14, 1.14, 1.618, 2.718 }nums := []int{2,4,6,8}print(strs)print(decs)print(nums)
}
上面这个例子中,有一个 print() 函数,这个函数就是想输出数组的值,如果没有泛型的话,这个函数需要写出 int 版,float版,string 版,以及我们的自定义类型(struct)的版本。现在好了,有了泛型的支持后,我们可以使用 [T any] 这样的方式来声明一个泛型类型(有点像C++的 typename T),然后面都使用 T 来声明变量就好。
上面这个示例中,我们泛型的 print() 支持了三种类型的适配—— int型,float64型,和 string型。要让这段程序跑起来需要在编译行上加上 -gcflags=-G=3编译参数(这个编译参数会在1.18版上成为默认参数),如下所示:
$ go run -gcflags=-G=3 ./main.go
有了个操作以后,我们就可以写一些标准的算法了,比如,一个查找的算法
func find[T comparable] (arr []T, elem T) int {for i, v := range arr {if  v == elem {return i}}return -1
}
我们注意到,我们没有使用 [T any]的形式,而是使用 [T comparable]的形式,comparable是一个接口类型,其约束了我们的类型需要支持 == 的操作, 不然就会有类型不对的编译错误。上面的这个 find() 函数同样可以使用于 int, float64或是string类型。
从上面的这两个小程序来看,Go语言的泛型已基本可用了,只不过,还有三个问题:一个是 fmt.Printf()中的泛型类型是 %v 还不够好,不能像c++ iostream重载 &gt;&gt; 来获得程序自定义的输出。
另外一个是,go不支持操作符重载,所以,你也很难在泛型算法中使用“泛型操作符”如:== 等
最后一个是,上面的 find() 算法依赖于“数组”,对于hash-table、tree、graph、link等数据结构还要重写。也就是说,没有一个像C++ STL那样的一个泛型迭代器(这其中的一部分工作当然也需要通过重载操作符(如:++ 来实现)不过,这个已经很好了,让我们来看一下,可以干哪些事了。
数据结构
Stack 栈
编程支持泛型最大的优势就是可以实现类型无关的数据结构了。下面,我们用Slices这个结构体来实现一个Stack的数结构。
首先,我们可以定义一个泛型的Stack
type stack [T any] []T
看上去很简单,还是 [T any] ,然后 []T 就是一个数组,接下来就是实现这个数据结构的各种方法了。下面的代码实现了 push() ,pop(),top(),len(),print()这几个方法,这几个方法和 C++的STL中的 Stack很类似。(注:目前Go的泛型函数不支持 export,所以只能使用第一个字符是小写的函数名)
func (s *stack[T]) push(elem T) {*s = append(*s, elem)
}func (s *stack[T]) pop() {if len(*s) &gt; 0 {*s = (*s)[:len(*s)-1]}
}
......

C++学习之第八天-解析RSS文件相关推荐

  1. tinyxml2解析rss文件

    参考资料:xml -> rss -> tinyxml -> regex xml:XML 教程 rss:RSS 教程 tinyxml2:TinyXML-2: TinyXML-2 reg ...

  2. 状态机学习(二)解析INI文件

    题目来自<系统程序员成长计划> 作者:李先静. 状态变化如下 #include <string> #include <iostream> using namespa ...

  3. Android实例RSS客户端开发(2)--解析XML文件

    一 介绍完RSS之后,下面开始讲解如何解析RSS文件.因为RSS是基于XML的,所以我们就直接介绍如何解析XML文件. 解析XML的方式有很多种,大家比较熟悉的可能就是DOM解析. DOM(文件对象模 ...

  4. Java 实现解析xml文件的基本步骤(做笔记)

    今天,初步学习了Java实现解析xml文件的基本步骤.不多说先上图解了. 源代码: public class Dome1 { public static void main(String[] args ...

  5. 【unity3d--初始学习五--c#脚本对xml文件的创建和解析】

    本人用c#编写脚本. 创建xml文件时,主要用到System.Xml包中的XmlDocument,XmlNode,XmlElement.下面是创建xml文档的一般步骤: XmlDocument doc ...

  6. DSP学习(8)—— linker.cmd文件解析

    DSP学习(8)-- linker.cmd文件解析 文章目录 DSP学习(8)-- linker.cmd文件解析 前言 前言 写工程的时候遇到报内存不够的错误,出现在linker.cmd的内存分配se ...

  7. Android学习笔记---Android平台1.使用dom解析xml文件

    1.使用dom解析xml文件 除了使用 SAX可以解析XML文件,大家也可以使用熟悉的DOM来解析XML文件. DOM解析XML文 件时,会将XML文件的所有内容以文档树方式存放在内存中,然后允许您使 ...

  8. 编程模板-R语言脚本写作:最简单的统计与绘图,包安装、命令行参数解析、文件读取、表格和矢量图输出

    写在前面 个人认为:是否能熟悉使用Shell(项目流程搭建)+R(数据统计与可视化)+Perl/Python等(胶水语言,数据格式转换,软件间衔接)三门语言是一位合格生物信息工程师的标准. 之前分享过 ...

  9. JavaXml教程(六)使用JDOM解析XML文件

    JDOM 提供了非常优秀的Java XML API来更方便的读取.修改.生成XML文档.JDOM还提供了包装类供用户从SAX.DOM.STAX事件解析.STAX流解析中选择具体的实现. 在本教程中,我 ...

最新文章

  1. JAVA增删改查XML文件
  2. 化学博士6次投毒同事,只因对方给自己安排工作太多....
  3. springMVC转发与重定向
  4. Non-Blind图像反卷积论文整理
  5. SpringBoot 扫描包
  6. 年终总结-致敬2014
  7. oracle倒导数的条件过滤参数,oracle exp导出加上过滤条件
  8. 我坚决不能容忍_出轨坚决不能忍,3星座女对出轨0容忍,敢出轨就等着吧
  9. POJ 2182 Lost Cows
  10. 有没有可能在安卓上,使用swing/awt开发?
  11. 4k显卡视频测试软件,4K分辨率下体验测试
  12. pytorch-psenet实现 并训练自己的数据集
  13. U盘无法在磁盘管理器中删除,显示不支持该操作的时候可以用以下的办法,亲测可以解决
  14. 2022.8.29-9.4 AI行业周刊(第113期):世界人工智能大会
  15. 黑产系列02-黑产画像
  16. 网络安全初创企业Illumio融资1.25亿美元 摩根领投
  17. Leetcode_154_Find Minimum in Rotated Sorted Array
  18. ubuntu19.04 设置中文环境
  19. “3点钟无眠区块链”的前世今生
  20. Unix整理笔记——Unix基础——里程碑

热门文章

  1. java相关的外文文献及翻译_外文文献及翻译:JavaandtheInternet
  2. Nginx面试题(史上最全 + 持续更新)
  3. Python之数据挖掘实践--scikit learn库介绍和下载、实践、采坑
  4. 微信群控服务器一体机,群控和微信群控,你了解多少?
  5. 复制文件到远程桌面显示未知错误
  6. C++简单输入输出-计算火车运行时间
  7. 基于cocos2d-x简易泡泡龙游戏
  8. 小红的签到题 (shui
  9. 末日启示:向死而生--《罗辑思维》第一季第一期
  10. java中的线程及常用方法