准大学生刚学c,用链栈写了个计算器,希望大家指正

// 思路:将常用的中缀表达式转化为逆波兰式(后缀表达式,即符号在两个数字后面,便于计算机识别)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

typedef struct _numstack
{
    double data;
    struct _numstack *pre;
} numStack; // 数字栈

typedef struct _opstack
{
    char ope;
    struct _opstack *pre;
} opStack; // 符号栈

typedef struct _head
{
    numStack *numTop;
    opStack *opTop;
    int i;
} Stack; // 指示栈顶和标记是否多位数

Stack *iniStack(Stack *p);         // 初始化栈
void pushNum(Stack *head, char a); // 将字符转化为数字,并压入数字栈
void pushOp(Stack *head, char op); // 将符号压入符号栈
double popNum(Stack *head);        // 将数字从数字栈弹出
char popOp(Stack *head);           // 将符号从符号栈弹出
void count(Stack *head);           // 计算
int isNum(char a);                 // 判断字符是数字还是符号
char compare(char a, char b);      // 比较符号优先度,返回'>''<''='

int main()
{
    printf("please input:\n");
    char ch[25];
    int i = 0;
    for (i = 0; i <= 25; i++)
    {
        ch[i] = '#';
    }
    fgets(ch, 25, stdin);

    Stack *head;
    head = iniStack(head);
    char e = '#';

    for (i = 0; i <= 25; i++)
    {
        if (isNum(ch[i]) == 1)
        {
            pushNum(head, ch[i]);
            head->i = 1;
        }
        else
        {
            head->i = 0;
            if (head->opTop == NULL)
            {
                pushOp(head, ch[i]);
            }
            else if (ch[i] == ')')
            {
                pushOp(head, ch[i]);
                count(head);
            }
            else
            {
                e = compare(ch[i], head->opTop->ope);
                if (e == '>')
                {
                    pushOp(head, ch[i]);
                }
                else if (e == '<')
                {
                    if (head->opTop->ope != '(')
                    {
                        count(head);
                    }
                    pushOp(head, ch[i]);
                    if (head->opTop->ope == '=')
                    {
                        printf("%.3f", head->numTop->data);
                        break;
                    }
                }
            }
        }
    }

    return 0;
}

int isNum(char a)
{
    if (a == '+' || a == '-' || a == '*' || a == '/' || a == '(' || a == ')' || a == '^' || a == '=')
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

Stack *iniStack(Stack *p)
{
    p = malloc(sizeof(Stack));
    p->numTop = NULL;
    p->opTop = NULL;
    p->i = 0;
}

void pushNum(Stack *head, char a)
{
    if (head->i != 1)
    {
        numStack *p = malloc(sizeof(numStack));
        if (!p)
        {
            printf("ERROR");
            exit(1);
        } // 以防内存满的保险处理
        p->pre = head->numTop;
        head->numTop = p;
        p->data = (int)(a - 48) / 1.0;
    }
    else
    {
        head->numTop->data *= 10;
        head->numTop->data += (int)(a - 48) / 1.0;
    }
}

void pushOp(Stack *head, char a)
{
    opStack *p = malloc(sizeof(opStack));
    if (!p)
    {
        printf("ERROR");
        exit(1);
    }
    p->pre = head->opTop;
    head->opTop = p;
    p->ope = a;
}

double popNum(Stack *head)
{
    double i = head->numTop->data;
    numStack *p = head->numTop;
    head->numTop = head->numTop->pre;
    free(p);
    return i;
}

char popOp(Stack *head)
{
    char i = head->opTop->ope;
    opStack *p = head->opTop;
    head->opTop = head->opTop->pre;
    free(p);
    return i;
}

char compare(char a, char b)
{
    char operator[] = { '+',
                        '-',
                        '*',
                        '/',
                        '^',
                        '(',
                        ')',
                        '=' };
    int x = 0, y = 0;
    char levelTable[8][8] = {
        {'>', '>', '<', '<', '<', '>', '>', '>'},
        {'>', '>', '<', '<', '<', '>', '>', '>'},
        {'>', '>', '>', '>', '<', '>', '>', '>'},
        {'>', '>', '>', '>', '<', '>', '>', '>'},
        {'>', '>', '>', '>', '>', '>', '>', '>'},
        {'>', '>', '>', '>', '>', '>', ' ', '>'},
        {'<', '<', '<', '<', '<', ' ', '<', '>'},
        {'<', '<', '<', '<', '<', '<', '<', '<'}}; // 制作二维数组,将两个符号坐标化再判断优先度
    for (x = 0; x < 8; x++)
    {
        if (operator[x] == a)
        {
            break;
        }
    }
    for (y = 0; y < 8; y++)
    {
        if (operator[y] == b)
        {
            break;
        }
    }
    return levelTable[x][y];
}

void count(Stack *head)
{
    char op = '#';
    double down, up, sum;
    numStack *p = NULL;
    int i = 0;
    if (head->opTop->ope == ')')
    {
        i = 1;
    } // 如果从反括号开始运算,就是要把整个括号算完,即头括号也要删去,故做一标记i
    while (head->numTop->pre != NULL)
    {
        if (head->opTop->ope == '(')
        {
            break;
        }
        op = popOp(head);
        if (op != '(' && op != ')')
        {
            b = head->numTop->data;
            p = head->numTop;
            head->numTop = head->numTop->pre;
            free(p);
            a = head->numTop->data;
            switch (op)
            {
            case '+':
                sum = a + b;
                break;
            case '-':
                sum = a - b;
                break;
            case '*':
                sum = a * b;
                break;
            case '/':
                sum = a / b;
                break;
            case '^':
                sum = pow(a, b);
                break;
            }
            head->numTop->data = sum;
        }
    }
    if (i == 1)
    {
        op = popOp(head);
    } // 运算结束后,head->opTop恰好指在头括号处
}

自我感觉写的很烂,

参考文章数据结构-C描述-堆栈-简单计算器_c语言使用堆栈写简单计算器编程代码-CSDN博客

还有这个码龄居然是按照注册年份算的。。。。

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我来为您介绍一下如何使用链栈实现简易计算器。 首先,我们需要定义一个链栈的结构体,包括数据域和指针域: ``` struct Node { double data; Node* next; }; ``` 然后,我们需要定义一些基本的操作,如入栈、出栈、获取栈顶元素等: ``` void push(Node*& top, double data) { Node* newNode = new Node; newNode->data = data; newNode->next = top; top = newNode; } double pop(Node*& top) { if (top == nullptr) { throw "Stack is empty!"; } double data = top->data; Node* temp = top; top = top->next; delete temp; return data; } double peek(Node* top) { if (top == nullptr) { throw "Stack is empty!"; } return top->data; } ``` 接下来,我们可以利用这些基本操作来实现一个简易计算器。具体实现方法如下: 1. 读入一个表达式,将其中的数字和运算符分别入栈。 2. 当遇到一个运算符时,弹出栈顶的两个数字进行计算,并将结果入栈。 3. 重复步骤2,直到表达式中的所有运算符都被处理完毕。 4. 最终栈中剩下的数字就是表达式的计算结果。 下面是一个示例代码: ``` double calculate(string expression) { Node* stack = nullptr; for (int i = 0; i < expression.length(); i++) { if (isdigit(expression[i])) { double num = 0; while (i < expression.length() && isdigit(expression[i])) { num = num * 10 + (expression[i] - '0'); i++; } push(stack, num); i--; } else if (expression[i] == '+' || expression[i] == '-' || expression[i] == '*' || expression[i] == '/') { double num1 = pop(stack); double num2 = pop(stack); switch (expression[i]) { case '+': push(stack, num2 + num1); break; case '-': push(stack, num2 - num1); break; case '*': push(stack, num2 * num1); break; case '/': push(stack, num2 / num1); break; } } } double result = pop(stack); if (stack != nullptr) { throw "Invalid expression!"; } return result; } ``` 这样,我们就实现了一个简易的计算器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值