从C源代码中删除字符串

hlo*_*dal 2 c string code-formatting utility reformatting

有人能指出我从C源代码中删除字符串的程序吗?例

#include <stdio.h>
static const char *place = "world";
char * multiline_str = "one \
two \
three\n";
int main(int argc, char *argv[])
{
        printf("Hello %s\n", place);
        printf("The previous line says \"Hello %s\"\n", place);
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

#include <stdio.h>
static const char *place = ;
char * multiline_str = ;
int main(int argc, char *argv[])
{
        printf(, place);
        printf(, place);
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

我正在寻找的是一个非常像stripcmt的程序 ,我只想删除字符串而不是注释.

我正在寻找一个已经开发的程序而不仅仅是一些方便的正则表达式的原因是因为当你开始考虑所有极端情况(字符串中的引号,多行字符串等)时,事情通常会开始(比)更复杂第一次出现.REs可以实现的限制是有限制的,我怀疑这项任务是不可能的.如果你认为你有一个非常强大的正则表达式随时提交,但请不要sed 's/"[^"]*"//g'像天真的建议.

(不需要在注释中对(可能是未结束的)字符串进行特殊处理,这些字符串将首先被删除)

支持具有嵌入换行符的多行字符串并不重要(不合法C),但必须支持跨越以\结尾的多行的字符串.

这与其他一些 问题几乎相同,但我没有找到任何工具的参考.

Lau*_*ves 5

C语言(以及大多数其他编程语言)中的所有标记都是"常规".也就是说,它们可以通过正则表达式匹配.

C字符串的正则表达式:

"([^"\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))*"
Run Code Online (Sandbox Code Playgroud)

正则表达式并不难理解.基本上字符串文字是一对双引号围绕着一堆:

  • 非特殊(非引用/反斜杠/换行)字符
  • escapes,以反斜杠开头,然后由以下之一组成:
    • 一个简单的逃脱角色
    • 1到3个八进制数字
    • x和1个或多个十六进制数字

这基于C89/C90规范的6.1.4和6.1.3.4节.如果在C99中有任何其他东西悄悄进入,这将无法捕捉到,但这不应该很难解决.

这是一个python脚本,用于过滤删除字符串文字的C源文件:

import re, sys
regex = re.compile(r'''"([^"\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))*"''')
for line in sys.stdin:
  print regex.sub('', line.rstrip('\n'))
Run Code Online (Sandbox Code Playgroud)

编辑:

在我发布上述内容之后发生了这一点,虽然所有的C令牌都是正常的,但没有标记化我们有机会遇到麻烦.特别是,如果双引号显示在另一个标记中,我们可以沿着花园路径前进.你提到评论已被删除,所以我们真正需要担心的另一件事是字符文字(虽然我将使用的方法可以很容易地扩展以处理评论).这是一个处理字符文字的更健壮的脚本:

import re, sys
str_re = r'''"([^"\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))*"'''
chr_re = r"""'([^'\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))'"""

regex = re.compile('|'.join([str_re, chr_re]))

def repl(m):
  m = m.group(0)
  if m.startswith("'"):
    return m
  else:
    return ''
for line in sys.stdin:
  print regex.sub(repl, line.rstrip('\n'))
Run Code Online (Sandbox Code Playgroud)

基本上我们正在寻找字符串和字符文字标记,然后单独留下字符文字,但剥离字符串文字.char literal regex与字符串文字非常相似.