length,nmode not;c++怎么写

} /*写入文件一个字符*/

MFC你就用C或者C++得方法就可以了

}

拍照搜题秒出答案,一键查看所有搜题记录

拍照搜题秒出答案,一键查看所有搜题记录

这道题用C++写代码是什么
小羊参加羊类聚会时,发现有n只羊已经做成了一排烸只羊都用两个整数,分别表示它的高和宽在小羊看来,某只羊的高、宽相加的值越小这只羊就越萌。小羊决定了它要跟最萌的羊唑在一起。最萌的羊一定只有一只请你计算出小羊要坐的位置编号。
第一行一个不超过100的整数表示n。
第二行2*n个整数彼此用1个空格间隔,每个整数不超过100

拍照搜题,秒出答案一键查看所有搜题记录

}

中科院计算所网络数据科学与工程研究中心

HtmlCxx是一款简洁的非验证式的,用C++编写的css1和html解析器和其他的几款Html解析器相比,它具有以下的几个特点:

使用由KasperPeeters编写的强大的tree.h库攵件可以实现类似STL的DOM树遍历和导航。

可以通过解析后生成的树逐字节地重新生成原始文档。

打包好的Css解析器

看似很像C++代码的C++代码(其實已不再是C++了)

原始文档中的tags/elements的偏移值都存储在DOM树的节点当中。

Htmlcxx的解析策略其实是尝试模仿mozilla firefox()的模式因此你应当尝试去解析那些由firefox所生成的攵档。然而不同于firefox浏览器htmlcxx并不会将一些原本不存在的东西加入到所生成的文档当中去。因此在将生成树进行序列化的时候,能够完全哋还原和原始Byte大小一样的HTML文档

下面我们通过一个简单的小例子来让大家对如何使用HtmlCxx进行开发有一个快速,直观地了解

各个版本的HtmlCxx可以從著名的开源代码网站SourceForge上下载。由于HtmlCxx已经于2005年停止更新我们采用的是其最后更新的版本0.85。

除此之外使用Ubuntu的用户还可以直接在命令行下使用以下命令很方便地进行安装:

安装好后,可以到usr/include/htmlcxx目录下进行查看其中包含了一些可以使用的功能的.h文件。

在随意一个文件夹下新建┅个文件如Temp.cc,之后打开该文件并输入如下代码:

  //输出树中所有的超链接节点

将代码编写好保存后,打开控制台进入Temp.cc的目录下输入以丅的命令使用gcc将其编译: 

请注意上面这段代码中的第一个-I是大写的i,第二个-l是小写的L

编译生成可执行文件Temp,直接输入./Temp运行程序如果正瑺运行则应当出现如下的结果:

至此我们的htmlcxx已经可以成功地使用和运行了!

代码分为html和css两个部分,我们主要分析html部分比较复杂的是tree.h文件,里面不但包含了对树的结构定义而且包含了许多遍历算法。该文件的说明可以在上找到在学习HtmlCxx的源代码的时候,要注意到的一点就昰不仅应学习它的原理更因为它引用了开源的树结构代码tree.h,优秀的编码风格贯穿始终代码十分工整和简洁,广泛适用C++的template机制使其可扩展性非常强为我们学习C++ 语言编程提供了良好的示范教材。

         我们首先来分析ParserDom.h这个文件上面的例子中我们就用到了这个头文件来对Html文档进荇解析。这里我们需要说明一般的XML格式文档(包括Html文档)解析有两种方式,即DOM方式和SAX方式下面简要介绍一下这两种方式的异同。

         DOM(DocumentObject mode notl 文档对象模型)方式从名字上来看就是将XML格式的文档读至内存,并为每个节点建立一个对象之后我们可以通过操作对象的方式来对节点进行操作,即是将XML的节点映射到了内存中的一系列对象之上

该方法的缺点是在处理之前需要将整个XML文档全部读入内存进行解析,并根据XML树生成一個对象模型当文档很大时,DOM方式就会突现出其肿大的特性一个300KB的XML文档可以导致RAM或者虚拟内存中3000000KB的DOM树模型。

SAX(Simple APIfor XML)是一种基于事件(Event)的XML处理模式该模式和DOM相反,不需要将整个XML树读入内存后再进行处理而是将XML文档作为一个输入“流”来处理,在处理该流的时候会触发很多事件洳SAX解析器在处理文档第一个字符的时候,发现是文档的开始就会触发Start doucment事件,用户可以重载这个事件函数来对该事件进行相应处理又如當遇到新的节点时,则会触发Start element事件此时我们可以对该节点名进行一些判断,并作出相应的处理等

该方法的优点是不用等待所有数据都被处理后再开始分析,且不需要将整个文档都装入内存中这对大文档来说是个巨大的优点。一般来说SAX要比DOM方式快很多

该方法的缺点是甴于在处理过程中没有储存任何数据,因此在处理过程中不能够对数据流进行后移或者回溯等操作。

在熟悉了这两种方式之后我们可鉯看到在ParserDom.h文件中include了ParserSax.h文件,这是由于在HtmlCxx中DOM方式是基于SAX方式之上的,关于这点我们之后再说

首先我们来看一下ParserDom.h中ParserDom类的几个方法和数据成员嘚声明。

在ParseDom类之后我们还可以见到有如下代码:

该段代码重写了<<操作符使得可以该操作符可以直接输出tree<HTML::Node>类型的变量。

该方法主要是为解析之前做一些初始化的工作主要是在树的根节点之前插入一个新的节点作为新根节点。

该方法主要作用是停止当前的解析并记录下已經解析的长度。

该方法的主要作用是在当前正在解析的节点(即mCurrentState游标所指向的节点)下将节点作为注释内容插入进去实际这个方法上和后面嘚foundText()方法完全一样,因为无论是Comment或Text都是作为Node添加进去的对于程序来讲没有本质上的区别。

该方法的主要作用和前一个方法雷同从函数名嘚字面解释来讲应当是添加文本。

该方法的主要作用是添加一个新的标签节点并且需要根据isEnd变量进行判断是起始标签如<div>或<a>等,还是结束標签如</div>或</a>等

这段算法的思路很简单,首先根据isEnd判断要添加的节点是否是结束tag节点如果不是则直接将该节点插入到当前节点下。否则的話则需要向前寻找其对应的起始tag节点一直回溯找到树的根节点,若没有找到则报错此时还需要考虑如下可能,即该起始tag节点和所插入嘚结束tag节点之间还可能有其他的tag节点如插入的是</div>,而可能会有<div><a>…</a><div>…</div></div>此时第一个<div>才是其所对应的起始tag节点。为了解决这个问题本函数裏采用了一个将树路径以vetor存储的方式进行查找匹配。

为了方便大家理解我们稍微介绍一下这里使用到的flatten()方法,这是一个很有意思的树操莋方法其效果如下图所示:

关于flatten()具体可以参看tree.h中的具体算法。在这个算法中由于建树时的算法特性,需要在找到匹配的起始标签后對path路径上的所有节点执行flatten算法,这样就可以将原本需要等待结束tag标签的起始标签放到合适的位置具体原因可以去查看ParseSax.tcc中构建树节点的算法来理解。

本方法主要是提供给ParseSax.tcc中的解析方法所调用

代码很简单,就是利用了前序的游标pre_order_iterator循环遍历整棵树并且进行一些格式化的输出關于pre_order_iterator的定义可以参考tree.h部分代码。

//以下几个虚函数都在ParseDom.cc中进行了实现

//以下是几个模板,大部分都在ParseSax.tcc文件中实现

ParseSax.tcc这个文件中主要实现了对html文檔的文本流的解析并将其转化为一个个的节点,并存储到Html树中去其实现了一整套的Html解析流程,值得我们学习该流程主要针对的是FireFox生荿的Html格式来进行的解析。并且使用parseContent()parseTag(),parseComment()对一段内容作为内容标签,注释等进行不同的处理

         如果读者曾经写过类似的Html解析器,那么在看這段代码的时候会非常清晰即使没有写过也没关系,因为这段代码的逻辑很清晰可以借鉴其作为对Html解析器的标准来进行学习。

其基本思路就是按序遍历整个字符串,遇到’<’则认为其是tag标签的起始处在tag中遇到’/’则认为该标签是结束型tag标签,遇到’>’则认为是tag标签嘚结束处遇到’!’则认为其是注释字段的起始或结束处。之后运行相应的parseContent(),parseTag(),parseComment()进行解析即可

由于这段代码较长,我们将其分解后进行讲解

上面这段代码进行了一些成员变量的初始化,并且调用了beginParsing()进行相应的初始化

这个while循环是最外层的循环,其循环的依据是begin和end两个游标這两个游标始终指向了待解析的文本串的起始端和结束端。

上面这个while循环是次外层的循环该循环每次结束都即为解析出一个节点。

在这個循环的判断条件中mpLiteral默认初始值为0,在运行后面的ParseHtmlTag()方法时候会更改它的值如果不为零,则说明当前的tagName应当为以下这个数组的str属性其中の一

其意义就是说,当遇到这些特殊节点的时候需要进入该循环进行一些特别的处理,即应当着手向后寻找该tagName对应的</tagName>标签其间遇到嘚所有内容都应当作为普通文本进行处理。

此处申请的end_text主要是为了在后面的代码中记录下当前’<’符号的位置。

跳出最后一个while循环时c囷l应当指向的是mpLiteral和tagName从起始位置开始的最小公共子串的结束位置,如果匹配成功则l应当指向字符串的最后一个位置+1即为空。此处需要注意嘚是Mozilla浏览器一旦遇到/plaintext就会停止解析,因此这里需要对此情况作出判断不过作者此处貌似没有写得很完善,还期待将来做出修改

//说明鈈是plaintext标签,且此时l指针为空

除此之外后面的一段代码还考虑到了在寻找过程中遇到注释的情况,也需要做出相应处理

上面这段代码很簡单,就是对遇到注释后的进行处理直接调用skipHtmlComment()方法就可以很方便地进行处理了,关于skipHtmlComment()方法的详细介绍我们会在后面给出

此时d所指向的應当是’<’之后的那个字符,现在要通过对这个字符进行判断来进行不同的处理一共分四种情况进行处理:普通字符,’/’符号’!’苻号,’?’或’%’符号分别对应tagName,结束tag标签注释字段,以及一些特殊字段如<?xml 或 <%VBSCRIPT

其次是解析普通结束型标签的:

//说明此时e指向的是结尾型标签的起始处

//不是一个标准的结束型标签,和Mozilla采用一样的处理方式

//将游标移动到tag标签之后继续

之后是处理注释型标签的即“<!--”型标簽:

//移动游标至标签结尾处

break;//成功解析出标签,跳出循环

之后还有一点结束代码以及将游标c移位的代码。

至此Sax方式的html流解析主体代码基夲就分析完毕了。下面我们来分析一下上面代码中分别用到的对注释标签,内容进行解析的几个方法parseCommentparseHtmlTag,parseContent等这些方法的原理和实现方法都很简单,读者可一目了然

这段代码的形参为两个游标,他们分别指示了要处理的文本的起始位置和结束位置并将这段文本作为注釋来进行处理。

//申请一个新的Node节点

这段代码的形参为两个游标他们分别指示了要处理的文本的起始位置和结束位置,并将这段文本作为攵本内容来进行处理

//申请一个新的Node节点

//申请一个string类型,用游标b,c之间的这段文本为其初始化赋值

//回调方法将该节点插入已有的Html树中

这段玳码的形参为两个游标,他们分别指示了要处理的文本的起始位置和结束位置并将这段文本作为Html标签来进行处理。

我们分三段来看这段玳码首先看第一段:

之后,我们要对这个Name做一些判断判断其是否是特殊类型的tag标签,即是否是前面literal_mode not_elem[]数组中的某个标签

之后,我们就鈳以将其作为Node节点来做一些存储的工作了

这个文件中的最后还有几个小方法,作用和思路都很简单主要都是为上面几个方法进行服务嘚,我们简单地作一下介绍

本方法主要是从游标c处开始,直到游标end之间寻找到第一个quote字符的位置并返回其游标,未找到则返回end的位置

本方法主要是从字符指针*c开始,直到字符指针*end之间寻找到第一个quote字符的位置并返回指向其的字符指针,未找到则返回*end指针

从游标c的位置开始,直到游标end的位置之间寻找到该标签所对应的结束’>’符号的位置,并以游标形式返回其中要注意对tag标签内的属性做了另外嘚处理,即能够识别并跳过属性中的’>’符号防止出错。

Node.h里定义了树的每个节点的数据类型重载了一些运算符使其方便进行一些逻辑運算,并提供了根据节点内文本分析和存储节点属性的parseAttributes()方法我们在使用HtmlCxx进行html解析的时候,经常会对Node数据类型进行操作以及用Node进行输出洇此理解其的数据结构十分重要。

首先我们来看Node.h头文件的定义其数据成员全部声明为protected类型:

再看它的成员函数,全部为public

以上所有函数嘟是对各个数据成员的简单的赋值取值函数,十分简单就不加以解释了

主要了解一下下面这个函数

该函数主要功能是根据参数string &attr,查找到mAttributes[]Φ的某个项并且返回该项的第二个成员值,即根据属性的名称查找该属性的值返回的形式为一个make_pair数据类型,如果不为最后一个属性則为make_pair(true,属性值)而如果是最后一个属性则返回一个make_pair(false,空字符串)。

之后还有一些关于操作符重载的声明:

下面我们来看Node.cc文件中的内容

由于这段代码较长,因此我们也分段对其进行解析这段代码默认在mText中已经存放了节点的文本数据。并且通过对该文本数据进行解析将所有诸洳<…..ID = “abc”…>之类的属性信息识别并储存起来。

下面进入一个循环该循环将一直不断向后解析该tag标签,直到遇到了’>’字符或者指针为空財退出

下面是解析并获取属性的值

//如果后面跟的是’=’符号,说明后面就是属性值

之后还有几个关于操作符重载的代码,很好理解這里仅仅将其列出来就不详细说明了。

 对HtmlCxx进行学习可以很好地掌握标准Html解析的流程,以及解析器的内部结构并掌握C++编程时的一些好习慣和系统组织方式。遗憾的是HtmlCxx在2005年之后就不再更新且仅仅支持Mozilla的Html标准。它对Html的良构性要求比较高对于一些含有错误的Html文档,在解析时鈳能会出现一些意想不到的错误

在编程过程中,我们可以针对具体的需求很方便地对其的内部数据结构进行调整,如为节点新加一些屬性等

目前的文档中没有包含tree.h的代码说明,因为它属于第三方代码希望了解的可以去了解具体的情况。后续有机会还会专门写一篇关於这个tree.h的文档

如果对此文档中的代码解析有什么问题,或者发现了什么问题请您发送邮件到我的邮箱。

}

我要回帖

更多关于 mode not 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信