表达式求值程序多位数/浮点数入栈故障排查求助
问题分析与修复方案
你当前的代码无法处理多位数整数和浮点数,核心问题集中在Token结构冗余、栈存储类型混乱、数字解析逻辑缺失浮点数支持,以及中缀转后缀时错误拆分数字这几点。以下是针对性的修复步骤:
1. 重构Token结构,统一数字存储
把冗余的value(int)和value1(double)合并为单个double num,用统一类型存储所有数字(整数/浮点数),同时明确Token类型:
typedef struct token{ int type; // 标记类型:T_NUMBER、T_PLUS、T_MINUS、T_TRIG等 double num; // 存储数字(整数/浮点数通用) int trig_type; // 三角函数类型(如1=sin,2=cos) int precedence; // 运算符优先级 struct token *next; } Token;
2. 修复栈结构,避免类型混淆
原栈用double items混存字符和数字,导致类型错乱。改为存储Token指针,明确每个栈元素的类型:
typedef struct { Token* items[200]; int top; } Stack;
如果追求简单,也可以拆分出数字栈(存double)和操作符栈(存Token或字符),彻底避免混存问题。
3. 完善数字解析逻辑,支持多位数和浮点数
原define_type只处理了整数第一位,补充浮点数解析和完整数字读取逻辑:
// Function为输入表达式字符串,i为当前解析索引,head为Token链表头 void define_type() { int len = strlen(Function); while (i < len) { // 解析数字(整数+浮点数) if (isdigit(Function[i]) || Function[i] == '.') { Token* nexttoken = (Token*)malloc(sizeof(Token)); nexttoken->type = T_NUMBER; double num = 0.0; int decimal_flag = 0; double decimal_factor = 0.1; // 读取整数部分 while (i < len && isdigit(Function[i])) { num = num * 10 + (Function[i] - '0'); i++; } // 读取小数部分 if (i < len && Function[i] == '.') { i++; decimal_flag = 1; while (i < len && isdigit(Function[i])) { num += (Function[i] - '0') * decimal_factor; decimal_factor *= 0.1; i++; } } nexttoken->num = num; // 将Token加入链表 if (head == NULL) { head = nexttoken; } else { Token* tmp = head; while (tmp->next != NULL) tmp = tmp->next; tmp->next = nexttoken; } nexttoken->next = NULL; } // 处理运算符、三角函数等逻辑(根据你的需求补充) else if (strchr("+-*/()", Function[i])) { Token* nexttoken = (Token*)malloc(sizeof(Token)); switch(Function[i]) { case '+': nexttoken->type = T_PLUS; nexttoken->precedence = 1; break; case '-': nexttoken->type = T_MINUS; nexttoken->precedence = 1; break; case '*': nexttoken->type = T_MUL; nexttoken->precedence = 2; break; case '/': nexttoken->type = T_DIV; nexttoken->precedence = 2; break; case '(': nexttoken->type = T_LPAREN; nexttoken->precedence = 0; break; case ')': nexttoken->type = T_RPAREN; nexttoken->precedence = 0; break; } // 加入链表逻辑同上 i++; } // 其他字符处理(如三角函数、非法字符) else { printf("无效字符: %c\n", Function[i]); i++; } } }
4. 修复中缀转后缀逻辑,完整存储数字Token
原代码把数字转成单个字符存入栈,导致多位数被拆分。现在直接将完整的数字Token加入后缀栈:
void infix_to_postfix(Token* head, Stack* postfix_tokens) { Stack op_stack; // 初始化栈(需实现对应的push_token、pop_token、peek_token函数) initialize_stack(&op_stack); Token* tmp = head; while (tmp != NULL) { switch (tmp->type) { case T_NUMBER: push_token(postfix_tokens, tmp); break; case T_LPAREN: push_token(&op_stack, tmp); break; case T_RPAREN: // 弹出操作符直到左括号 while (op_stack.top != -1 && peek_token(&op_stack)->type != T_LPAREN) { push_token(postfix_tokens, pop_token(&op_stack)); } pop_token(&op_stack); // 丢弃左括号 break; case T_PLUS: case T_MINUS: case T_MUL: case T_DIV: // 按优先级弹出操作符 while (op_stack.top != -1 && peek_token(&op_stack)->precedence >= tmp->precedence) { push_token(postfix_tokens, pop_token(&op_stack)); } push_token(&op_stack, tmp); break; case T_TRIG: push_token(&op_stack, tmp); break; } tmp = tmp->next; } // 弹出剩余操作符 while (op_stack.top != -1) { push_token(postfix_tokens, pop_token(&op_stack)); } }
5. 修复后缀表达式求值逻辑
现在后缀栈里是完整的Token,直接读取数字即可,无需拼接字符:
double evaluate_postfix(Stack* postfix_tokens) { Stack num_stack; initialize_num_stack(&num_stack); // 数字栈存储double while (postfix_tokens->top != -1) { Token* token = pop_token(postfix_tokens); if (token->type == T_NUMBER) { push_num(&num_stack, token->num); } else if (token->type == T_PLUS || token->type == T_MINUS || token->type == T_MUL || token->type == T_DIV) { double b = pop_num(&num_stack); double a = pop_num(&num_stack); double res; switch(token->type) { case T_PLUS: res = a + b; break; case T_MINUS: res = a - b; break; case T_MUL: res = a * b; break; case T_DIV: if (b == 0) { printf("除零错误!\n"); exit(1); } res = a / b; break; } push_num(&num_stack, res); } else if (token->type == T_TRIG) { double val = pop_num(&num_stack); double res; switch(token->trig_type) { case 1: res = sin(val); break; // 注意参数为弧度 case 2: res = cos(val); break; } push_num(&num_stack, res); } free(token); // 释放Token内存 } return pop_num(&num_stack); }
内容的提问来源于stack exchange,提问作者Meryem İbrahim
相关产品推荐
相关产品推荐

