C语言实现加减乘除的括号计算器

文章介绍了如何使用C语言实现后缀表达式的求值,利用栈来处理运算符和数字,根据运算符优先级进行计算,最终得到结果。
摘要由CSDN通过智能技术生成

#include<stdbool.h>
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<strings.h>
#include<stdlib.h>
#ifndef stack_h 
#define stack_h
#include <stddef.h> // for size_t

typedef char ele;//栈的类型 

// 定义栈结构体,包含栈顶指针、容量和当前元素数量等信息
typedef struct {
    ele* data;     // 栈内存储数据的数组
    size_t capacity; // 栈的总容量
    size_t count;   // 当前栈内元素数量
}zhan;
// 初始化栈,分配指定容量的内存空间
zhan space(size_t capacity) {
    zhan stack = {0};
    stack.capacity = capacity;
    stack.data = malloc(capacity * sizeof(*stack.data));
    return stack;
}
// 压一个元素进栈
void in(zhan* stack, ele element) {
    stack->data[stack->count++] = element;
}
// 判断栈是否为空
int iskong(const zhan* stack) {
    return stack->count == 0;
}
// 从栈中弹出一个元素
ele out(zhan* stack) {
    // 保存即将弹出的栈顶元素的值
    char top_element = stack->data[stack->count - 1];
    // 弹出操作:减少计数并将栈顶元素置为 '\0'
    stack->data[--stack->count] = '\0';
    // 返回栈顶元素的原值
    return top_element;
}
// 获取栈顶元素(但不弹出)
ele gettop(const zhan* stack) {
    return stack->data[stack->count - 1];
}
#endif // stack_h
char s[100];
int cmp(char a, char b){
    // 定义运算符优先级映射表
    const int priority[] = {
        ['+'] = 1,
        ['-'] = 1,
        ['*'] = 2,
        ['/'] = 2,
    };
    // 比较优先级值
    if(priority[a] >= priority[b]){
        return 1;
    }
    else{
        return 0;
    }
}
double cal(double a, double b, char c) {
    switch (c) {
        case '+':
            return a + b;
        case '-':
            return a - b;
        case '*':
            return a * b;
        case '/':
            return a / b;
    }
}
int main(){
    while(1){//循环 
    char tmpa;
    int n=0;

    while(scanf("%c",&tmpa)){
        if(tmpa=='='){
            s[n]='=';
            goto next;
        }
        if(tmpa!=' '){
            s[n]=tmpa;
            n++;
        }
    }
    next:;
    s[n+1]='\0';
    int a[100];//储存数字 
    char b[100];//储存运算符 
    int num_count = 0;
    int op_count = 0;

    for (int i = 0; s[i] != '\0'; ++i) {
        if (isdigit(s[i])) { // 遇到数字
            int j = i;
            while (isdigit(s[j]) && j < sizeof(s) - 1) { // 扩展到整个数字
                ++j;
            }
            char num_str[j - i + 1];
            strncpy(num_str, &s[i], j - i);
            num_str[j - i] = '\0';
            a[num_count++] = atoi(num_str); // 将数字字符串转换为整数并存入数组
            i = j - 1; // 跳过已处理的数字字符
        } else{ // 遇到运算符
            a[num_count++] = -1; // 在a数组中用-1标记运算符位置
            b[op_count++] = s[i]; // 存储运算符到数组
        }
    }
    a[num_count]=-2;
    //现在已经完成输入,开始改变为后缀运算式
    zhan op=space(100);//操作栈 
    int abac[100];
    char bbac[100];
    int bbac1=0,abac1=0;
    char rubbish;//你不会再用到我的 
    int j=0,bcnt=0;
    while(a[j]!=-2){
        if(a[j]!=-1){
            abac[abac1++]=a[j];//数字进入 
            j++;
        }
        else{
            if(b[bcnt]!=')'){//不是右括号,判断优先级,栈内如果大出栈,直到小或空,栈内小则入栈 
                if(iskong(&op)!=0){//空栈,直接进入 
                    in(&op,b[bcnt++]);//录入当前操作到栈 ,注意这里不用标记 
                    j++;
                    goto again;
                }else{
                    if(b[bcnt]=='('){//左括号,直接进入 
                        in(&op,b[bcnt++]);//录入当前操作到栈 ,注意这里不用标记 
                        j++;
                        goto again;
                    }        
                     else{
                         top:
                        if(cmp(gettop(&op),b[bcnt])>0&&iskong(&op)==0){//栈内优先,出栈(不为空)
                            bbac[bbac1++]=out(&op);//弹出到字符串 
                            abac[abac1++]=-1;//标记运算符 
                            if(iskong(&op)>0||cmp(gettop(&op),b[bcnt])==0){
                                goto fuck;//空栈或优先级高,录入 
                            }
                            goto top;//循环 
                        }
                        fuck:;
                        in(&op,b[bcnt++]);//录入当前操作到栈 ,注意这里不用标记 
                        j++;
                        goto again;
                    }
                        
                }
            }
            else{//右括号,弹出,直到左括号 
                bcnt++; 
                while(gettop(&op)!='('){
                    bbac[bbac1++]=out(&op);//弹出到字符串 
                    abac[abac1++]=-1;//标记运算符 
                }
                rubbish=out(&op);//销毁栈中括号 
                j++;
                goto again;
            }
        }
        again:;
    }
    while(iskong(&op)==0){//栈没清干净
        if(gettop(&op)!='('&&gettop(&op)!='='){
            bbac[bbac1++]=out(&op);//弹出到字符串 
            abac[abac1++]=-1;//标记运算符
        }
        else{
            rubbish=out(&op);
        }
    }//这之后所有的后缀数据记录在了abac和bbac中

    abac[abac1]=-2;//总得有个结尾吧 
    double tmp1,tmp2;
    double num[1000];
    int i=0,num1=0;
    bbac1=0;
    while(abac[i]!=-2){
        if(abac[i]!=-1){
            num[num1]=(double)abac[i];//入栈 
            num1++;
            i++;
        }
        else{
            tmp2=num[num1-1];
            num1--;
            tmp1=num[num1-1];
            num1--;//最上面两个出栈 
            num[num1]=cal(tmp1,tmp2,bbac[bbac1]);//计算,结果储存到栈中 
            i++;
            bbac1++;
            num1++;
        }
    }
    printf("%.2lf\n\n",num[0]);//最后栈中只剩下一个结果数据 
            }//循环 
    return 0;
}

//主要使用后缀表达式原理
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值