2013-03-03 80 views
1

我需要解析很多文件名(最多250000我猜),包括路徑,並從中提取一些部分。「模式匹配」和提取在C

下面是一個例子:

原文:/my/complete/path/to/80/01/a9/1d.pdf

需要:8001a91d

的 「模式」 我正在尋找將始終以 「/ 8」 開頭。我需要提取的部分組成一個8位十六進制數字的字符串。

我的想法是以下(simplyfied演示):

/* original argument */ 
char *path = "/my/complete/path/to/80/01/a9/1d.pdf"; 

/* pointer to substring */ 
char *begin = NULL; 

/* final char array to be build */ 
char *hex = (char*)malloc(9); 

/* find "pattern" */ 
begin = strstr(path, "/8"); 
if(begin == NULL) 
    return 1; 

/* jump to first needed character */ 
begin++; 

/* copy the needed characters to target char array */ 
strncpy(hex, begin, 2); 
strncpy(hex+2, begin+3, 2); 
strncpy(hex+4, begin+6, 2); 
strncpy(hex+6, begin+9, 2); 
strncpy(hex+8, "\0", 1);  

/* print final char array */ 
printf("%s\n", hex); 

這工作。我只是覺得它不是最聰明的方式。而且可能有些陷阱我看不到自己。

那麼,有人有建議這種指針移位方式會有什麼危險嗎?你認爲什麼會有所改進?

C是否提供了這樣的功能,如s|/(8.)/(..)/(..)/(..)\.|\1\2\3\4|?如果我沒有記錯,一些腳本語言有這樣的功能;如果你明白我的意思。

+1

我認爲你這樣做大部分是正確的,但會用普通的賦值來替換'strncpy',並將這個操作限制在一個我不需要看到的函數中。 – cnicutar 2013-03-03 09:38:36

+0

你的意思是這樣的'hex [0] = begin [0];'? – 2013-03-03 09:41:32

+0

是的。但這更多的是品味的問題,對我來說看起來很好的東西可能會讓你看起來很可怕。 – cnicutar 2013-03-03 09:43:40

回答

2

C本身不提供這個,但你可以使用POSIX正則表達式。它是一個全功能的正則表達式庫。但是對於一個和你一樣簡單的模式,這可能是最好的方法。

順便說一句,更喜歡memcpystrncpy。很少有人知道什麼strncpy是有益的。我不是其中之一。

+0

因此,memcpy是好兄弟嗎?我在第一眼看不出什麼區別,但我會深入一點。謝謝! – 2013-03-03 09:46:15

+2

'memcpy'只是複製內存。 'strncpy'可能會或可能不會嘗試通過一組神祕的規則添加終止的'\ 0'。 – 2013-03-03 09:50:18

0

在簡單的匹配/8./../../..的情況下,我自己親自去0123'解決方案(不需要外部依賴項)。如果規則變得更多,你可以嘗試一個詞法分析器(flex和朋友),它們支持正則表達式。

在你的情況是這樣的:

h2   [0-9A-Fa-f]{2} 
mymatch  (/{h2}){4} 

可以工作。儘管詞法分析器通常會返回令牌標識符,但您必須將緩衝區設置爲匹配副作用。

無論如何,您將獲得沒有依賴關係的regexps的威力,但代價是生成的(讀取:不可讀的)代碼。

0
/* original argument */ 
char *path = "/my/complete/path/to/80/01/a9/1d.pdf"; 
char *begin; 
char hex[9]; 
size_t len; 

/* find "pattern" */ 
begin = strstr(path, "/8"); 
if (!begin) return 1; 

// sanity check 
len = strlen(begin); 
if (len < 12) return 2; 

    // more sanity 
if (begin[3] != '/' || begin[6] != '/' || begin[9] != '/') return 3; 

memcpy(hex, begin+1, 2); 
memcpy(hex+2, begin+4, 2); 
memcpy(hex+4, begin+7, 2); 
memcpy(hex+6, begin+10, 2); 
     hex[8] = 0;  

    // For additional sanity, you could check for valid hex characters here 
/* print final char array */ 
printf("%s\n", hex); 
+0

謝謝。這幾乎就是我未修改的代碼的樣子:-) – 2013-03-03 12:30:25

+0

然後,你爲什麼要修改它?在發佈之前你實際上已經取消了支票 – wildplasser 2013-03-03 12:32:33

+0

是的。他們不是問題的一部分,我試圖將其歸結爲我想問的問題。就像我也遺漏了其他(包括,功能,...)。 – 2013-03-03 13:20:54