學習了用用操作符堆棧和操作數堆棧實現四則運算表達式的基本思想和實現後,在https://blog.csdn.net/cyq0318/article/details/78633752/的基礎上自己動手實現了一下,代碼全部在CodeBlocks 下測試通過。
堆棧實現代碼如下:
#ifndef _DATA_STRUCT_H
#define _DATA_STRUCT_H
typedef struct _NODE
{
void *data;
struct _NODE *next;
} NODE;
typedef struct _STACK
{
NODE *top;
int nd_size;
int count;
} STACK;
void stack_init(STACK *s,int nd_size);
BOOL stack_empty(STACK *s);
void stack_push(STACK *s,void *data);
void* stack_pop(STACK *s);
void* stack_get_top(STACK *s);
char stack_ch_pop(STACK *s);
int stack_int_pop(STACK *s);
char stack_ch_peek(STACK *s);
#endif
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <assert.h>
#include "define.h"
#include "data_struct.h"
void stack_init(STACK *s,int nd_size)
{
s->top = NULL;
s->nd_size = nd_size;
s->count = 0;
return;
}
BOOL stack_empty(STACK *s)
{
return (s->top == NULL) ? R_TRUE:R_FALSE;
}
void stack_push(STACK *s,void *data)
{
NODE *p = (NODE *)malloc(sizeof(NODE));
assert(p);
p->data = malloc(s->nd_size);
memcpy(p->data,data,s->nd_size);
p->next = s->top;
s->top = p;
s->count++;
return;
}
void* stack_pop(STACK *s)
{
void *data = NULL;
if(s->top)
{
NODE *node = s->top;
data = node->data;
s->top = s->top->next;
s->count--;
free(node);
}
return data;
}
void* stack_get_top(STACK *s)
{
void *data = NULL;
if(s->top)
{
data = s->top->data;
}
return data;
}
char stack_ch_pop(STACK *s)
{
void *data;
char c;
data = stack_pop(s);
if(!data)
return 0;
c = *(char *)data;
free(data);
return c;
}
int stack_int_pop(STACK *s)
{
void *data;
int d;
data = stack_pop(s);
assert(data);
d = *(int *)data;
free(data);
printf("stack_int_pop:pop %d\n",d);
return d;
}
char stack_ch_peek(STACK *s)
{
void *data;
char c;
data = stack_get_top(s);
if(!data)
return 0;
c = *(char *)data;
return c;
}
表達式實現代碼如下;
/* 求出四則運算表達式的值 */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <assert.h>
#include "define.h"
#include "data_struct.h"
#define LP '('
#define RP ')'
#define PLUS '+'
#define MINUS '-'
#define MUL '*'
#define DIV '/'
int expr_op_priority(char s)
{
switch(s)
{
case '*':
case '/':
return 3;
case '+':
case '-':
return 2;
case '(':
case ')':
return 1;
default:
return 0;
}
}
static int oper_nolower_pri(char new_op,char old_op)
{
return expr_op_priority(new_op) >= expr_op_priority(old_op);
}
static void expr_pop_and_calc(STACK *s_op,STACK *s_num)
{
char oper = stack_ch_pop(s_op);
int num2 = stack_int_pop(s_num);
int num1 = stack_int_pop(s_num);
int result;
printf("%d %c %d\n",num1,oper,num2);
switch(oper)
{
case '+':
result = num1 + num2;
break;
case '-':
result = num1 - num2;
break;
case '*':
result = num1 * num2;
break;
case '/':
result = num1/num2;
break;
}
stack_push(s_num,&result);
printf("push num:%d\n",result);
return;
}
int math_expr(char *expr)
{
STACK stack_op,stack_num;
char *p = expr;
int num;
stack_init(&stack_op,sizeof(char));
stack_init(&stack_num,sizeof(int));
while(*p)
{
printf("begin parse %c\n",*p);
if(isdigit(*p))
{
num = util_str2num(p);
while(isdigit(*p))
p++;
printf("push num=%d\n",num);
stack_push(&stack_num,&num);
}
else if(*p == LP)
{
printf("oper=%c\n",*p);
stack_push(&stack_op,p);
p++;
}
else if(*p == RP)
{
char last_oper = stack_ch_peek(&stack_op);
printf("last oper=%c\n",last_oper);
if(last_oper == LP)
stack_pop(&stack_op);
else
{
expr_pop_and_calc(&stack_op,&stack_num);
last_oper = stack_ch_peek(&stack_op);
if(last_oper == LP)
stack_pop(&stack_op);
else
stack_push(&stack_op,p);
}
p++;
last_oper = stack_ch_peek(&stack_op);
printf("last oper111=%c\n",last_oper);
}
else
{
char last_oper,cur_oper = *p;
last_oper = stack_ch_peek(&stack_op);
printf("oper=%c,last_oper=%c\n",*p,last_oper);
if(last_oper && oper_nolower_pri(last_oper,cur_oper))
{
expr_pop_and_calc(&stack_op,&stack_num);
}
stack_push(&stack_op,p);
p++;
}
}
while(!stack_empty(&stack_op))
{
char cur_op = stack_ch_pop(&stack_op);
char last_op = stack_ch_peek(&stack_op);
printf("cur op=%c,last op=%c\n",cur_op,last_op);
if(last_op == LP && cur_op == RP)
stack_pop(&stack_op);
else if(!last_op)
{
stack_push(&stack_op,&cur_op);
expr_pop_and_calc(&stack_op,&stack_num);
}
else if(oper_nolower_pri(last_op,cur_op))
expr_pop_and_calc(&stack_op,&stack_num);
if(cur_op == RP && last_op != LP)
stack_push(&stack_op,&cur_op);
}
num = stack_int_pop(&stack_num);
assert(stack_empty(&stack_num));
assert(stack_empty(&stack_op));
return num;
}
void math_expr_test(void)
{
int result,expected_result;
result = math_expr("((23+24)*2-34+(20-4))");
expected_result = (23+24)*2-34+(20-4);
assert(result == expected_result);
result = math_expr("((1+1))");
expected_result = (1+1);
assert(result == expected_result);
result = math_expr("12+23-45");
expected_result = 12+23-45;
assert(result == expected_result);
result = math_expr("12+23-45+(78-23)");
expected_result = 12+23-45+(78-23);
assert(result == expected_result);
result = math_expr("(235+24*5)");
expected_result = (235+24*5);
assert(result == expected_result);
}