批处理文件“不平衡括号"; [英] Batch File "Unbalanced Parenthesis"

查看:44
本文介绍了批处理文件“不平衡括号";的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我要制作这个程序:

So I have this program I'm trying to make:

//@echo off
@title Calculate Caloric Needs
set /p name=What is the name of the individual in question? 
CLS

:START
set /p sex=Is %name% a M(ale) or F(emale)? (M/F) 
CLS
if NOT %sex%==M if NOT %sex%==F ( 
    echo Invalid Selection...Try Again....
    goto START
)

set /p w=What is the target weight of %name%? 
CLS

set /p h=What is the height of %name% IN INCHES? 
CLS

set /p a=What is the age of %name%? 
CLS

if %sex%==M set /a result=66 + (6.23 * %w%) + (12.7 * %h%) - (6.8 * %a%)
if %sex%==F set /a result=655+(4.35*%w%)+(4.7*%h%)-(4.7*%a%)

echo %result% is the caloric intake for %name%.
pause
exit

为排除故障,已禁用

@echo off .

@echo off has been disabled for the sake of troubleshooting.

这是一个简单的程序,旨在进行一些热量摄入计算,而这些计算很难一一完成.

It's a simple program meant to do some caloric intake calculations that are a bit arduous to do one by one.

每次我到达需要进行算术计算的位置时,就会发生以下两种情况之一:

Every time I reach the point where I need to do arithmetic calculations one of two things happens:

  1. 如果我将 set/a 语句包装在 if%sex%== M(CODE HERE)块中,该程序将意外退出而不会显示错误消息
  2. 如果我没有将所有内容都放在一行上(如上面示例代码所示),那么我会收到消息不平衡括号,而没有任何进一步的说明(感谢Windows ...).
  1. if I wrap the set /a statement in an if %sex%==M ( CODE HERE ) block, the program will exit unexpectedly without showing an error message.
  2. If I don't and have it all on one line (as it is in the example code posted above) then I get the message Unbalanced Parenthesis without any further explanation (thanks Windows...).

据我所知,从数学上讲,括号是完全平衡的.

As far as I know, mathematically speaking the parenthesis are completely balanced.

我尝试过:

  • " [] 中包装 set/a 语句, set/a"result = 66 +(6.23 *%w%)+(12.7 *%h%)-(6.8 *%a%)" set/a [结果= 66 +(6.23 *%w%)+(12.7 *%h%)-(6.8 *%a%)]
  • 转义算术 set/a result = 66 + ^(6.23 *%w%^)+ ^(12.7 *%h%^)-^(6.8 *%a%^)
  • 为了测试 set/a result = 66 +(6.23 *%w%),请减少括号的数量.如果我精确地使用 set/a result = 66 +(6.23 *%w%),则实际上可以将语句包装在 if(CODE HERE)块中并使其实际返回错误值.尽管错误仍然是不平衡括号 ...
  • 延长或缩短算术本身中的空格数 set/a结果= 66 +(6.23 *%w%)+(12.7 *%h%)-(6.8 *%a%)VS.设置/a结果= 66 +(6.23 *%w%)+(12.7 *%h%)-(6.8 *%a%)
  • 以上所有组合
  • wrapping the set /a statement in both "" and [], set /a "result=66 + (6.23 * %w%) + (12.7 * %h%) - (6.8 * %a%)" or set /a [result=66 + (6.23 * %w%) + (12.7 * %h%) - (6.8 * %a%)]
  • escaping some or all of the parenthesis used in the arithmetic set /a result=66 + ^(6.23 * %w%^) + ^(12.7 * %h%^) - ^(6.8 * %a%^)
  • reducing the amount of parenthesis for the sake of testing set /a result=66 + (6.23 * %w%). If I use set /a result=66 + (6.23 * %w%) exactly, I can actually wrap the statement in an if ( CODE HERE ) block and have it actually return an error value. Although the error is still Unbalanced Parenthesis...
  • lengthening or shortening the number of spaces in the arithmetic itself set /a result=66+(6.23*%w%)+(12.7*%h%)-(6.8*%a%) VS. set /a result=66 + (6.23 * %w%) + (12.7 * %h%) - (6.8 * %a%)
  • all combinations of the above

所以我对造成这种奇怪行为的原因不知所措.

So I am at a loss as to what could be causing this bizarre behavior.

推荐答案

在您遇到的情况下,您收到的错误消息非常令人困惑,因为 set/A 命令行中的括号是平衡的,并且如果整个命令行不是单独放在带括号的代码块中,则可以这样工作.无论如何,将整个 set/A 表达式放在引号之间始终是一个好主意,因此括号和其他特殊字符都不会造成麻烦.
方括号对于 set/A 没有任何特殊含义.

The error message you are receiving is very confusing in your situation, because the parentheses in the set /A command lines are balanced and work like that in case the entire command line is not placed inside of a parenthesised block of code on its own. Anyway, it is always a good idea to put the entire set /A expression in between quotation marks, so neither parentheses nor other special characters can cause trouble.
Square brackets do not have any particular meaning for set /A.

无论如何,该错误的根本原因是尽管 set/A 仅在32位空间中支持带符号整数算术(请参阅 set/?的帮助).在命令提示符窗口中键入 set/A(1.2 * 3),您将收到相同的错误消息;但是删除.,一切都会好起来的.

Anyway, the root cause of the error is the fact that you are using fractional numbers although set /A only supports signed integer arithmetics in a 32-bit room (see the help of set /?). Type set /A (1.2*3) in a command prompt window and you will receive the same error message; but remove the . and everything is going to be fine.

一种可能的解决方法是使用定点算术之类的东西,从而在计算过程中将所有内容乘以10的整数次幂,最后将结果除以相同的10次幂,换句话说,将小数点后移在进行计算之前先指向右侧,然后再向后移.

A possible work-around is to use something like fixed-point arithmetics, hence multiplying everything by a whole power of 10 during the calculations and dividing the result by the same power of 10 finally, or in other words, shifting the decimal point to the right before doing the calculations and shifting it back afterwards.

这是它的外观(我还修复了您代码中的其他问题,但请参见下文):

This is how it could look like (I also fixed some other issues in your code, but see below for that):

@echo off
@title Calculate Caloric Needs

cls
set "name=them"
set /P "name=What is the name of the individual in question? "

:START
set "sex="
set /P "sex=Is %name% a M(ale) or F(emale)? (M/F) "
if /I not "%sex%"=="M" if /I not "%sex%"=="F" (
    echo Invalid Selection... Try Again...
    goto :START
)

set "w=0"
set /P "w=What is the target weight of %name%? "

set "h=0"
set /P "h=What is the height of %name% IN INCHES? "
set "h=%h%."            & rem // append a decimal dot to entry in `h`
set "mil=1%h:*.=%"      & rem // store everything behind first dot in `mil`, prepend `1`
set /A "h+=0, mil+=0"   & rem // convert `h` to integer, dismiss fractional part
set "mil=%mil%000"      & rem // pad trailing zeros to `mil`
set "mil=%mil:~,4%"     & rem // extract first four numerals from `mil`
set /A "mil+=5"         & rem // add `5` to `mil` for rounding
if %mil:~,1% GTR 1 set /A "h+=1" & rem // regard carry of previous addition in `h`
set "h=%h%%mil:~-3,-1%" & rem /* append second and third numeral of `mil` to `h`,
                          rem    hence dismissing previously prepended `1`;
                          rem    so `h` holds the height in 100ths of inches now */

set "a=0"
set /P "a=What is the age of %name%? "

rem // quotation marks avoid trouble with parenthesis or other characters;
rem /* all original constants are multiplied by `1000` to avoid fractional parts,
rem    except the factor at `h` which is multiplied by `10` only due to above
rem    implicit multiplication of `h` by 100, then `500` is added for rounding,
rem    and finally, the result is divided by `1000` to remove the previous factors: */
if /I "%sex%"=="M" (
    set /A "result=(66000+(6230*%w%)+(127*%h%)-(6800*%a%)+500)/1000"
) else if /I "%sex%"=="F" (
    set /A "result=(655000+(4350*%w%)+(47*%h%)-(4700*%a%)+500)/1000"
)

echo %result% is the caloric intake for %name%.
pause
exit /B

这是我修复的问题:

    改进了
  • set 和 set/P 语法,以便整个表达式都位于引号之间,因此可以避免使用特殊字符的麻烦,并且可以清楚地看到是否存在是任何结尾的空格;
  • 初始化任何提示值,以避免在用户仅按 RETURN ;
  • 时采用先前的值的情况.纠正了
  • 用于性别输入的 if 查询,以便现在通过添加开关/I 使其不区分大小写,并且在经过测试的情况下也不会造成麻烦通过将比较表达式括在引号中来使变量为空;
    顺便说一句,您可能会对这样的单键输入的 choice 命令感兴趣,因为它甚至不接受任何其他字符;
  • 由于所述定点算法(但体重 w 和年龄 a仍视为整数);它是这样工作的:
    • 设置"h =%h%".:在 h 中的条目后面添加一个点,以确保至少有一个;
    • 设置"mil = 1%h:*.=%" :将 h 中第一个点之后的所有内容存储到 mil 中(小数部分),并在结果前加上 1 使其不丢失任何前导零(对于小数部分是重要的),只要将其转换为数字即可;
    • set/A"h + = 0,mil + = 0" :将 h mil 都转换为数值(整数);这会将直到第一个非数字数字的所有内容转换为数字,而忽略前导空格,但考虑符号 + /-(尽管它们无关紧要,在这里不需要);
    • 设置"mil =%mil%000" :将3个尾随零添加到小数部分(前置的 1 仍然存在,因此始终至少有4个数字);
    • 设置"mil =%mil:〜,4%" :提取前4个字符(因此,前面的 1 加上另外3个数字);
    • set/A"mil + = 5" :添加 5 ,因此,如果最后一个数字为 5 或更高,则会出现一个进位,所以倒数第二个数字会四舍五入;
    • 如果%mil:〜,1%GTR 1 set/A"h + = 1" :如果进位超过小数部分,则在 h 中递增整数部分;
    • 设置"h =%h %% mil:〜-3,-1%" :将 h 的整数部分以及从第二个到第二个密数在 mil 中的倒数第二个数字并将其存储在 h ;
    • the set and set /P syntax is improved so that entire expression is in between quotation marks, hence you avoid trouble with special characters and you clearly can see if there are any trailing white-spaces;
    • any prompted values are initialised to avoid the previous value is taken in case the user just presses RETURN;
    • the if queries for gender entry are corrected so that they are now case-insensitive by adding switch /I, and that they do not cause trouble in case the tested variables are empty by enclosing the comparison expressions in quotation marks;
      by the way, you might be interested in the choice command for such single-key entries, because it does not even accept any other characters;
    • the value of the height entry h in inches is converted to 100ths of inches because of the said fixed-point arithmetics (but weight w and age a are still treated as integers); this is how it works:
      • set "h=%h%.": append a dot to the entry in h to ensure there is at least one;
      • set "mil=1%h:*.=%": store everything after the first dot in h into mil (fractional part), and prepend 1 to the result to not lose any leading zeros (which are significant for the fractional part) as soon as this is converted to a number;
      • set /A "h+=0, mil+=0": convert both h and mil to numeric values (integers); this converts everything up to the first non-numeric figure to a number, ignoring leading white-spaces but regarding signs +/- (although they are irrelevant as not needed here);
      • set "mil=%mil%000": append 3 trailing zeros to the fractional part (the prepended 1 is still there, so there are always at least 4 digits);
      • set "mil=%mil:~,4%": extract the first 4 characters (so the prepended 1 plus 3 more figures);
      • set /A "mil+=5": add 5, so if the last numeral is 5 or more, a carry appears, so rounding up of the next-to-last figure happens;
      • if %mil:~,1% GTR 1 set /A "h+=1": increment integer part in h in case the carry exceeds the fractional part;
      • set "h=%h%%mil:~-3,-1%": concatenate the integer part of h and the range from the second to the next-to-last figure of the fractional part in mil and store it in h;

      请注意,批处理文件中的///* */之类的注释没有特殊含义.注释或备注由 rem 语句给出.我在这里 rem 中使用了斜杠样式的注释,只是为了在此站点上突出显示一些很酷的语法...

      Note that comments like // and /*, */ have no special meanings in batch-files. Comments or remarks are given by the rem statement. I used the slash-style comments within rem here only for some cool syntax highlighting here on this site...

      根据原始海报的评论,结果本身应该是小数,因此我对脚本进行了一些修改(以下说明):

      As per a comment by the original poster, the result itself should be a fractional number, so I modified the script a bit (a description follows below):

      @echo off
      @title Calculate Caloric Needs
      
      cls
      set "name=them"
      set /P "name=What is the name of the individual in question? "
      
      set "male="
      choice /C MF /M "Is %name% a M(ale) of F(emale)? "
      if not ErrorLevel 2 set "male=Flag"
      
      set "w=0"
      set /P "w=What is the target weight of %name% IN POUNDS? "
      
      set "h=0"
      set /P "h=What is the height of %name% IN INCHES? "
      set "h=%h%."            & rem // append a decimal dot to entry in `h`
      set "mil=1%h:*.=%"      & rem // store everything behind first dot in `mil`, prepend `1`
      set /A "h+=0, mil+=0"   & rem // convert `h` to integer, dismiss fractional part
      set "mil=%mil%000"      & rem // pad trailing zeros to `mil`
      set "mil=%mil:~,4%"     & rem // extract first four numerals from `mil`
      set /A "mil+=5"         & rem // add `5` to `mil` for rounding
      if %mil:~,1% GTR 1 set /A "h+=1" & rem // regard carry of previous addition in `h`
      set "h=%h%%mil:~-3,-1%" & rem /* append second and third numeral of `mil` to `h`,
                                rem    hence dismissing previously prepended `1`;
                                rem    so `h` holds the height in 100ths of inches now */
      
      set "a=0"
      set /P "a=What is the age of %name% IN YEARS? "
      
      rem // quotation marks avoid trouble with parenthesis or other characters;
      rem /* all original constants are multiplied by `1000` to avoid fractional parts,
      rem    except the factor at `h` which is multiplied by `10` only due to above
      rem    implicit multiplication of `h` by 100, then `500` is added for rounding,
      rem    and finally, the result is divided by `1000` to remove the previous factors: */
      if defined male (
          set /A "result=66000+(6230*%w%)+(127*%h%)-(6800*%a%)+5"
      ) else (
          set /A "result=655000+(4350*%w%)+(47*%h%)-(4700*%a%)+5"
      )
      
      echo %result:~,-3%.%result:~-3,-1% is the caloric intake for %name%.
      pause
      exit /B
      

      这就是我所做的:

      • 基本计算公式仍然相同,只是这次省略了 1000 的除法,并且将 5 添加到结果中而不是四舍五入 500 ;为了显示结果,将删除最后一个数字,并在其余的最后两个数字之前插入小数点.,因此结果有两个小数位;
      • 性别输入现在通过此答案原始版本中建议的 choice 命令完成(请参见上文),因此不再需要捕获无效结果作为 choice 仅接受预定义的键或字符;
      • the basic calculation formulas are still the same, except that the division by 1000 has been omitted this time, and that 5 is added to the result for rounding instead of 500; for displaying the result though, the very last figure is dismissed and a decimal dot . is inserted before the remaining last two numerals, so there are two fractional digits for the result;
      • the gender entry is now accomplished by the choice command as suggested in the original version of this answer (see above), so there is no more need to capture invalid results as choice simply only accepts predefined keys or characters;

      这篇关于批处理文件“不平衡括号";的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆