中国DOS联盟论坛

China DOS Union

-- Unite DOS · Advance DOS · Grow DOS --
Union site: www.cn-dos.net Forum site: www.cn-dos.net/forum
Guest | Log in | Register | Members | Search | China DOS Union
中国DOS联盟论坛
The time now is 2026-09-14 13:21
47,812 topics / 349,917 posts / today 0 new / 48,268 members
DOS批处理 & 脚本技术(批处理室) » A batch script that can calculate simple expressions
Printable Version  13,099 / 22
Floor1 brglng Posted 2005-08-15 15:53
银牌会员 Posts 466 Credits 1,200 From 上海
I've compiled an interesting batch script for NT-based systems like 2K/XP, which can calculate simple expressions. It's just an entry-level one, so I'm posting it here.

@echo off
echo Welcome to use the 2K/XP expression calculation batch script
echo Made by Brglng 2005.8.15
echo Download address: http://brglng.ys168.com
echo Please report bugs in time! Email:sky-0310@sohu.com
echo.
echo Note: This batch script can only be used in NT-based systems, not in Win9x/Me/DOS!
echo If using in the command line, please use "Command Prompt" in the accessories or use cmd.exe, not command.com!
echo This batch file can only be used in Chinese version of
echo Windows 2K/XP/2003...!
echo Do not use command.com instead of cmd.exe!
pause

:inputExpr
set Expr=
set EvalExpr=
echo.
echo Please enter the expression (enter "?" to view help):
set /p Expr=
if "%Expr%"=="" (
goto inputExpr
)
if "%Expr%"=="?" (
echo This expression calculation batch script is very simple and supports the following operations in decreasing order of priority:
echo ^(^) ^- Grouping
echo ^! ^~ ^- ^- Unary operators
echo ^* ^/ ^% ^- Arithmetic operators
echo ^+ ^- ^- Arithmetic operators
echo ^<^< ^>^> ^- Logical shift
echo ^- Bitwise "AND"
echo ^^ ^- Bitwise "XOR"
echo ^| ^- Bitwise "OR"
echo ^= ^*^= ^/^= ^%^= ^+^= ^-^= ^- Assignment
echo ^&^= ^^^= ^|^= ^<^<^= ^>^>^=
echo ^, ^- Expression separator
echo If you use any logical or remainder operators, you need to enclose the expression string in quotes. Any non-numeric string key in the expression is taken as an environment variable name, and the values of these environment variable names are converted to numbers before use. If an environment variable name is specified but not defined in the current environment, the value will be set to zero. This allows you to use environment variable values for calculations without typing those % symbols to get their values. Except for hexadecimal numbers with 0x prefix and octal numbers with 0 prefix, numeric values are decimal numbers. Therefore, 0x12 is the same as 18 and 022. Please note that octal formulas can be easily confused: 08 and 09 are invalid numbers because 8 and 9 are not valid octal digits.
goto inputExpr
)
set /a EvalExpr="%Expr%"
if "%EvalExpr%"=="" (
echo Input error!
goto inputExpr
)
echo The calculation result is: %EvalExpr%

:if_save
set SaveEval=
echo.
echo Do you want to save the expression and calculation result to a file ?
set /p SaveEval=
if "%SaveEval%"=="Y" goto save
if "%SaveEval%"=="y" goto save
if "%SaveEval%"=="N" goto next
if "%SaveEval%"=="n" goto next
goto if_save

:save
echo Please enter the file path and file name (such as C:\Windows\file.txt. If no path is entered, it means the current folder, leaving it blank means the last entered path):
set /p SaveEvalPath=
echo %Expr%=%EvalExpr% >>%SaveEvalPath%
echo The expression and calculation result have been saved to %SaveEvalPath%!

:next
set EvalNext=
echo 1. Continue calculation 2. Exit
set /p EvalNext=
if "%EvalNext%"=="1" goto inputExpr
if "%EvalNext%"=="2" goto end
goto next

:end
echo Thank you for using! Press any key to exit...
pause >nul
set Expr=
set EvalExpr=
set SaveEval=
set SaveEvalPath=
set EvalNext=


The latest version of this batch script can be downloaded from the "DIY" directory on my E drive.

[ Last edited by namejm on 2007-2-3 at 09:49 PM ]
Floor2 venchia Posted 2005-08-15 18:02
初级用户 Posts 11 Credits 125
Not bad, collected
Floor3 merlin Posted 2005-08-15 19:00
初级用户 Posts 18 Credits 143
Why not write one for Win9x/me/DOS!
Floor4 Michael Posted 2005-08-15 19:44
钻石会员 Posts 3,041 Credits 10,056
Maybe only 2k/xp has ready-made expression evaluation statements.
Floor5 brglng Posted 2005-08-16 09:41
银牌会员 Posts 466 Credits 1,200 From 上海
Originally posted by Michael at 2005-8-15 07:44 PM:
Maybe only 2k/xp have ready-made expression evaluation statements.

Well, that's right.
In fact, to really achieve better expression calculation, you can just use those command-line calculators. Their usage is very convenient. The /a parameter of the set command in NT also has many limitations, and the function is not strong. For example, it does not support floating-point numbers, does not support complex mathematical functions (such as sin, cos), etc. So, this batch processing is actually not very practical, and can only be used for learning. I think this batch processing has a good comprehensive application of new command switches and syntax for 2K/XP.

[ Last edited by brglng on 2005-8-16 at 10:18 ]
Floor6 Michael Posted 2005-08-16 21:36
钻石会员 Posts 3,041 Credits 10,056
I was really startled at first. I thought the expression calculation was also done by batch processing.

Writing a similar program in C++ still needs so many lines:

#include<iostream>
#include<string>
#include<map>
#include<cctype>
#include<sstream>

using namespace std;

namespace Parser
{
double prim(bool);
double term(bool);
double expr(bool);
}

namespace Lexer
{
enum Token_value
{
NAME, NUMBER, END,
PLUS='+', MINUS='-', MUL='*', DIV='/',
PRINT=';', ASSIGN='=', LP='(', RP=')'
};

Token_value curr_tok;
double number_value;
string string_value;
map<string,double>table;

Token_value get_token();
}

namespace Driver
{
int no_of_errors;
istream* input;
void skip();
void sta();
}

namespace Error
{
struct Syntax_error
{
const char* p;
Syntax_error(const char* q) {p=q;}
};
struct Zero_divide{};
}


using namespace Driver;
using namespace Parser;
using namespace Lexer;
using namespace Error;

double Parser::expr(bool get)
{
double left=term(get);
for(;;)
switch(curr_tok)
{
case PLUS:
left+=term(true);
break;
case MINUS:
left-=term(true);
break;
default:
return left;
}
}

double Parser::term(bool get)
{
double left=prim(get);
for(;;)
switch(curr_tok)
{
case MUL:
left*=prim(true);
break;
case DIV:
if(double d=prim(true))
{
left/=d;
break;
}
throw Zero_divide();
default:
return left;
}
}



double Parser::prim(bool get)
{
if (get) get_token();
switch(curr_tok)
{
case NUMBER:
{
double v=number_value;
get_token();
return v;
}
case NAME:
{
double& v=table;
if(get_token()==ASSIGN)v=expr(true);
return v;
}
case MINUS:
return -prim(true);
case LP:
{
double e=expr(true);
if(curr_tok!=RP) throw Syntax_error("')'expected");
get_token();
return e;
}


default:
throw Syntax_error("primary expected");
}

}
Token_value Lexer::get_token()
{
char ch;
do
{
if(!input->get(ch))return curr_tok=END;
}while(ch!='\n'&&isspace(ch));
switch(ch)
{
case '\n':
return curr_tok=PRINT;
case ';':
case '*':
case '/':
case '+':
case '-':
case '(':
case ')':
case '=':
return curr_tok=Token_value(ch);
case '0':case '1':case '2':case '3':case '4':
case '5':case '6':case '7':case '8':case '9':
input->putback(ch);
*input>>number_value;
return curr_tok=NUMBER;
default:
if(isalpha(ch))
{
string_value=ch;
while(input->get(ch)&&isalnum(ch))string_value.push_back(ch);
input->putback(ch);
return curr_tok=NAME;
}
throw Syntax_error("bad token");
}
}
void Driver::sta()
{
while(*input){
try
{
get_token();
if(curr_tok==END)break;
if(curr_tok==PRINT)continue;
cout<<expr(false)<<endl;
}
catch(Zero_divide)
{
cerr<<"attempt to divide by zero\n";
if(curr_tok!=PRINT)skip();
}
catch(Syntax_error e)
{
cerr<<"syntax error:"<<e.p<<endl;
if(curr_tok!=PRINT)skip();
}
}
}



void Driver::skip()
{
no_of_errors++;

while(*input)
{
char ch;
input->get(ch);

switch(ch)
{
case '\n':
case ';':
return;
}
}
}

int main(int argc, char*argv)
{
switch(argc)
{
case 1:
input=&cin;
break;
case 2:
input=new istringstream(argv);
break;
default:
cerr<<"too many arguments\n";
return 1;
}
sta();
if(input!=&cin)delete input;
return no_of_errors;
}

[ Last edited by Michael on 2005-8-16 at 21:37 ]
Floor7 brglng Posted 2005-08-17 15:46
银牌会员 Posts 466 Credits 1,200 From 上海
Hehe, I've programmed one with VB.
Floor8 willsort Posted 2005-08-19 20:31
元老会员 Posts 1,512 Credits 4,432
Re: brglng:

Very good code, three suggestions are put forward:

1. Add command-line parameter support, that is, allow writing expressions or /? in command-line parameters;

2. The prompt string of set /p can be written in the set statement, for example
set /p SaveEval=Do you want to save the expression and calculation result to the file ?

3. The switch /i can be used in the if statement for case-insensitive judgment, for example:
if /i "%SaveEval%"=="Y" goto save
if /i "%SaveEval%"=="N" goto next

In addition, after the code is improved, I am interested in including it in my batch processing collection post {8905} "Abnormalities in Batch Processing Programming", but due to layout restrictions, most of the explanatory document code may be deleted. I wonder if Brother brglng agrees?
Floor9 agboy888 Posted 2005-08-20 01:20
新手上路 Posts 1 Credits 1
Not bad, thanks
Floor10 brglng Posted 2005-08-23 14:56
银牌会员 Posts 466 Credits 1,200 From 上海
Originally posted by willsort at 2005-8-19 08:31 PM:
Re brglng:

Good code, three suggestions:

1. Add command-line parameter support, that is, allow writing expressions or /? in command-line parameters;

2. The prompt word of set /p...


Thanks to expert Willsort for the suggestions. Regarding inclusion, I have no opinion, anyway, it was just written casually.
Floor11 brglng Posted 2005-08-25 11:39
银牌会员 Posts 466 Credits 1,200 From 上海
Here is the translation of the provided code's relevant description part:

The following is the improved code according to the suggestions of willsort (added many functions):
Floor12 defrag Posted 2005-08-26 00:54
中级用户 Posts 570 Credits 456
It's not very difficult to compile a calculator with GW-BASIC...
This hasn't been tested
No error handling
main.bas:

It can also be done with QB7.1 (needs to be run with QBX, can't be compiled)
Has error handling
Also not tested
main.bas:


[ Last edited by defrag on 2005-8-30 at 19:41 ]
Floor13 willsort Posted 2005-08-26 11:28
元老会员 Posts 1,512 Credits 4,432
Re Brglng:

Some structural changes have been made to make the program execution flow clearer, and the core code has not been changed. Please Brother Brglng do the testing. Regarding the expression usage help, I initially used the for statement to save code, but later considered the readability issue and finally discarded it. You can also test together.



[ Last edited by willsort on 2005-9-11 at 13:19 ]
Floor14 pfox Posted 2005-08-26 15:01
银牌会员 Posts 446 Credits 1,451
A few friends who wrote in other languages, can they compile into exe and upload casually?
Floor15 defrag Posted 2005-08-27 16:43
中级用户 Posts 570 Credits 456
Said, mine can only run in the IDE (urgently become the development environment)...
1 2  Next
[ Contact the Union admin team - 中国DOS联盟 - Standard version ]
Sponsored by ifanr Inc | © 2001–2023