test 2.1任务描述本关任务:编写一个能计算表达式值的小程序。

任务描述

本关任务:编写一个能计算表达式值的小程序。

相关知识

为了完成本关任务,你需要掌握:1.栈的封装,2.字符串的遍历,3,表达式求值的原理。

测试说明

平台会对你编写的代码进行测试:

输入由1行组成,包含表达式字符串 预期输出:表达式的值,3位小数

测试输入:3+2*5 预期输出:13.000

涉及浮点数,负数,以及数的n次幂。

#include <stdio.h>
#include <stdlib.h>
#include<math.h>
#include<string.h>
//创建字符栈
typedef struct Node {
    int data;
    struct Node* next;
} Node;
typedef struct Stack {
    Node* top;
} Stack;

//创建数字栈(所有有关数字的出栈入栈等操作我都只是在前面加了一个n,表示数字....有点懒得打复杂的英文)
typedef struct nNode {
    double data;
    struct nNode* next;
} nNode;
typedef struct nStack {
    nNode* top;
} nStack;

//判断是否是操作符,后面对遍历表达式有用
int is_operator(char ch) {
    return (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '^');
}

//如果是操作符,给各个操作符一个返回值,用来比较操作符的优先等级
int priority(char op) {
    switch (op) {
    case '+':
    case '-':
        return 1;
    case '*':
    case '/':
        return 2;
    case '^':
        return 3;
    default:
        return 0;
    }
}
 
//对弹出的两个数计算
double calculate(double a, char op, double b) {
    switch (op) {
    case '+':
        return a + b;
    case '-':
        return a - b;
    case '*':
        return a * b;
    case '/':
        return a / b;
    case '^':
        return pow(a, b);
    default:
        exit(1);
    }
}

Stack* create_stack() {   // 创建空栈
    Stack* stack = (Stack*)malloc(sizeof(Stack));
    stack->top = NULL;
    return stack;
}
nStack* ncreate_stack() {   // 创建空栈n
    nStack* nstack = (nStack*)malloc(sizeof(nStack));
    nstack->top = NULL;
    return nstack;
}

void push(Stack* stack, int data) {   // 入栈操作
    Node* node = (Node*)malloc(sizeof(Node));
    node->data = data;
    node->next = stack->top;
    stack->top = node;
}
//前面有n的都是对数字进行的操作,别看岔看重复了
void npush(nStack* stack, double data) {   // 入栈操作n
    nNode* nnode = (nNode*)malloc(sizeof(nNode));
    nnode->data = data;
    nnode->next = stack->top;
    stack->top = nnode;
}
int pop(Stack* stack) {   // 出栈操作
    if (stack->top == NULL) {
        return -1;   // 如果栈为空,则返回-1
    }
    Node* node = stack->top;
    int data = node->data;
    stack->top = node->next;
    free(node);
    return data;
}
double npop(nStack* stack) {   // 出栈操作n
    if (stack->top == NULL) {
        return -1;   // 如果栈为空,则返回-1
    }
    nNode* node = stack->top;
    double data = node->data;
    stack->top = node->next;
    free(node);
    return data;
}
int top(Stack* stack) {   // 返回栈顶元素
    if (stack->top == NULL) {
        return -1;   // 如果栈为空,则返回-1
    }
    return stack->top->data;
}
double ntop(nStack* stack) {   // 返回栈顶元素n
    if (stack->top == NULL) {
        return -1;   // 如果栈为空,则返回-1
    }
    return stack->top->data;
}

//开始读取表达式expression,并且计算
double evaluate_expression(char* expression) {
    nStack* s1 = ncreate_stack();   // 操作数栈,用于存储操作数
    Stack* s2 = create_stack();   // 操作符栈,用于存储操作符
    char n[10];//考虑到有浮点数的存在,需要建立一个char[]来存放浮点数的各个数字和小数点,然后调用atof函数可以转换为浮点数,之后入栈。
    double num;//调用atof函数后用来存放浮点数。
    int len = strlen(expression);
    for (int i = 0, j = 0; i < len; i++) {
        if (i == 0 && expression[i] == '-') {//第一个数字为负数时,也将第一个负号存放在n[]里,atof会转化为负数.
            n[j] = expression[i];
            j++;i++;
        }
        if ((expression[i] >= '0' && expression[i] <= '9') || expression[i] == '.') {// 如果当前字符为数字
            n[j] = expression[i];
            j++;
            if (i == len - 1 || !(expression[i + 1] >= '0' && expression[i + 1] <= '9' || expression[i + 1] == '.')) {//一直读取到后面的数不是数字时
                num = atof(n);
                npush(s1, num);
                for (int k = 0;k < j;k++) {
                    n[k] = 0;
                }
                j = 0;
            }
        }
        else   if (is_operator(expression[i])) {   // 如果当前字符为操作符
            while (s2->top != NULL && priority(top(s2)) >= priority(expression[i])) {
                // 如果操作符栈不为空,并且栈顶操作符的优先级大于等于当前操作符的优先级
                double b = npop(s1);    // 出栈一个操作数作为运算的右操作数
                double a = npop(s1);    // 再出栈一个操作数作为运算的左操作数
                char op = pop(s2);  // 出栈一个操作符
                double result = calculate(a, op, b);   // 计算两个操作数和操作符的结果
                npush(s1, result);   // 将计算结果入栈到操作数栈中
            }
            push(s2, expression[i]);  // 当前操作符入栈到操作符栈中
        }
        else if (expression[i] == '(') { // 如果当前字符为左括号
            push(s2, expression[i]);    // 入栈到操作符栈中
        }
        else if (expression[i] == ')') { // 如果当前字符为右括号
            while (top(s2) != '(') {    // 循环执行直到遇到左括号
                double b = npop(s1);    // 出栈一个操作数作为运算的右操作数
                double a = npop(s1);    // 再出栈一个操作数作为运算的左操作数
                char op = pop(s2);  // 出栈一个操作符
                double result = calculate(a, op, b);   // 计算两个操作数和操作符的结果
                npush(s1, result);   // 将计算结果入栈到操作数栈中
            }
            pop(s2);    // 弹出左括号
        }
    }
    // 处理剩余的操作符
    while (s2->top != NULL) {
        double b = npop(s1);    // 出栈一个操作数作为运算的右操作数
        double a = npop(s1);    // 再出栈一个操作数作为运算的左操作数
        char op = pop(s2);  // 出栈一个操作符
        double result = calculate(a, op, b);   // 计算两个操作数和操作符的结果
        npush(s1, result);   // 将计算结果入栈到操作数栈中
    }
    return npop(s1); // 返回最终的计算结果
}
int main() {
    char expression[100];
    scanf("%s", expression);
    double result = evaluate_expression(expression);
    printf("%.3f\n", result);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值