《C程序设计语言》第2版4.3节RPN代码异常:数字未入栈等问题
逆波兰表达式(RPN)代码问题排查与修复
核心问题拆解与修复方案
1. 数字压栈后显示为0
- 检查
push()函数的栈指针操作:必须是先赋值再自增栈指针,即val[sp++] = f;,如果写成val[++sp] = f;会写入错误的栈位置,导致读取到未初始化的0值。 - 验证
getop()的数字转换逻辑:确认读取到数字字符后,正确通过atof()(或手动转换)得到浮点数,且将转换结果完整传递给push()。 - 确认栈初始化:
sp初始值必须为0,val数组的大小要足够(书中定义为MAXVAL 100),避免数组越界导致数值被覆盖。
2. 空格未被跳过,触发未知命令错误
- 重点检查
getop()的空白字符跳过逻辑:书中的getop()开头会跳过所有空格、制表符,代码必须包含这段逻辑:
如果这段代码缺失或条件写错(比如误判为换行符),空格会被当作有效字符返回,触发未知命令。int c; while ((c = getch()) == ' ' || c == '\t') ; - 检查
getch()和ungetch()的实现:如果用了自定义字符缓冲,要确保缓冲逻辑正确,不会丢失或重复读取字符,影响空白跳过流程。
3. 运算符'+'被识别为未知命令
- 核对
getop()的返回值分支:读取到运算符时应直接返回该字符,确保这段逻辑正确:
若条件判断错误,会把运算符误判为非有效字符。if (!isdigit(c) && c != '.' && c != '-') return c; // 返回运算符或未知字符 - 检查主函数的命令处理分支:必须存在
'+'对应的case分支,示例:
遗漏该分支会走到默认的错误处理逻辑。case '+': push(pop() + pop()); break;
关键代码片段验证
书中getop()的核心逻辑参考(确保空白跳过、数字收集、运算符返回逻辑正确):
#include <ctype.h> #define NUMBER '0' // 自定义常量,标记返回的是数字 int getop(char s[]) { int i, c; while ((s[0] = c = getch()) == ' ' || c == '\t') ; s[1] = '\0'; if (!isdigit(c) && c != '.' && c != '-') return c; i = 0; if (isdigit(c)) while (isdigit(s[++i] = c = getch())) ; if (c == '.') while (isdigit(s[++i] = c = getch())) ; s[i] = '\0'; if (c != EOF) ungetch(c); return NUMBER; }
push()和pop()的标准实现:
#define MAXVAL 100 int sp = 0; double val[MAXVAL]; void push(double f) { if (sp < MAXVAL) val[sp++] = f; else printf("error: stack full, can't push %g\n", f); } double pop(void) { if (sp > 0) return val[--sp]; else { printf("error: stack empty\n"); return 0.0; } }
内容的提问来源于stack exchange,提问作者theperson
相关产品推荐
相关产品推荐

