我希望使用C解析iCalendar文件。我有一个现有的结构设置和读取所有就绪,并希望逐行解析组件。
例如,我需要解析如下内容:
UID:uid1@example.com
DTSTAMP:19970714T170000Z
ORGANIZER;CN=John Doe;SENT-BY="mailto:smith@example.com":mailto:john.doe@example.com
CATEGORIES:Project Report, XYZ, Weekly Meeting
DTSTART:19970714T170000Z
DTEND:19970715T035959Z
SUMMARY:Bastille Day Party
以下是一些规则:
CATEGORIES
例如,数组中有3个元素用于值ORGANIZER
行上可以有多个可选参数。只有另一个分号后跟下一个参数和值。 我正在使用strchr()
和strtok()
进行此操作,并从中获得了一些基本元素,但它变得非常混乱和无组织,并且似乎不是正确的方法。
如何使用标准C库(或POSIX正则表达式库)实现这样一个复杂的解析器? (不是寻找整个解决方案,只是出发点)
答案 0 :(得分:1)
这个答案假设您想使用标准C来推广自己的解析器。在实践中,通常最好使用现有的解析器,因为他们已经考虑并处理了可能出现的所有奇怪的事情。
我的高级方法是:
parse_line
:
strcspn
标识第一个:
或;
的位置(如果未找到标记,则中止);
时:
extract_name_value_pair
传递解析指针的地址。;
或:
。当然,此函数必须处理值中的引号,以及值可能为;
或:
的事实:
)parse_csv
,该函数将查找以逗号分隔的值(再次,知道引号)并将找到的结果存储在正确的位置。 事实上,应首先开发和测试函数parse_csv
和extract_name_value_pair
。制作测试套件并检查它们是否正常工作。然后编写整体解析器函数,根据需要调用这些函数。
此外,将所有内存分配代码写为单独的函数。想一想您要将解析结果存储在哪种数据结构中。然后编写该数据结构并对其进行测试,完全独立于解析代码。只有这样,编写解析代码并调用函数才能将结果数据插入数据结构中。
你确实不希望内存管理代码与解析代码混淆。这使得它在指数上难以调试。
当创建一个接受字符串的函数(例如上面所有三个命名函数,以及你决定需要的任何其他帮助函数)时,你有一些关于它们的接口的选项:
每种方式都有它的优点和缺点:在任何地方写入null终结符然后在需要时再写入它是很烦人的;但是当你想使用strcspn
或其他字符串函数但你收到一个长度计算的字符串时,它也很烦人。
此外,当函数需要让调用者知道解析时消耗了多少文本时,您有两个选择:
没有一个正确的答案,根据经验,您可以更好地决定哪个选项可以获得最干净的代码。