计算器 1.0版

项目描述:

1.0版:

功能:控制台实现中缀表达式的求值

作者:小代码:

时间:2014年 11月 09日 星期日 21:58:13 CST

C语言版:

test.c://测试入口

#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;
}


stack.h//字符栈

此文件声明了栈的基本操作,模仿自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_ */


stack.c//栈实现

#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);
}


bolan.h//逆波兰算法的声明

/** @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_ */


bolan.c//逆波兰算法的实现

#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;
}


makefile

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$





你可能感兴趣的:(计算器 1.0版)