实现一个表达式求值的工具(类似计算器,但是接受变量赋值)

使用c语言(最好是c语言,c++可以接受,只接受这两种语言),编写一个表达式求值工具,接受两种输入形式:
例如
1,a = 233, b = 1,a + b
或者a = 233,a + 1
2,1 + 1
输出结果为赋值计算表达式的值,计算限定在四则运算的浮点数计算,变量名不局限于a, b 上述只是举例说明,变量由用户输入
(可联系我私发具体操作要求)

C++可以吗

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX_TOKEN_LENGTH 100

typedef enum {
    NUMBER,
    OPERATOR,
    VARIABLE,
    UNKNOWN
} TokenType;

typedef struct {
    TokenType type;
    double value;
    char name[MAX_TOKEN_LENGTH];
} Token;

double variables[26]; // 变量数组,支持小写字母的变量

int get_token(char* str, Token* token) {
    int i = 0;

    // 忽略空格
    while (isspace(str[i])) {
        i++;
    }

    // 如果是数字,读取数字
    if (isdigit(str[i]) || str[i] == '.') {
        token->type = NUMBER;
        token->value = atof(str + i);
        while (isdigit(str[i]) || str[i] == '.') {
            i++;
        }
        return i;
    }

    // 如果是变量,读取变量
    if (isalpha(str[i])) {
        token->type = VARIABLE;
        int j = 0;
        while (isalpha(str[i])) {
            token->name[j++] = str[i++];
        }
        token->name[j] = '\0';
        return i;
    }

    // 如果是操作符,读取操作符
    if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/') {
        token->type = OPERATOR;
        token->name[0] = str[i];
        token->name[1] = '\0';
        return 1;
    }

    token->type = UNKNOWN;
    return 0;
}

double eval(char* str) {
    Token tokens[MAX_TOKEN_LENGTH];
    int num_tokens = 0;

    // 将字符串分解为单独的令牌
    int i = 0;
    while (str[i] != '\0') {
        int length = get_token(str + i, &tokens[num_tokens]);
        i += length;
        num_tokens++;
    }

    // 如果第一个令牌是赋值运算符,将它替换为等号和变量名,并将变量名和变量值保存到变量数组中。
    int j = 0;
    while (j < num_tokens) {
        if (tokens[j].type == VARIABLE && tokens[j + 1].type == OPERATOR && tokens[j + 1].name[0] == '=') {
            variables[tokens[j].name[0] - 'a'] = eval(str + i + 2);
            j += 3;
        } else {
            j++;
        }
    }
    double stack[MAX_TOKEN_LENGTH];
    int stack_pos = 0;

    for (int i = 0; i < num_tokens; i++) {
        if (tokens[i].type == NUMBER) {
            stack[stack_pos++] = tokens[i].value;
        } else if (tokens[i].type == VARIABLE) {
            stack[stack_pos++] = variables[tokens[i].name[0] - 'a'];
        } else if (tokens[i].type == OPERATOR) {
            double right = stack[--stack_pos];
            double left = stack[--stack_pos];
            if (tokens[i].name[0] == '+') {
                stack[stack_pos++] = left + right;
            } else if (tokens[i].name[0] == '-') {
                stack[stack_pos++] = left - right;
            } else if (tokens[i].name[0] == '*') {
                stack[stack_pos++] = left * right;
            } else if (tokens[i].name[0] == '/') {
                stack[stack_pos++] = left / right;
            }
        }
    }

    return stack[0];
}

int main() {
    printf("%f\n", eval("a = 233, b = 1, a + b"));
    printf("%f\n", eval("a = 233, a + 1"));
    printf("%f\n", eval("1 + 1"));
    return 0;
}

望采纳

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

// 定义变量的结构体
typedef struct
{
  char name[32];  // 变量名
  double value;   // 变量值
} variable_t;

// 定义节点的结构体
typedef struct node
{
  double value;   // 节点的值
  char op;        // 节点的操作符
  struct node *left;   // 左子节点
  struct node *right;  // 右子节点
} node_t;

// 获取变量的值
double get_variable(char *name, variable_t *variables, int num_variables)
{
  for (int i = 0; i < num_variables; i++)
  {
    if (strcmp(name, variables[i].name) == 0)
    {
      return variables[i].value;
    }
  }

  // 如果变量不存在,返回 0
  return 0;
}

// 解析表达式的节点
node_t *parse_node(char *expression, variable_t *variables, int num_variables)
{
    node_t *node = malloc(sizeof(node_t));
    memset(node, 0, sizeof(node_t));
    
    // 如果表达式的第一个字符是数字,则表示节点的值为该数字
    if (expression[0] >= '0' && expression[0] <= '9')
    {
        sscanf(expression, "%lf", &node->value);
    }
    else
    {
        // 如果表达式的第一个字符是字母,则表示节点的值为变量的值
        char name[32];
        sscanf(expression, "%[a-zA-Z]", name);
        node->value = get_variable(name, variables, num_variables);
    }
    
    // 如果表达式中包含操作符,则解析出节点的操作符和左、右子节点
    for (int i = 0; i < strlen(expression); i++)
    {
        char c = expression[i];
        if (c == '+' || c == '-' || c == '*' || c == '/' || c == '^')
        {
            node->op = c;
            char *left_expression = strndup(expression, i);
            node->left = parse_node(left_expression, variables, num_variables);
            free(left_expression);
            char *right_expression = strdup(expression + i + 1);
            node->right = parse_node(right_expression, variables, num_variables);
            free(right_expression);
            break;
        }
    }
    
    return node;
}

// 计算表达式的节点的值
double eval_node(node_t *node)
{
    double result = node->value;

    // 如果节点存在操作符,则计算左、右子节点的值
    if (node->op)
    {
        double left_value = eval_node(node->left);
        double right_value = eval_node(node->right);
        switch (node->op)
        {
            case '+':
                result = left_value + right_value;
                break;
            case '-':
                result = left_value - right_value;
                break;
            case '*':
                result = left_value * right_value;
                break;
            case '/':
                result = left_value / right_value;
                break;
            case '^':
                result = pow(left_value, right_value);
                break;
        }
    }

    return result;
}

// 解析表达式并计算结果
double eval_expression(char *expression, variable_t *variables, int num_variables)
{
    node_t *node = parse_node(expression, variables, num_variables);
    double result = eval_node(node);
    free(node);
    return result;
}

int main(int argc, char **argv)
{
    // 定义变量
    variable_t variables[] = {
        { "a", 233 },
        { "b", 1 },
    };
    int num_variables = sizeof(variables) / sizeof(variables[0]);

    // 解析表达式 "a = 233, b = 1, a + b"
    char *expression = "a = 233, b = 1, a + b";
    double result = eval_expression(expression, variables, num_variables);
    printf("%s = %f\n", expression, result);

    // 解析表达式 "a = 233, a + 1"
    expression = "a = 233, a + 1";
    result = eval_expression(expression, variables, num_variables);
    printf("%s = %f\n", expression, result);

    // 解析表达式 "1 + 1"
    expression = "1 + 1";
    result = eval_expression(expression, variables, num_variables);
    printf("%s = %f\n", expression, result);
    
    return 0;
}

该代码使用递归的方式解析表达式,首先将表达式转换为节点的树形结构,然后递归计算每个节点的值,最终输出表达式的结果。

该代码支持两种输入形式:

  • a = 233, b = 1, a + b
  • a = 233, a + 1

它还支持四则运算的浮点数计算,例如输入表达式 "1 + 1" 将会输出结果 2.0。

提供参考实例【C语言之四则运算表达式求值(链栈)—支持浮点型数据,负数, 整型数据运算】,链接:https://www.cnblogs.com/Jony-2018/p/11872280.html?ivk_sa=1024320u


#include<stdio.h>
#include<string.h>
#include<stdlib.h>
 
 
#define N 1000+10
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define OK 1
#define OVERFLOW 0
#define ERROR 0
 
char str[N];
typedef  int Status;
typedef  int SElemType;
 
typedef struct{
    SElemType *base;
    SElemType *top;
    int stacksize;
}SqStack;
 
unsigned char prior[7][7] = {
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=',' '},
{'<','<','<','<','<',' ','>'},
{'<','<','<','<','<',' ','='}};
 
char OPSET[7] = {'+','-','*','/','(',')','#'};
 
Status InitStack(SqStack *s)//初始化栈 
{
    s->base = (SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
    if(!s->base)
        exit(OVERFLOW);
    s->top = s->base ;
    s->stacksize = STACK_INIT_SIZE;
    return OK;
}
 
Status Push(SqStack *s,SElemType c)//入栈 
{
    if((s->top - s->base ) >= s->stacksize )
    {
        s->base = (SElemType*)realloc(s->base ,(s->stacksize +STACKINCREMENT)*sizeof(SElemType));
        if(!s->base )
            exit(OVERFLOW);
        s->stacksize += STACKINCREMENT;
    }
    *(s->top)++ = c;
    return OK;
}
 
Status GetTop(SqStack *s)//取栈顶元素 
{
    SElemType e;
    if(s->base == s->top )
        return ERROR;
    e = *(s->top-1)    ;
    return e;
}
 
Status In(char c,char str[])//判断是否为运算符 
{
    int i = 0;
    while(c != str[i])
    {
        i++;
    }
    if(i < 7)
        return OK;
    return ERROR;
}
 
void  Strcat(char *str1,char *str2)//字符串连接函数,把字符串str2连接到str1后 
{
    int i = 0, j = 0;
    while(str1[i]!='\0')
    {
        i++;
    }
    while(str2[j]!='\0')
    {
        str1[i++] = str2[j++];
    }
    str1[i] = '\0';
} 
 
Status Atoi(char *c)//把字符串转为数字 
{
    int data= 0,d = 0;
    int i = 0;
    while(c[i]!='\0')
    {
        data = data*10 + c[i]-'0';
        i++;
    }
    return data;    
} 
 
Status precede(int a,char b)//判断优先级函数 
{
    int i = 0,j = 0;
    while(OPSET[i] != a)
    {
        i++;
    }
    while(OPSET[j] != b)
    {
        j++;
    }
    return prior[i][j];
}
 
Status Pop(SqStack *s)//脱括号函数 
{
    int e;
    if(s->base == s->top )
        return ERROR;
    e = *--(s->top);
    return e;
}
 
Status Opereta(int a,int b,int c)//运算函数 
{
    switch(b)
    {
        case '+':
            return a+c;
        case '-':
            return a-c;
        case '*':
            return a*c;
        case '/':
            return a/c;
    } 
}
 
int EvaluateExpression(char *MyExpression)//算法3.4 
{//算术表达式求值的算符优先算法。
//设OPTR和OPND分别为运算符栈和运算数栈
    SqStack OPTR;//运算符栈,字符元素 
    SqStack OPND;//运算数栈,实数元素 
    
    char TempData[20];
    int data,a,b;
    char *c,Dr[2],e;
    int theta;
    
    InitStack(&OPTR);
    Push(&OPTR,'#');
    InitStack(&OPND);
    
    c = MyExpression;
    TempData[0] = '\0';
    while(*c != '#'|| GetTop(&OPTR) != '#')
    {
        
        if(!In(*c,OPSET))//不是运算符则进栈 
        {
            Dr[0] = *c;
            Dr[1] = '\0';
            Strcat(TempData,Dr);
            c++; 
            if(In(*c,OPSET))//是运算符时 
            {
                data = Atoi(TempData);
                Push(&OPND,data);
                TempData[0] = '\0';
            }
        }
        else
        {
            switch(precede(GetTop(&OPTR),*c))
            {
                case '<':
                    Push(&OPTR,*c);
                    c++;
                    break;
                case '=':
                    Pop(&OPTR);
                    
                    c++;
                    break;
                case '>':
                    a = Pop(&OPND);
                    b = Pop(&OPND);
                    theta = Pop(&OPTR);
                    Push(&OPND,Opereta(b,theta,a));
                    break;
            }
        }
    }
    
    return GetTop(&OPND);
}
int main()
{
    
    while(scanf("%s",str)!=EOF)
    {
        printf("%d\n",EvaluateExpression(str));
    }
    return 0;
 }