Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 解析:加载到内存或使用流_C_Parsing - Fatal编程技术网

C 解析:加载到内存或使用流

C 解析:加载到内存或使用流,c,parsing,C,Parsing,我正在编写一个小解析器,我想知道加载要解析的数据的不同方法的优缺点。我想到的两种方法是: 将文件内容加载到字符串中,然后解析字符串(访问数组位置的字符) 解析为读取文件流(fgetc) 前者允许我有两个功能:一个用于parse_from_file和parse_from_string,但是我相信这种模式会占用更多内存。后者不会有使用更多内存的缺点 有人对这件事有什么建议吗?考虑使用lex(如果您的语法语言与它的功能相匹配,可能还有yacc)。Lex将为您处理词法分析的所有细节,并生成高效的代码

我正在编写一个小解析器,我想知道加载要解析的数据的不同方法的优缺点。我想到的两种方法是:

  • 将文件内容加载到字符串中,然后解析字符串(访问数组位置的字符)
  • 解析为读取文件流(
    fgetc
前者允许我有两个功能:一个用于
parse_from_file
parse_from_string
,但是我相信这种模式会占用更多内存。后者不会有使用更多内存的缺点


有人对这件事有什么建议吗?

考虑使用lex(如果您的语法语言与它的功能相匹配,可能还有yacc)。Lex将为您处理词法分析的所有细节,并生成高效的代码。您可能会比它的内存占用少几个字节,但是您想在这方面花费多少精力呢?

POSIX系统上最有效的方法可能不是这两种方法(或者第一种方法的变体,如果您愿意的话):只需将文件以只读方式映射到
mmap
,然后解析它。现代系统非常高效,因为它们在检测到流式访问等时预取数据,解析同一文件的多个程序实例将获得相同的物理内存页等,并且接口相对简单,我认为。

在内存映射中读取整个文件会更快,但如果您希望您的语言能够
#包含
其他文件,则可能会导致问题,因为这些文件也会被内存映射或读入内存

stdio函数会很好地工作,因为它们通常会尝试为您缓冲数据,但它们也是通用的,因此它们也会尝试寻找不同于从头到尾读取文件的使用模式,但这不应该有太大的开销

一个很好的平衡是有一个大的循环缓冲区(x*2*4096是一个很好的大小),您可以用文件数据加载它,然后让您的标记器从中读取。每当一个块的数据被传递到您的标记器(并且您知道它不会被推回)时,您可以使用文件中的新数据重新填充该块,并更新一些缓冲区位置信息

另一个要考虑的是,如果有可能的话,记录器将需要被用来从一个管道或一个直接键入文本的人阅读。在这些情况下,如果不将数据放在文件末尾,读取返回的数据可能会比您要求的少,并且我上面提到的缓冲方法会变得更加复杂。stdio缓冲对这一点很好,因为它可以很容易地切换到行或块缓冲(或无缓冲)

使用gnu fast lex(flex,但不是AdobeFlash)或类似工具可以大大缓解所有这些问题。您应该考虑使用它为标记器生成C代码(词法分析)


无论你做什么,你都应该试着去做,这样你的代码就可以很容易地被修改,使用不同形式的下一个字符窥视和使用函数,这样如果你改变主意,你就不必重新开始了。

你是不是特别缺乏内存?@Neil不一定,我希望内存占用尽可能小。为什么?我的意思是,这是一个约束吗?如果不是,您通常更愿意将尽可能多的内容读入内存,并在内存中进行解析。@Neil,即使它不适用于OP,也可能会成为其他使用该代码的人的约束条件。可能有理由通过先将所有内容加载到内存中来实现它,但是“除非你有充分的理由不这样做,否则请将其加载到内存中”听起来像是逆向推理。@R。我们必须在这一点上有所不同。gnu flex可以选择使用stdio或读取系统调用,而不需要额外的stdio开销。