进制转换

栈先进后出的特性刚好符合十进制转二进制的方法:

#include <stdio.h>
#include <stdbool.h>

#define OK      true
#define ERROR   false
typedef bool STATUS;
#define MAX_SIZE    100
typedef char Elem_Type;
#define SYS     2 // 进制

typedef struct SQ_Stack
{
    Elem_Type data[MAX_SIZE];
    int top;
} SQ_Stack;

SQ_Stack stack;

STATUS init_stack(SQ_Stack *s)
{
    s->top = -1;
    return OK;
}

STATUS pop(SQ_Stack *s, Elem_Type *e)
{
    if(s->top <= -1)
        return ERROR;

    *e = s->data[s->top];
    (s->top)--;
    return OK;
}

STATUS push(SQ_Stack *s, Elem_Type e)
{
    if(s->top >= (MAX_SIZE - 1))
        return ERROR;

    (s->top)++;
    s->data[s->top] = e;
    return OK;
}

int main()
{
    int num = 0;
    Elem_Type temp;

    printf("decimal numeral(num > 0): ");
    scanf("%d",&num);
    init_stack(&stack);
    while(num != 0)
    {
        push(&stack, (num % SYS) + '0');
        num /= SYS;
    }
    /* 打印结果 */
    printf("binary number: ");
    while(pop(&stack, &temp))
    {
        printf("%c",temp);
    }
}

RPN(逆波兰)计算

早期计算机无法计算复杂的算式(对我们来说很简单),因此有了逆波兰计算:首先是中缀表达式转化为后缀表达式,然后计算机通过后缀表达式计算结果。

例:1+2*3-->123*+(1+2)*3-->12+3*

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define OK      true
#define ERROR   false
typedef bool STATUS;
typedef float Elem_Type;
#define INPUT_MAX_SIZE  100

typedef struct Node
{
    Elem_Type data;
    struct Node *prior;
}Node;

typedef struct CH_Stack
{
    Node *top;
    int size;
} CH_Stack;

CH_Stack stack;

STATUS init_stack(CH_Stack *s)
{
    s->top = NULL;
    s->size = 0;
    return OK;
}

bool stack_is_empty(CH_Stack s)
{
    if(s.size == 0)
        return true;
    return false;
}

STATUS pop(CH_Stack *s, Elem_Type *e)
{
    if(s->size <= 0)
        return ERROR;

    Node *temp = s->top;
    *e = temp->data;
    s->top = s->top->prior;
    (s->size)--;
    free(temp);
    return OK;
}

STATUS push(CH_Stack *s, Elem_Type e)
{
    Node *temp = NULL;
    if(!(temp = (Node *)malloc(sizeof(Node))))
        return ERROR;

    temp->data = e;
    temp->prior = s->top;
    s->top = temp;
    (s->size)++;
    return OK;
}

/*****************************************************************************
 * @brief 中缀转后缀
 * 
 * @param in 中缀表达式
 * @param ch 后缀表达式
 * @return STATUS 
 ****************************************************************************/
STATUS change(char in[], char ch[])
{
    int cur_i = 0;
    int cur_c = 0;
    Elem_Type temp = 0;
    while(in[cur_i] != '\0')
    {
        if(in[cur_i] == '.' || ('0' <= in[cur_i] && in[cur_i] <= '9'))
        {
            ch[cur_c++] = in[cur_i];
            cur_i++;
            if(!(in[cur_i] == '.' || ('0' <= in[cur_i] && in[cur_i] <= '9')))
                ch[cur_c++] = '#'; // 数字间隔
        }
        else if(in[cur_i] == '*' || in[cur_i] == '/' || in[cur_i] == '(')
        {
            push(&stack, in[cur_i]);
            cur_i++;
        }
        else if(in[cur_i] == '+' || in[cur_i] == '-')
        {
            pop(&stack, &temp);
            if((char)temp == '*' || (char)temp == '/') // 优先级
            {
                ch[cur_c++] = (char)temp;
            }
            else
            {
                push(&stack, temp);
            }
            push(&stack, in[cur_i]);
            cur_i++;
        }
        else if(in[cur_i] == ')')
        {
            pop(&stack, &temp);
            while((char)temp != '(')
            {
                ch[cur_c++] = (char)temp;
                pop(&stack, &temp);
            }
            cur_i++;
        }
        else
        {
            return ERROR;
        }
    }
    /* 清空栈 */
    while(pop(&stack, &temp))
    {
        ch[cur_c++] = (char)temp;
    }
    ch[cur_c] = '\0';
    return OK;
}

/*****************************************************************************
 * @brief 后缀表达式计算
 * 
 * @param ch 后缀表达式
 * @return STATUS 
 ****************************************************************************/
STATUS compute(char ch[])
{
    int cur = 0;
    char n[INPUT_MAX_SIZE];
    int cur_n = 0;
    Elem_Type temp = 0;
    Elem_Type n1 = 0;
    Elem_Type n2 = 0;
    while(ch[cur] != '\0')
    {
        /* 字符串转数字 */
        while (ch[cur] == '.' || ('0' <= ch[cur] && ch[cur] <= '9'))
        {
            n[cur_n++] = ch[cur++];
        }
        n[cur_n] = '\0';
        temp = strtof(n,NULL);
        cur_n = 0;
        /* 计算 */
        switch(ch[cur])
        {
            case '+' :
                pop(&stack, &n1);
                pop(&stack, &n2);
                push(&stack, n2 + n1);
                break;
            case '-' :
                pop(&stack, &n1);
                pop(&stack, &n2);
                push(&stack, n2 - n1);
                break;
            case '*' :
                pop(&stack, &n1);
                pop(&stack, &n2);
                push(&stack, n2 * n1);
                break;
            case '/' :
                pop(&stack, &n1);
                pop(&stack, &n2);
                push(&stack, n2 / n1);
                break;
            case '#' :
                push(&stack, temp);
                temp = 0;
                break;
        }
        cur++;
    }
    pop(&stack,&temp);
    printf("%.2f\n",temp);
    return OK;
}

int main()
{
    char in[INPUT_MAX_SIZE] = "";
    char ch[INPUT_MAX_SIZE * 2] = "";

    printf("What do you want to compute:\n");
    scanf("%s",&in);

    if(!change(in, ch))
        printf("CHANGE ERROR!\n");
    printf("postfix expression : %s\n",ch);

    if(!compute(ch))
        printf("COMPUTE ERROR!\n");
    return 0;
}

测试集:
1)in:8   out:8
2)in:10+20   out:10#20#+
3)in:5+20*3   out:5#20#3#*+
4)in:80/5-10   out:80#5#/10#-
5)in:6-(23+4)*(40-25)   out:6#23#4#+40#25#-*-
6)in:50/8-(60/2-3*(40-25))   out:50#8#/60#2#/3#40#25#-*--