2009-08-18 54 views
2

任何人都可以指向一個從C源代碼中去除字符串的程序嗎?例如從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; 
} 

成爲

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

我所尋找的是一個程序非常喜歡stripcmt 只是我想要去除的字符串,而不是評論。

,我在尋找一個已經開發的程序,而不只是一些方便的正則表達式的原因是 因爲當你開始考慮所有的情況(字符串中的引號,多行字符串等) 事情通常開始是(很多)比第一次出現更復雜。並且 有哪些RE可以實現的限制,我懷疑這個任務是不可能的。 如果你認爲你有一個極其健壯的正則表達式隨時提交,但請不要天真sed 's/"[^"]*"//g'喜歡的建議。

(無需註釋內(可能未端)字符串中的特殊的處理,那些將首先被刪除)

支持具有嵌入式換行符多行字符串並不重要(不合法C),但必須支持跨越以\結尾的多行的字符串。

這幾乎與someotherquestions一樣,但我沒有發現任何工具的參考。

+3

純粹是爲了利益,爲什麼你需要這樣的工具?換句話說,你將如何處理該工具的輸出? – 2009-08-18 15:14:02

+0

它用於令牌搜索。例如「在哪些文件中函數x,y和z叫」。通過預處理,刪除評論和字符串我會得到一個準確的結果。目前這些琴絃正在產生噪音。 – hlovdal 2009-08-18 15:41:10

+2

使用理解C的代碼分析工具不是更好嗎?有很多。 – 2009-08-18 16:17:57

回答

4

您可以下載source code to StripCmt(.tar.gz - 5kB)。它非常小,不應該太難以適應條紋字符串(它是released under the GPL)。

您可能還想研究C字符串的官方詞彙語言規則。我發現this很快,但它可能不是確定性的。它將字符串定義爲:

stringcon ::= "{ch}", where ch denotes any printable ASCII character (as specified by isprint()) other than " (double quotes) and the newline character. 
+0

我沒有想過檢查stripcmt的來源。修改很簡單。 – hlovdal 2009-08-18 18:04:35

5

C(以及大多數其他編程語言)中的所有標記都是「常規」的。也就是說,它們可以通過正則表達式匹配。

爲C字符串的正則表達式:

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

的正則表達式是不是太難理解了。基本上文字串是一對周圍一堆雙引號:

  • 非特殊(非報價/反斜槓/換行符)字符
  • 逃逸,其以反斜槓開始,然後由一個的:
    • 一個簡單的換碼字符
    • 1至3個八進制數字
    • x和1個或多個十六進制數字

這是基於6.1.4和6.1.3節。4的C89/C90規範。如果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')) 

編輯:

據我張貼的上面後雖然這是事實發生,我認爲所有的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')) 

本質上我們發現字符串和字符文字記號,然後只留下燒焦的文字,但剔除字符串文字。 char literal正則表達式與字符串文字非常相似。

+0

在這種情況下,我認爲它會更好:([^「\\\ n] | \\。)* – hiena 2009-08-18 15:53:07

+0

您的正則表達式無法處理 << char * str =」one \ two \ three \ n 「; >>表示有一個換行符,這就是我的意思:) – hlovdal 2009-08-18 16:05:34

+0

使用\連接行是預處理的一部分,我忽略了它(例如:如果代碼是< > - 你想怎麼做?)如果你關心的只是連接線,你可以在abfnrtv字符類中添加\ n,並用sys替換for-loop .stdout.write(regex.sub(repl,sys.stdin.read())。你還需要調整chr_re,如果你擔心char文字內部的行連接。 – 2009-08-18 16:20:21

0

在紅寶石:

#!/usr/bin/ruby 
f=open(ARGV[0],"r") 
s=f.read 
puts(s.gsub(/"(\\(.|\n)|[^\\"\n])*"/,"")) 
f.close 

打印到標準輸出

0

在Python使用pyparsing:

from pyparsing import dblQuotedString 

source = open(filename).read() 
dblQuotedString.setParseAction(lambda : "") 
print dblQuotedString.transformString(source) 

同時打印到標準輸出。