1

我正在编写一个搜索文件的程序,每次遇到'<'字符时,它都会将它和每个后续字符复制到一个字符串中,直到达到'>'。到目前为止,这就是我所做的:

while(!file.eof()){
    char c;
    string tag;

    file.get(c);

    if(c == '<'){

        tag_num++;
        tag += c;
    }       
}

我现在如何继续file.get(c),将每个字符添加tag到 '>' 到达?

我的想法,我似乎无法开始工作,是while(file.get(c) != '>')在 if 循环中添加一个循环,该循环将由另一个循环组成,file.get(c)并且每个字符都将被复制到tag.

4

1 回答 1

1

手动快速解析文件变得很棘手。您可能想看看递归下降解析器

它是一种模式,它通过让函数以递归方式解码每个元素来实现文件的语法。

让我们用一个简化的 XML 语法(BNF 形式)举一个简单的例子:

element ::= '<'<tag>'/>'|'<'<tag>'>'<content>'<'<tag>'/>'
content ::= <element>|<freetext>|<freetext><element>
freetext ::= [^<>]<freetext>
tag ::= <alpha>|<alpha><alphanum>
alpha ::= [a-zA-Z]
alphanum ::= [a-zA-Z0-9]

(我认为正则[...]表达式的语法不是 BNF 的一部分,但对我来说它比写下所有字母更简单:-)[^<]表示任何不是 < 的字符都会与 XML 中标记的开头冲突)

该语法描述了一个元素。一个元素由一个自闭合标签(例如:)<br/>或一个开始标签,后跟一个内容,然后是一个结束标签组成。内容可以是一个元素(因此使用前一个元素递归定义)、一些自由文本或一些自由文本后跟一个元素。ETC ...

然后可以机械地实现解析:

Element parse_element(char *c)
{
    Element myElement; // Element contains the result of the parsing
                       // It's a type you have to define !
    assert( *c == '<' ); // Handle the error in a more clever way :-)
    c++;
    Tag myTag = parse_tag(c);
    if( *c == '/') 
    {
         // Self-closing tag - add myTag to myElement
         c++;
         assert( *c == '>'); // Here again, better error handling
         c++;
    }
    else
    {
         // Or a start tag
         assert( *c == '>'); // Here again, better error handling
         c++;
         Content myContent = parse_content(c);
         // Add myTag with myContent to myElement
         assert( *c == '/'); // Here again, better error handling
         c++;
         assert( *c == '>'); // Here again, better error handling
         c++;
    }
    return myElement;
}

我希望这个功能足以了解这个概念。要理解的要点是,您首先需要对要阅读的格式有一个清晰的语法定义。然后,您可以机械地实现解析器。

请注意,此示例太简单了:您至少需要处理实体、属性等...才能解析真正的 XML。

一旦你掌握了语法,一些工具,如GNU Bison ,就可以简化代码的编写。

最后,如评论中所述,如果您想解析 XML 文件,则存在一些像libxml这样的 XML 解析器。这将比实现自己的解析器更容易和更完整。XML 是一种非常复杂的格式

于 2016-02-22T13:59:45.290 回答