首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >将C文件导出到新文件时,删除#if 0和#endif之间的代码

将C文件导出到新文件时,删除#if 0和#endif之间的代码
EN

Stack Overflow用户
提问于 2018-09-10 03:48:04
回答 3查看 2K关注 0票数 5

我想删除toy.c文件中的所有注释。从Remove comments from C/C++ code中我看到我可以使用

代码语言:javascript
复制
gcc -E -fpreprocessed -P -dD toy.c

但是我的一些代码(比如我不想编译的不推荐使用的函数)被包装在between #if 0 and endif, as if they were commented out中。

  • 一方面,上面的命令不会删除这种类型的“注释”,因为它只能在-fpreprocessed阻止的宏展开时删除;
  • 另一方面,我有其他不想展开的宏,所以删除-fpreprocessed不是一个好主意。

我看到了一个进退两难的局面。有没有办法走出这种局面?谢谢。

下面的玩具示例"toy.c“就足以说明这个问题。

代码语言:javascript
复制
#define foo 3  /* this is a macro */

// a toy function
int main (void) {
  return foo;
  }

// this is deprecated
#if 0
int main (void) {
  printf("%d\n", foo);
  return 0;
  }
#endif

gcc -E -fpreprocessed -P -dD toy.c给出

代码语言:javascript
复制
#define foo 3
int main (void) {
  return foo;
  }
#if 0
int main (void) {
  printf("%d\n", foo);
  return 0;
  }
#endif

gcc -E -P toy.c给出了

代码语言:javascript
复制
int main (void) {
  return 3;
  }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-09-10 13:19:09

谢谢你另外两个答案。

我现在知道unifdefsunifdef了。我很高兴知道这些工具的存在,而且我不是唯一一个想要做这种代码清理的人。

我还写了一个删除#if 0 ... #endif块的rm_if0_endif.c (附在下面),这对我来说已经足够了。它的哲学是基于文本处理的。它扫描一个输入C脚本,定位#if 0和正确的封闭endif,以便在逐个字符复制时可以省略这个块。

文本处理方法是有限的,因为它仅适用于#if 0 ... #endif情况,但这就是我现在需要的全部内容。C程序并不是这种文本处理的唯一方法。Jean-François Fabre's answer演示了如何在Python语言中执行此操作。我也可以用R做类似的事情,使用readLinesstartsWithwriteLines。我选择用C语言,因为我还不是C语言的专家,所以这个任务驱使我去学习。这是我的rm_if0_endif.c的演示。请注意,该程序可以连接多个C文件并为每个文件添加头文件。

原始输入文件input.c

代码语言:javascript
复制
#define foo 3  /* this is a macro */

// a toy function
int test1 (void) {
  return foo;
  }

#if 0

#undef foo
#define foo 4

#ifdef bar
  #warning "??"
#endif

// this is deprecated
int main (void) {
  printf("%d\n", foo);
  return 0;
  }

#endif

// another toy
int test2 (void) {
  return foo;
  }

gcc预处理输出"gcc_output.c“(作为我的程序的输入)

代码语言:javascript
复制
gcc -E -fpreprocessed -P -dD input.c > gcc_output.c

代码语言:javascript
复制
#define foo 3
int test1 (void) {
  return foo;
  }
#if 0
#undef foo
#define foo 4
#ifdef bar
  #warning "??"
#endif
int main (void) {
  printf("%d\n", foo);
  return 0;
  }
#endif
int test2 (void) {
  return foo;
  }

我的程序的最终输出final_output.c

rm_if0_endif.c具有效用函数pattern_matching和主函数rm_if0_endif

代码语言:javascript
复制
void rm_if0_endif (char *InputFile,
                   char *OutputFile, char *WriteMode, char *OutputHeader);

下面的附加文件有一个main函数,正在执行

代码语言:javascript
复制
rm_if0_endif("gcc_output.c",
             "final_output.c", "w", "// this is a demo of 'rm_if0_endif.c'\n");

它产生:

代码语言:javascript
复制
// this is a demo of 'rm_if0_endif.c'
#define foo 3
int test1 (void) {
  return foo;
  }

int test2 (void) {
  return foo;
  }

附录:rm_if0_endif.c

代码语言:javascript
复制
#include <stdio.h>
int pattern_matching (FILE *fp, const char *pattern, int length_pattern) {
  int flag = 1;
  int i, c;
  for (i = 0; i < length_pattern; i++) {
    c = fgetc(fp);
    if (c != pattern[i]) {
      flag = 0; break;
      }
    }
  return flag;
  }
void rm_if0_endif (char *InputFile,
                   char *OutputFile, char *WriteMode, char *OutputHeader) {
  FILE *fp_r = fopen(InputFile, "r");
  FILE *fp_w = fopen(OutputFile, WriteMode);
  fpos_t pos;
  if (fp_r == NULL) perror("error when opening input file!");
  fputs(OutputHeader, fp_w);
  int c, i, a1, a2;
  int if_0_flag, if_flag, endif_flag, EOF_flag;
  const char *if_0 = "if 0";
  const char *endif = "endif";
  EOF_flag = 0;
  while (EOF_flag == 0) {
    do {
      c = fgetc(fp_r);
      while ((c != '#') && (c != EOF)) {
        fputc(c, fp_w);
        c = fgetc(fp_r);
        }
      if (c == EOF) {
        EOF_flag = 1; break;
        }
      fgetpos(fp_r, &pos);
      if_0_flag = pattern_matching(fp_r, if_0, 4);
      fsetpos(fp_r, &pos);
      if (if_0_flag == 0) fputc('#', fp_w);
      } while (if_0_flag == 0);
    if (EOF_flag == 1) break;
    a1 = 1; a2 = 0;
    do {
      c = fgetc(fp_r);
      while (c != '#') c = fgetc(fp_r);
      fgetpos(fp_r, &pos);
      if_flag = pattern_matching(fp_r, if_0, 2);
      fsetpos(fp_r, &pos);
      if (if_flag == 1) a1++;
      fgetpos(fp_r, &pos);
      endif_flag = pattern_matching(fp_r, endif, 5);
      fsetpos(fp_r, &pos);
      if (endif_flag == 1) a2++;
      } while (a1 != a2);
    for (i = 0; i < 5; i++) c = fgetc(fp_r);
    if (c == EOF) {
      EOF_flag == 1;
      }
    }
  fclose(fp_r);
  fclose(fp_w);
  }
int main (void) {
  rm_if0_endif("gcc_output.c",
               "final_output.c", "w", "// this is a demo of 'rm_if0_endif.c'\n");
  return 0;
  }
票数 0
EN

Stack Overflow用户

发布于 2018-09-10 06:31:50

有一对程序,sunifdef (“unifdef之子”,可以从unifdef获得)和coan,可以用来做你想做的事情。these Is there a C pre-processor which eliminates #ifdef blocks based on values defined/undefined?提供了讨论这些程序的答案。

例如,给定"xyz37.c":

代码语言:javascript
复制
#define foo 3  /* this is a macro */

// a toy function
int main (void) {
  return foo;
  }

// this is deprecated
#if 0
int main (void) {
  printf("%d\n", foo);
  }
#endif

使用sunifdef

代码语言:javascript
复制
sunifdef -DDEFINED -ned < xyz37.c

给出

代码语言:javascript
复制
#define foo 3  /* this is a macro */

// a toy function
int main (void) {
  return foo;
  }

// this is deprecated

给定这个文件"xyz23.c":

代码语言:javascript
复制
#if 0
This is deleted
#else
This is not deleted
#endif

#if 0
Deleted
#endif

#if defined(XYZ)
XYZ is defined
#else
XYZ is not defined
#endif

#if 1
This is persistent
#else
This is inconsistent
#endif

该程序

代码语言:javascript
复制
sunifdef -DDEFINE -ned < xyz23.c

给出

代码语言:javascript
复制
This is not deleted

#if defined(XYZ)
XYZ is defined
#else
XYZ is not defined
#endif

This is persistent

我想,这就是你想要的。-DDEFINED选项似乎是必要的;可以选择代码中不使用的任何名称。如果您愿意,也可以使用-UNEVER_DEFINE_THIS-ned选项计算常量项并删除相关代码。如果没有它,像01这样的常量术语就不会被消除。

我已经愉快地使用sunifdef很多年了(长达十年之久)。我还没有发现它会出错,我已经用它清理了一些令人反感的深奥的“ifdeffery”集合。程序coan是对sunifdef的开发,具有更多的功能。

票数 4
EN

Stack Overflow用户

发布于 2018-09-10 04:05:00

预处理器不会产生异常。您不能在这里使用它来做这件事。

一个使用python的简单状态机就可以工作。它甚至可以处理嵌套(嗯,也许并不是所有的情况都像嵌套的#if 0一样被覆盖,但你可以在之前和之后比较源代码,并手动验证)。也不支持注释代码(但似乎你已经覆盖了它)

输入(在演示中比您的输入稍微复杂一些):

代码语言:javascript
复制
#define foo 3
int main (void) {
  return foo;
  }
#if 0
int main (void) {
  #ifdef DDD
  printf("%d\n", foo);
  #endif
  }
#endif

void other_function()
{}

现在,代码使用正则表达式来检测#if & #endif

代码语言:javascript
复制
import re
rif0 = re.compile("\s*#if\s+0")
rif = re.compile("\s*#(if|ifn?def)")
endif = re.compile("\s*#endif")

if_nesting = 0
if0_nesting = 0
suppress = False

with open("input.c") as fin, open("output.c","w") as fout:
    for l in fin:
        if rif.match(l):
            if_nesting += 1
            if rif0.match(l):
                suppress = True
                if0_nesting = if_nesting
        elif endif.match(l):
            if if0_nesting == if_nesting:
                suppress = False
            if_nesting -= 1
            continue  # don't write the #endif

        if not suppress:
            fout.write(l))

输出文件包含:

代码语言:javascript
复制
#define foo 3
int main (void) {
  return foo;
  }

void other_function()
{}

因此,嵌套起作用了,#if 0部件被成功删除。这不是sed "/#if 0/,/#endif/d所能做到的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52248143

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档