【beautiful code】
下面这段代码实现一个正则表达式适配器,用来处理以下的模型:
字符 | 含义 |
c | 匹配任意的字符c |
.(句点) | 匹配任意的单个字符 |
^ | 匹配输入字符串的开头 |
$ | 匹配输入字符串的结尾 |
* | 匹配前一个字符的零个或者多个出现 |
以下是匹配算法的代码:
- /* match: 在text中找到regexp */
- int match(char *regexp, char *text)
- {
- if (regexp[0] == '^')
- return matchhere(regexp + 1, text);
- do { /* 即使字符串为空时也必须检查 */
- if (matchhere(regexp, text))
- return 1;
- } while (*text++ != '/0');
- return 0;
- }
- /* matchhere: 在text的开头查找regexp */
- int matchhere(char *regexp, char *text)
- {
- if (regexp[0] == '/0')
- return 1;
- if (regexp[1] == '*')
- return matchstar(regexp[0], regexp + 2, text);
- if (regexp[0] == '$' && regexp[1] == '/0')
- return *text == '/0';
- if (*text != '/0' && (regexp[0] == '.' || regexp[0] == *text))
- return matchhere(regexp + 1, text + 1);
- return 0;
- }
- /* matchstar: 在text的开头查找C*regexp */
- int matchstar(int c, char *regexp, char *text)
- {
- do { /* 通配符 * 匹配零个或多个实例 */
- if (matchhere(regexp, text))
- return 1;
- } while (*text != '/0' && (*text++ == c || c == '.'));
- return 0;
- }
如果在matchstar函数中需要识别最左边的一级最长的匹配,那么函数将首先识别输入字符c的最大重复序列。然后函数将调用matchhere来尝试把匹配延伸到正则表达式的剩余部分和text的剩余部分。每次匹配失败都会将cs的出现次数减1,然后再次开始尝试,包括处理字符c零出现的情况:
- /* matchstar: 搜索c*regexp的最左一级最长的匹配 */
- int matchstar(int c, char *regexp, char *text)
- {
- char *t;
- for (t = text; *t != '/0' && (*t == c || c == '.'); t++);
- do { /* 通配符 * 匹配零个或者多个实例 */
- if (matchhere(regexp, t))
- return 1;
- } while (t-- > text);
- return 0;
- }
【结论】
什么是代码的优雅和美,在这一章给我的启示是,在处理一个问题时,学会取舍是非常重要的,如何选择一个最小的问题集来精确阐述需要描述的问题,实现时采用什么样的方法,写出紧凑的程序……
程序的美在于取舍!