【问题标题】:C parse comments from textfileC从文本文件中解析注释
【发布时间】:2018-03-04 03:47:15
【问题描述】:

所以我正在尝试实现一个非常简单的解析器来读取文件并执行一些命令。我想与 bash 脚本非常相似,但要简单得多。鉴于您可以使用# 表示的 cmets,我无法弄清楚如何标记文件的内容。举例说明源文件的外观

# Script to move my files across
# Author: Person Name 

# First delete files
 "rm -rf ~/code/bin/debug";
 "rm -rf ~/.bin/tmp"; #deleting temp to prevent data corruption
# Dump file contents
 "cat ~/code/rel.php > log.txt";

到目前为止,这是我的代码。请注意,我本质上是在使用这个小项目作为对 C 更加熟悉和熟悉的一种方式。所以请原谅代码中的任何明显缺陷。将不胜感激的反馈。

// New line.
#define NL '\n'
// Quotes.
#define QT '"'
// Ignore comment.
#define IGN '#'

int main() {
  if (argc != 2) {
    show_help();
    return 0;
  }
  FILE *fptr = fopen(argv[1], "r");
  char *buff;
  size_t n = 0;
  int readlock = 0;
  int qread = 0;
  char c;

  if (fptr == NULL){
     printf("Error: invalid file provided %s for reading", argv[1]);
     exit(1);
  }

 fseek(fptr, 0, SEEK_END);
 long f_size = ftell(fptr);
 fseek(fptr, 0, SEEK_SET);
 buff = calloc(1, f_size);

 // Read file contents.
 // Stripping naked whitespace and comments.
 // qread is when in quotation mode. Everything is stored even '#' until EOL or EOF.
 while ((c = fgetc(fptr)) != EOF) {
    switch(c) {
        case IGN :
            if (qread == 0) {
                readlock = 1;
            }
            else {
                buff[n++] = c;
            }
            break;
        case NL :
            readlock = 0;
            qread = 0;
            break;
        case QT :
            if ((readlock == 0 && qread == 0) || (readlock == 0 && qread == 1)) {
                // Activate quote mode.
                qread = 1;
                buff[n++] = c;
            }
            else {
                qread = 0;
            }
            break;
        default :
            if ((qread == 1 && readlock == 0) || (readlock == 0  && !isspace(c))) {
                buff[n++] = c;
            }
            break;
    }
 }
fclose(fptr);
printf("Buffer contains %s \n", buff);
free(buff);

return 0;

}

所以上述解决方案有效,但我的问题是......有没有更好的方法来实现预期的结果?目前我实际上并没有“标记”任何东西。当前的实现是否缺少能够根据字符创建标记的逻辑?

【问题讨论】:

  • 您在代码中的注释中说“所有内容都已存储”,但您也忽略了 cmets。 “一切”是否意味着“除了 cmets 之外的一切”?不清楚您是否诊断错误,例如以双引号开头且不以双引号结尾的 s 行。那会发生什么?
  • @JonathanLeffler 我已经更新了评论。但是我也想存储引号之间的 cmets 以供以后分析。因此,为什么我使用该变量。 EOL 和 EOF 将处理未封闭的报价。希望这让我的问题更清楚

标签: c parsing lexer


【解决方案1】:

整行阅读文件更容易:

char line[1024];

while(!feof(fptr)) 
{
  if(!fgets (line , 1024 , fptr))
    continue;

  if(line[0] == '#') // comment 
    continue; // skip it

  //... handle command in line here 
}

【讨论】:

  • 使用fgetc() 获取输入会使处理复杂化——我建议处理整行并按照@c-smile 的建议“标记\清理\忽略”整行
  • 我同意“阅读整行”的建议。但是,请参阅 while (!feof(file)) is always wrong。当然,您也在检查fgets(),但使用while (fgets(line, sizeof(line), fptr) != 0) 来控制循环会更惯用(如果您愿意,可以将!= 0 关闭,或者将其写为!= NULL)。跨度>
猜你喜欢
  • 2022-06-29
  • 1970-01-01
  • 1970-01-01
  • 2012-10-20
  • 2014-03-03
  • 1970-01-01
  • 2015-01-07
  • 2016-12-13
  • 1970-01-01
相关资源
最近更新 更多