-
2009-08-15
统计程序注释行数之核心程序---正则表达式匹配文件名 - [comment系列]
熟悉linux的用户一定用过ls命令。而ls命令参数是支持正则表达式的。要不然我想看100个文件的信息,岂不是要输入100个文件名。同理统计程序注释行数设计到的程序文件也可能有很多,所有,支持正则表达式是必须的。
其实,在C语言下也可以使用正则表达式,当然C标准里没有这些库函数,目前包含正则表达式的函数库有两个:POSIX以及PERL。通常LINUX的各个版本中都有POSIX库,而PERL库就需要另外安装。介于这个原因,本程序中使用POSIX库.
具体POSIX库中关于正则表达式函数使用可以参考这篇帖子,很详细,还有例子。
主要是以下4个函数的使用(linux下直接 man 3 regex就可以看到):
SYNOPSIS
#include <sys/types.h>
#include <regex.h>- int regcomp(regex_t *preg, const char *regex, int cflags);
- int regexec(const regex_t *preg, const char *string, size_t nmatch,regmatch_t pmatch[], int eflags);
- size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
- void regfree(regex_t *preg);
主要程序如下:
23 #define BUFFSIZE 128u /* buffer size */
24
25 /*-----------------------------------------------------------------------------
26 * Description: According to the regex,judge whether the filename
27 * matches the regex or not.
28 *-----------------------------------------------------------------------------*/
29 Boolean_e
30 is_string_matched_regex (
31 const char *filename, /* filename string needed to match */
32 const char *pattern /* regex pattern */
33 )
34 {
35 Boolean_e is_matched = FALSE;
36 uint32 matched_no = 0;
37 uint32 ret = 0;
38 uint8 err_buf[BUFFSIZE] = {0};
39
40 regex_t reg;
41 regmatch_t pm[10]; /* the array storing the matched result */
42 const size_t nmatch = 10;
43
44 RETURN_VAL_IF_FAIL(filename == NULL, FALSE);
45 RETURN_VAL_IF_FAIL(pattern != NULL, FALSE);
46
47 #ifdef DEBUG
48 printf("%s is processing...\n",__FUNCTION__);
49 #endif /* ----- DEBUG ----- */
50
51 /*-----------------------------------------------------------------------------
52 * compile the regex
53 * using (Extend |Insensitive Case | Newline) POSIX regx
54 *-----------------------------------------------------------------------------*/
55 ret = regcomp(®, pattern, REG_EXTENDED|REG_ICASE|REG_NEWLINE);
56 if (ret != 0)
57 {
58 regerror(ret, ®, err_buf, sizeof(err_buf));
59 fprintf(stderr, "%s: filename '%s' \n", err_buf,filename);
60 is_matched = FALSE;
61
62 return(is_matched);
63 }
64
65 /* exec the regex match*/
66 ret = regexec(®, filename, nmatch, pm, 0);
67
68 if (ret == REG_NOMATCH )
69 {
70 is_matched = FALSE;
71
72 return(is_matched);
73 }
74 else
75 if (ret != 0)
76 {
77 regerror(ret, ®, err_buf, sizeof(err_buf));
78 fprintf(stderr, "%s: regcom('%s')\n", err_buf, filename);
79 is_matched = FALSE;
80
81 return(is_matched);
82 }
83
84 /* judge if matched according to the regexec's result */
85 for (matched_no = 0; matched_no < nmatch && pm[matched_no].rm_so != -1; ++ matched_no)
86 {
87 /*result = substr(filename, pm[matched_no].rm_so, pm[matched_no].rm_eo);*/
88
89 if( pm[matched_no].rm_so == 0
90 && pm[matched_no].rm_eo == strlen(filename))
91 {
92 is_matched = TRUE;
93 break;
94 }
95 }
96
97 /* release regex */
98 regfree(®);
99
100 return(is_matched);
101 } /* ----- end of function is_string_matched_regex ----- */实现单个文件名与正则表达式的匹配之后,只需要遍历当前目录下的所有文件名,重复匹配。
测试程序如下:
int main(int argc, char *argv[])
105 {
106 Boolean_e is_matched = FALSE;
107 uint16 file_no = 0;
108
109 DIR *dp = NULL;
110 struct dirent *dirp = NULL;
111
112 /*-----------------------------------------------------------------------------
113 * open the current directoty.
114 *-----------------------------------------------------------------------------*/
115 if((dp = opendir("."))== NULL)
116 {
117 printf("can't open the current directoty!\n");
118 exit(0);
119 }
120
121 /* get filename in the current directoty,and match the regex. */
122 while((dirp = readdir(dp))!=NULL)
123 {
124 file_no++;
125 is_matched = is_string_matched_regex(dirp->d_name, argv[1]);
126
127 #ifdef DEBUG
128 if( is_matched == TRUE )
129 {
130 printf("file_no:%d---filename:%s\n",file_no, dirp->d_name);
131 }
132 #endif /* ----- DEBUG ----- */
133 }
134
135 closedir(dp);
136
137 return 0;
138 }