| @Echo Off |
| Setlocal Enabledelayedexpansion |
| ::CODER BY 老刘 POWERD BY iBAT |
| Title 【老刘编写】逆波兰四则计算器 |
| Path "%~dp0" |
| If Not Exist "Stack_LSS.Bat" ( |
| Echo "Stack_LSS"缺失! |
| Pause&Exit |
| ) |
| |
| Set "Stack=Call Stack_LSS" |
| !Stack! :Init 运算符 |
| !Stack! :Init 操作数 |
| Echo Code By OldLiu |
| Echo. |
| Echo 表达式中只能出现“0123456789+-*/()”这些字符。 |
| Echo 计算支持分数、括号可以嵌套。 |
| Echo 支持负数,但负号前有运算符时需加括号。 |
| Echo 错误举例:6/-3 5--3*-8 |
| Echo 正确举例:6/(-3) 5-(-3*(-8)) |
| Echo 输入Quit或Exit退出。 |
| Echo. |
| Set /p IsDebug=是否开启DEBUG模式(y/n): |
| If /i "!IsDebug!" Neq "y" ( |
| Set "Hide=Rem" |
| ) Else ( |
| Set "Hide=" |
| ) |
| |
| :Loop |
| Echo. & Set /p "中缀表达式=键入表达式>>> " |
| If /i "!中缀表达式!" Equ "Quit" Exit |
| If /i "!中缀表达式!" Equ "Exit" Exit |
| |
| Rem 中缀转后缀。 |
| !Stack! :Clear 运算符 |
| Set 后缀表达式= |
| Set 可能出现负数=True |
| :读取中缀表达式 |
| If "!中缀表达式!" == "" Goto 中缀转后缀完成 |
| Set "字符=!中缀表达式:~,1!" |
| %Hide% Set 中缀表达式 |
| Set "中缀表达式=!中缀表达式:~1!" |
| |
| Rem 处理数字。 |
| Set /A "IsNum=!字符!" 2>Nul |
| If "!IsNum!" EQU "!字符!" ( |
| Set 数字=!数字!!字符! |
| Set 可能出现负数=False |
| Goto 读取中缀表达式 |
| ) Else ( |
| If Defined 数字 ( |
| Set "后缀表达式=!后缀表达式! !数字!" |
| %Hide% Set 后缀表达式 |
| Set 数字= |
| ) |
| ) |
| |
| Rem 处理左括弧。 |
| If "!字符!" == "(" ( |
| |
| !Stack! :Push 运算符 字符 |
| Set 可能出现负数=True |
| Goto 读取中缀表达式 |
| ) |
| |
| Rem 处理右括弧。 |
| If "!字符!" == ")" ( |
| |
| :括弧中运算符输出 |
| !Stack! :Pop 运算符 栈顶运算符 |
| If "!栈顶运算符!" Neq "(" ( |
| Set "后缀表达式=!后缀表达式! !栈顶运算符!" |
| %Hide% Set 后缀表达式 |
| Goto 括弧中运算符输出 |
| ) |
| Goto 读取中缀表达式 |
| ) |
| |
| Rem 处理运算符。 |
| If "!字符!" == "-" ( |
| If !可能出现负数! == True ( |
| |
| Set "后缀表达式=!后缀表达式! 0" |
| %Hide% Set 后缀表达式 |
| ) |
| ) |
| !Stack! :IsEmpty 运算符 |
| If !ErrorLevel! Equ 0 ( |
| |
| !Stack! :Push 运算符 字符 |
| Goto 读取中缀表达式 |
| ) Else ( |
| :运算符优先级比对 |
| !Stack! :Pop 运算符 栈顶运算符 |
| If !ErrorLevel! Equ 0 ( |
| Set 优先级高=False |
| |
| If "!栈顶运算符!" == "(" Set 优先级高=True |
| |
| If "!栈顶运算符!" == "+" ( |
| If "!字符!" == "*" Set 优先级高=True |
| If "!字符!" == "/" Set 优先级高=True |
| ) |
| If "!栈顶运算符!" == "-" ( |
| If "!字符!" == "*" Set 优先级高=True |
| If "!字符!" == "/" Set 优先级高=True |
| ) |
| If "!优先级高!" == "True" ( |
| |
| !Stack! :Push 运算符 栈顶运算符 |
| !Stack! :Push 运算符 字符 |
| Goto 读取中缀表达式 |
| ) Else ( |
| |
| Set "后缀表达式=!后缀表达式! !栈顶运算符!" |
| %Hide% Set 后缀表达式 |
| |
| Goto 运算符优先级比对 |
| ) |
| ) Else ( |
| |
| !Stack! :Push 运算符 字符 |
| Goto 读取中缀表达式 |
| ) |
| Echo 输入的表达式有误。 |
| Goto Loop |
| ) |
| |
| :中缀转后缀完成 |
| |
| Set "后缀表达式=!后缀表达式! !数字!" |
| Set 数字= |
| |
| !Stack! :Pop 运算符 栈顶运算符 |
| :运算符弹出 |
| Set "后缀表达式=!后缀表达式! !栈顶运算符!" |
| !Stack! :Pop 运算符 栈顶运算符 |
| If !ErrorLevel! Equ 0 Goto 运算符弹出 |
| %Hide% Set 后缀表达式 |
| |
| Rem 开始计算结果。 |
| !Stack! :Clear 操作数 |
| Call :计算结果 !后缀表达式! |
| Goto 计算完成 |
| :计算结果 |
| Set 字符=%1 |
| Set /A "IsNum=!字符!" 2>Nul |
| If "!IsNum!" EQU "!字符!" ( |
| |
| !Stack! :Push 操作数 字符 |
| ) Else ( |
| |
| |
| !Stack! :Pop 操作数 操作数2 |
| If !ErrorLevel! Neq 0 ( |
| Echo 输入的表达式有误。 |
| Goto Loop |
| ) |
| !Stack! :Pop 操作数 操作数1 |
| If !ErrorLevel! Neq 0 ( |
| Echo 输入的表达式有误。 |
| Goto Loop |
| ) |
| |
| If "!操作数1:/=!" Equ "!操作数1!" ( |
| Set "操作数1=!操作数1!/1" |
| ) |
| If "!操作数2:/=!" Equ "!操作数2!" ( |
| Set "操作数2=!操作数2!/1" |
| ) |
| |
| If "!字符!" Equ "*" ( |
| |
| For /f "tokens=1,2 delims=/" %%a in ("!操作数1!") do ( |
| Set /A 当前结果分子=%%a |
| Set /A 当前结果分母=%%b |
| ) |
| For /f "tokens=1,2 delims=/" %%a in ("!操作数2!") do ( |
| Set /A 当前结果分子*=%%a |
| Set /A 当前结果分母*=%%b |
| ) |
| ) |
| If "!字符!" Equ "/" ( |
| |
| For /f "tokens=1,2 delims=/" %%a in ("!操作数1!") do ( |
| Set /A 当前结果分子=%%a |
| Set /A 当前结果分母=%%b |
| ) |
| For /f "tokens=1,2 delims=/" %%a in ("!操作数2!") do ( |
| Set /A 当前结果分子*=%%b |
| Set /A 当前结果分母*=%%a |
| ) |
| ) |
| Set 加减法=False |
| If "!字符!" Equ "+" Set 加减法=True |
| If "!字符!" Equ "-" Set 加减法=True |
| If "!加减法!" Equ "True" ( |
| |
| For /f "tokens=1,2 delims=/" %%a in ("!操作数1!") do ( |
| Set /A 当前结果分子=%%a |
| Set /A 当前结果分母=%%b |
| ) |
| For /f "tokens=1,2 delims=/" %%a in ("!操作数2!") do ( |
| Set /A 当前结果分子=当前结果分子*%%b!字符!当前结果分母*%%a |
| Set /A 当前结果分母*=%%b |
| ) |
| ) |
| |
| Set /A 被除数=当前结果分子,除数=当前结果分母 |
| :求最大公约数 |
| If !除数! Equ 0 ( |
| Echo 除以0错误。 |
| Goto Loop |
| ) |
| Set /A 余数=被除数%%除数 |
| If !余数! Neq 0 ( |
| Set /A 被除数=除数,除数=余数 |
| Goto 求最大公约数 |
| ) |
| |
| Set /A 当前结果分子/=除数,当前结果分母/=除数 |
| Set 当前结果=!当前结果分子!/!当前结果分母! |
| %Hide% Echo ^(!操作数1!^)!字符!^(!操作数2!^)=!当前结果! |
| !Stack! :Push 操作数 当前结果 |
| ) |
| Shift /1 |
| If "%1" Neq "" Goto 计算结果 |
| Goto :Eof |
| |
| :计算完成 |
| !Stack! :Pop 操作数 计算结果 |
| For /f "tokens=1,2 delims=/" %%a in ("!计算结果!") do ( |
| Set /A 结果分子=%%a,结果分母=%%b |
| If !结果分母! Lss 0 Set /A 结果分子*=-1,结果分母*=-1 |
| If !结果分子! Equ 0 ( |
| Echo 结果:0 |
| ) Else If !结果分母! Equ 1 ( |
| |
| Echo 结果:!结果分子! |
| ) Else If !结果分子! Gtr !结果分母! ( |
| |
| Set /A 商=结果分子/结果分母,余数=%%a%%结果分母 |
| Echo 结果:!结果分子!/!结果分母!=!商!…!余数! |
| ) Else ( |
| |
| Echo 结果:!结果分子!/!结果分母! |
| ) |
| ) |
| Goto LoopCOPY |