coreutils4.5源码expr.c分析——漂亮的代码 有一本书叫《漂亮的代码》,其中选择了一些写得漂亮的代码,重点加以分析,如只用30多行程序实现正则表达式。今天反复读expr.c,感觉这个代码写得真漂亮。比如: static char * inttostr (intmax_t i, char buf[INT_STRLEN_BOUND (intmax_t) + 1]) { uintmax_t ui = i; char *p = buf + INT_STRLEN_BOUND (intmax_t); *p = '\0'; if (i < 0) ui = -ui; do *--p = '0' + ui % 10; while ((ui /= 10) != 0); if (i < 0) *--p = '-'; return p; } 这个函数把数字转为字符串。 如把-123存储到字符串str[10]中,大概是这个样子: str[000000-1230] 返回指针值str+6 我发现作者对指针的操作非常熟练。
/* Coerce V to an integer value. Return 1 on success, 0 on failure. */
static int toarith (VALUE *v) { intmax_t i; int neg; char *cp;
switch (v->type) { case integer: return 1; case string: i = 0; cp = v->u.s; neg = (*cp == '-'); if (neg) cp++;
do { if (ISDIGIT (*cp)) i = i * 10 + *cp - '0'; else return 0; } while (*++cp);
free (v->u.s); v->u.i = i * (neg ? -1 : 1); v->type = integer; return 1; default: abort (); } } 这个程序把字符串转为数字。同样的漂亮。 另外,作者没有实现语法树,所以有一系统的eval函数,如eval(),eval1(),eval2(),eval3(),eval4(),eval5(),eval6(),eval7() 我的理解是,eval()-->eval1() eval()-->eval1() eval1()-->eval2() ..... 其中每个eval函数写得相当的精练。 如: static VALUE * eval (void) { VALUE *l; VALUE *r;
#ifdef EVAL_TRACE trace ("eval"); #endif l = eval1 (); while (1) { if (nextarg ("|")) { r = eval1 (); if (null (l)) { freev (l); l = r; } else freev (r); } else return l; } } 这个函数没有递归,如执行./expr 3 | 2 说不明白,感觉有些懂。
