1.0版:
功能:控制台实现中缀表达式的求值
作者:小代码:
时间:2014年 11月 09日 星期日 21:58:13 CST
#include<stdio.h> #include<stdlib.h> #include<string.h> #include"bolan.h" int main ( void ){ char test[] = {"1 + 2 * 3 - 7 * 5"}; char test1[] = {"1+2"}; // printf("len = %d\n",strlen(test)); char * p = exp_bolan( test ); // puts(p); int c = exp_bolan_cal( p ); printf("c = %d\n",c); return 0; }
此文件声明了栈的基本操作,模仿自JAVA的 java.util.Stack 类
/** @file stack.h * @brief 栈及其操作声明 */ #ifndef STACK_H_ #define STACK_H_ #include<stdio.h> #include<stdbool.h> /** @brief 栈 * */ struct _stack{ /** @brief 栈数组*/ char * elem; /** @brief 栈顶下标*/ int top; /** @brief 栈容量 */ size_t stack_size; }; /** @typedef 栈类型 */ typedef struct _stack Stack; /** @typedef 栈指针 */ typedef struct _stack * stackPtr; /** @brief 创建一个初始人的栈 * 其初始容量为16 * @return 初始化的栈 * @retval NULL 创建失败 */ stackPtr stack_init(); /** @brief 压栈 * @pre 栈 stack 存在 * @param stack 栈 * @param elem 要入压孤元素 * @retval 0 入栈成功 * @retval 1 入栈失败 */ int stack_push( stackPtr stack, char elem ); /** @brief 出栈 * @pre 栈 stack 存在 * @param stack 栈 * @return 出栈的元素 * @retval -1 出失败 */ char stack_pop( stackPtr stack ); /** @brief 判断栈是否为空 * @pre 栈 stack 存在 * @param stack 栈 * @retval true 为空 * @retval false 为空 */ bool stack_empty( stackPtr stack ); /** @brief 返回栈顶的元素而不是弹出 * @pre 栈 stack 存在 * @param stack * @return 栈顶元素 * @retval -1 操作失败 */ char stack_peek( stackPtr stack ); /** @brief 栈长度 * @pre 栈存在 * @param stack 栈 * @return 栈的长度 * @retval -1 操作失败 */ int stack_len( stackPtr stack ); /** @brief 栈数组扩容 * @pre 栈 stack 存在 * @param stack 要扩容的栈 */ void stack_expand( stackPtr stack ); #endif /* STACK_H_ */
#include<stdio.h> #include<stdlib.h> #include<stdbool.h> #include"stack.h" /** @brief 创建一个初始人的栈 * 其初始容量为16 * @return 初始化的栈 * @retval NULL 创建失败 */ stackPtr stack_init() { stackPtr stack = (stackPtr) malloc(sizeof(Stack)); if (NULL == stack) { puts("stack_init...NULL == stack 初始化栈失败"); return NULL; } stack->stack_size = 16; stack->top = -1; stack->elem = (char*) malloc(sizeof(char) * stack->stack_size); if (NULL == stack->elem) { puts("stack_init...NULL == stack->elem 初始化数组失败"); return NULL; } return stack; } /** @brief 压栈 * @pre 栈 stack 存在 * @param stack 栈 * @param elem 要入压孤元素 * @retval 0 入栈成功 * @retval 1 入栈失败 */ int stack_push(stackPtr stack, char elem) { if( NULL == stack ){ return -1; } if( stack->top >= stack->stack_size - 1 ){ stack_expand( stack ); } stack->top++; stack->elem[stack->top] = elem; return 0; } /** @brief 出栈 * @pre 栈 stack 存在 * @param stack 栈 * @return 出栈的元素 * @retval -1 出失败 */ char stack_pop(stackPtr stack) { char ch = stack_peek( stack ); stack->top--; return ch; } /** @brief 判断栈是否为空 * @pre 栈 stack 存在 * @param stack 栈 * @retval 1 为空 * @retval 0 为空 */ bool stack_empty(stackPtr stack) { if( -1 == stack->top ){ return true; }else{ return false; } } /** @brief 返回栈顶的元素而不是弹出 * @pre 栈 stack 存在 * @param stack * @return 栈顶元素 * @retval -1 操作失败 */ char stack_peek(stackPtr stack) { if( NULL == stack || stack_empty(stack)){ return -1; } return stack->elem[stack->top]; } /** @brief 栈长度 * @pre 栈存在 * @param stack 栈 * @return 栈的长度 * @retval -1 操作失败 */ int stack_len(stackPtr stack) { if ( NULL == stack) { return -1; } return stack->top + 1; } /** @brief 栈数组扩容 * @pre 栈 stack 存在 * @param stack 要扩容的栈 */ void stack_expand(stackPtr stack) { if( NULL == stack ){ return ; } stack->stack_size = stack->stack_size * 1.75; stack->elem = (char*)realloc( stack->elem, stack->stack_size); }
/** @file bolan.h * @brief 逆波兰计算声明 */ #ifndef BOLAN_H_ #define BOLAN_H_ /** @brief 根据给定的逆波兰表达式计算其结果 * @note 参数 bolan 必须是一个逆波兰表达式 * @param bolan 一个逆波兰表达式 * @return 计算结果 */ int exp_bolan_cal(char * bolan); /** @brief 两个数字计算 * * * @param a 操作数 * @param o 运算符 * @param b 操作数 * @return 计算结果 */ int cal(int a, char o, int b) ; /** @brief 将中缀表达式转化为后缀表达式 * * @param exp 中缀表达式字符串数组 * @return 转化后的后缀表达式 */ char * exp_bolan(char * exp); /** @brief 比较运算符的优先级 * * @param a * @param b * @return 比较结果 * @retval 1 a > b * @retval 0 a = b * @retval -1 a < b */ int exp_compare_opr(char a, char b); #endif /* BOLAN_H_ */
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<ctype.h> #include"stack.h" #include"bolan.h" /** @brief 根据给定的逆波兰表达式计算其结果 * @note 参数 bolan 必须是一个逆波兰表达式 * @param bolan 一个逆波兰表达式 * @return 计算结果 */ int exp_bolan_cal(char * bolan) { int len = strlen(bolan); int * calS = (int*)malloc(sizeof(int)*len); int n = 0; int i = 0; for (i = 0; i < len; i++) { if (isdigit(bolan[i])) { calS[n] = bolan[i] - '0'; n++; } else { n--; int a = calS[n]; n--; int b = calS[n]; int c = cal(b,bolan[i],a); // printf("a = %d,b = %d,c = %d\n",a,b,c); calS[n] = c; n++; } } return calS[n-1]; } /** * 两个数字计算 * * @param a 操作数 * @param o 运算符 * @param b 操作数 * @return 计算结果 */ int cal(int a, char o, int b) { int res = 0; switch (o) { case '+': { res = a + b; break; } case '-': { res = a - b; break; } case '*': { res = a * b; break; } case '/': { res = a / b; break; } } return res; } /** @brief 将中缀表达式转化为后缀表达式 * * @param exp 中缀表达式字符串数组 * @return 转化后的后缀表达式 */ char * exp_bolan(char * exp) { int len = strlen(exp); stackPtr stack = stack_init(); char * bolan = (char*) malloc(sizeof(char) * (len + 1)); int i = 0; int n = 0; stack_push(stack, '#'); for (i = 0; i < len; i++) { if (32 == exp[i]) { continue; } if ('0' <= exp[i] && exp[i] <= '9') { bolan[n] = exp[i]; n++; } else { char a = exp[i]; char b = stack_peek(stack); if (exp_compare_opr(a, b) > 0) { stack_push(stack, exp[i]); } else { while (exp_compare_opr(exp[i], stack_peek(stack)) <= 0) { char c = stack_pop(stack); bolan[n] = c; n++; } stack_push(stack, exp[i]); } } } while ('#' != stack_peek(stack)) { bolan[n] = stack_pop(stack); n++; } bolan[n] = '\0'; return bolan; } /** @brief 比较运算符的优先级 * * @param a * @param b * @return 比较结果 * @retval 1 a > b * @retval 0 a = b * @retval -1 a < b */ int exp_compare_opr(char a, char b) { if ('#' == b) { return 1; } int result = 0; switch (a) { case '+': case '-': { if ('*' == b || '/' == b) { result = -1; } break; } case '*': case '/': { if ('+' == b || '-' == b) { result = 1; } break; } } return result; }
OBJS=test.o stack.o bolan.o test:${OBJS} gcc -o test ${OBJS} test.o:test.c bolan.h gcc -c -Wall test.c stack.o:stack.c stack.h gcc -c -Wall stack.c bolan.o:bolan.c bolan.h stack.h gcc -c -Wall bolan.c .PHNOY:clean clean: rm ${OBJS} test
laolang@laolang-Lenovo-G470:~/code/gongda/eclipse/stack_test_two$ ll 总用量 1008 drwxrwxr-x 3 laolang laolang 4096 11月 9 22:03 ./ drwxrwxr-x 12 laolang laolang 4096 11月 9 16:12 ../ -rw-rw-r-- 1 laolang laolang 2467 11月 9 21:59 bolan.c -rw-rw-r-- 1 laolang laolang 866 11月 9 21:48 bolan.h -rw-rw-r-- 1 laolang laolang 10840 11月 9 16:12 .cproject drwxrwxr-x 2 laolang laolang 4096 11月 9 21:46 Debug/ -rw-rw-r-- 1 laolang laolang 245 11月 9 20:28 makefile -rw-rw-r-- 1 laolang laolang 766 11月 9 16:12 .project -rw-rw-r-- 1 laolang laolang 2190 11月 9 17:07 stack.c -rw-rw-r-- 1 laolang laolang 1569 11月 9 16:51 stack.h -rw-rw-r-- 1 laolang laolang 975580 11月 9 20:37 stack.h.gch -rw-rw-r-- 1 laolang laolang 307 11月 9 21:59 test.c laolang@laolang-Lenovo-G470:~/code/gongda/eclipse/stack_test_two$ make gcc -c -Wall test.c test.c: In function ‘main’: test.c:11:7: warning: unused variable ‘test1’ [-Wunused-variable] char test1[] = {"1+2"}; ^ gcc -c -Wall stack.c gcc -c -Wall bolan.c gcc -o test test.o stack.o bolan.o laolang@laolang-Lenovo-G470:~/code/gongda/eclipse/stack_test_two$ ./test c = -28 laolang@laolang-Lenovo-G470:~/code/gongda/eclipse/stack_test_two$