|

楼主 |
发表于 2009-6-30 09:32:22
|
显示全部楼层
如果对正则表达式的机理有一定了解,就可以借助这个经验猜到这个函数大概是把正则表达
式字符串转换成状态机以便高效地匹配目标字符串。如果以前用过其它编程语言的正则表达
式库函数,也可以借助这些经验知道正则表达式在使用之前大多有一个预处理的步骤。另
外,对英文缩写要有一定敏感性,函数名是regcomp,reg就是正则表达式,comp是compare还
是compile?如果是compare,那应该有两个相同类型的参数来做比较,就像strcmp,这里显
然是compile,编译,把字符串形式转为二进制形式,从另一个侧面也验证了前面的猜测。这
些都是靠经验而不是推理得到的,经验有助于更快更准确地理解,但不是必须的,因为事实
上我们通过上面基于传入传出参数的推理已经猜出正确结论了,只不过有经验的人会对自己
的猜测更自信。
对英文缩写敏感是看man page和看代码需要具备的最基本的能力,但这需要长期的练习才能
找到感觉。也许你要学会一个函数怎么用并不必知道函数名和各个参数名是什么的缩写,你
通过以上列举的两本烂书就可以学会怎么用,但如果总是回避man page,总是不去做猜缩写
的练习,就不可能看懂别人的代码,不看别人的代码就自己乱写代码,连变量名该怎么起都
不知道,写出来的永远是垃圾代码。对于regcomp这个函数名以及各参数名,regex是
regular expression,regcomp是regular expression compile。那么preg是什么?reg是
regular expression,p表示什么呢?表示指针?那是微软的infamous的hungarian
notation,Linux上肯定不是这么用的,这里的p我猜是precompiled。cflags的c是什么?不
知道,但是跟下面一个函数对比来看:
C代码
1. int regexec(const regex_t *preg, const char *string, size_t nmatch,
2. regmatch_t pmatch[], int eflags);
int regexec(const regex_t *preg, const char *string, size_t nmatch,
regmatch_t pmatch[], int eflags);
这个函数有个参数叫eflags。所以c是regcomp的c,而e是regexec的e,一个是编译时的
flags,一个是执行时的flags,这两种flags的取值必然不同,下文必然会分别说明。这又是
一种猜测:猜测下文的行文逻辑。这种猜测同样是非常有助于理解的。后面几个函数的函数
名和参数名是怎么缩写的,留给读者自己练习。
preg参数在regcomp中是传出参数,在regexec中却是传入参数,根据推理,preg是由
regcomp函数填写好之后传给regexec函数用的,也就是说正则表达式以转换之后的二进制格
式传给regexec函数来用。regexec又有一个字符串传入参数string,还有两个match参数表示
匹配结果,pmatch是传出参数,表示缓冲区首地址,nmatch表示缓冲区长度(根据经验,这
类似于strncpy),这必然就是我一开始想要的my_expect_func了:
C代码
1. int my_expect_func(传入:正则表达式, 传入:目标字符串, 传出:匹配结果);
2. 返回:错误码
int my_expect_func(传入:正则表达式, 传入:目标字符串, 传出:匹配结果);
返回:错误码
preg对应正则表达式,pmatch和nmatch对应匹配结果,因此string这个传入参数必然是目标
字符串了。pmatch是一个指针变量,但是写成pmatch[],说明它指向的是一组而不是一个
regmatch_t类型的对象,这一组有多少个呢?用nmatch参数表示。和strncpy类似,这一组
regmatch_t对象应该由我们事先分配好再传给函数。因此这两个函数应该是这样调用的:
C代码
1. regex_t regobj;
2. regcomp(®obj, "正则表达式", 标志位1|标志位2|...);
3. regmatch_t matchbuf[10];
4. regexec(®obj, "目标字符串", 10, matchbuf, 标志位1|标志位2|...);
regex_t regobj;
regcomp(®obj, "正则表达式", 标志位1|标志位2|...);
regmatch_t matchbuf[10];
regexec(®obj, "目标字符串", 10, matchbuf, 标志位1|标志位2|...);
regmatch_t对象如何表示一个匹配呢?如果一个正则表达式模式在一个目标字符串中有五次
出现,如何表示这五次出现呢?可以猜测这个regmatch_t结构体一定包含了在目标字符串中
的匹配位置信息。另外,我传进去10个regmatch_t对象,如果只有五次匹配,函数返回后我
怎么知道前面五个对象是有效的匹配信息而后面是无效的呢?是不是通过一个参数或返回值
表示匹配次数的?该函数并没有额外的参数,而且快速翻看一下man page的RETURN
VALUE节,这个函数返回值是错误码,也不表示匹配次数。那这个函数一定会在后面无效的
regmatch_t对象里填充一个特殊值,这就是推理,这个猜测将会在阅读后面的文字时证实或
证伪,不管猜得对不对,一定会在后面得到答案。 |
|