文章目录
表达式求值是程序设计中的一个经典问题,主要考察对栈的应用。
一般是形如:
int expr(char* s){
}
入口参数 s 是待求表达式。我们就以s包含 “+, -, *, /, (, ), 10进制数非负整数”,表达式合法作为已知条件讨论这个问题。
返回值 即表达式的结果。
Step1. Token 提取
第一步,我们需要提取 Token。主要有以下两种方法:
正则表达式
C 中本身没有 RE 特性,但 Linux 中 regex.h 提供 RE 特性;
使用 RE ,优点是拓展性好,需要加什么操作很容易完成。
#include <sys/types.h>
#include <regex.h>
#include <stdlib.h>
enum {
TK_NOTYPE = 256, TK_NUM,
};
static struct rule {
char *regex;
int token_type;
} rules[] = {
{
" +", TK_NOTYPE}, // spaces
{
"\\+", '+'}, // plus
{
"-", '-'}, // decrease
{
"\\*", '*'}, // multiply
{
"/", '/'}, // divide
{
"\\(",'('}, // Left parenthesis
{
"\\)",')'}, // Right parenthesis
{
"([1-9][0-9]{1,31})|[0-9]",TK_NUM}, // Decimal integer
};
#define NR_REGEX (sizeof(rules) / sizeof(rules[0]) )
static regex_t re[NR_REGEX];
/* Rules are used for many times.
* Therefore we compile them only once before any usage.
*/
void init_regex() {
int i;
char error_msg[128];
int ret;
for (i = 0; i < NR_REGEX; i ++) {
ret = regcomp(&re[i], rules[i].regex, REG_EXTENDED);
if (ret != 0)
regerror(ret, &re[i], error_msg, 128);
}
}
typedef struct token {
int type;
char str[32];
} Token;
Token tokens[10000];
int nr_token;
static bool make_token(char *e) {
int position = 0;
int i;
regmatch_t pmatch;
nr_token = 0;
while (e[position] != '\0') {
/* Try all rules one by one. */
for (i = 0; i < NR_REGEX; i ++) {
if (regexec(&re[i], e + position, 1, &pmatch, 0) == 0 && pmatch.rm_so == 0) {
char *substr_start = e + position;
int substr_len = pmatch.rm_eo;
position += substr_len;
switch (rules[i].token_type) {
case '+':
case '-':
case '*':
case '/':
case '(':
case ')':
case TK_NUM:
{
tokens[nr_token].type = rules[i].token_type;
strncpy(tokens[nr_token].str, substr_start, substr_len);
tokens