![]() |
中国DOS联盟-- 联合DOS 推动DOS 发展DOS --联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum |
| 游客 | 登录 | 注册 | 会员 | 搜索 | 中国DOS联盟 |
|
中国DOS联盟论坛 现在时间是 2026-09-14 13:37 |
共 47,812 主题排行 / 349,917 发帖 / 今日 0 篇 / 48,268 会员排行 |
| DOS批处理 & 脚本技术(批处理室) » 一个可以计算简单表达式的批处理 |
| 可打印版本 13,106 / 22 |
| 第1楼 brglng | 发表于 2005-08-15 15:53 |
| 银牌会员 发帖 466 积分 1,200 来自 上海 | |
|
一个可以计算简单表达式的批处理 我编了一个有趣的批处理,用于2K/XP等NT类的系统,可以计算简单的表达式。只能算作入门级的吧,所以就贴在这里了。
@echo off 这个批处理的最新版可以在我的E盘的“DIY”目录里下载到。 [ Last edited by namejm on 2007-2-3 at 09:49 PM ] |
|
| 第2楼 venchia | 发表于 2005-08-15 18:02 |
| 初级用户 发帖 11 积分 125 | |
|
不错,收藏
|
|
| 第3楼 merlin | 发表于 2005-08-15 19:00 |
| 初级用户 发帖 18 积分 143 | |
|
怎么不写一个Win9x/me/DOS的啊!
|
|
| 第4楼 Michael | 发表于 2005-08-15 19:44 |
| 钻石会员 发帖 3,041 积分 10,056 | |
|
也许只有2k/xp才有现成的表达式求值语句吧。
|
|
| 第5楼 brglng | 发表于 2005-08-16 09:41 |
| 银牌会员 发帖 466 积分 1,200 来自 上海 | |
Originally posted by Michael at 2005-8-15 07:44 PM: 嗯,没错 其实,要真正实现更好的表达式计算,只要用那些命令行计算器就可以了。它们的使用都很方便。NT的set命令的/a参数也有很多限制的,功能并不强,比如不支持浮点数,不支持复杂的数学函数(如sin、cos)等。所以,这个批处理实际上没什么实用价值,只能作为学习学习吧。我自认为这个批处理对2K/XP新的命令开关和语法的综合运用还是不错的。 [ Last edited by brglng on 2005-8-16 at 10:18 ] |
|
| 第6楼 Michael | 发表于 2005-08-16 21:36 |
| 钻石会员 发帖 3,041 积分 10,056 | |
|
开始还真吓了我一跳,我还以为表达式计算也是批处理完成的呢。
C++编一个类似程序还得需要这么多行呢: #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 ] |
|
| 第7楼 brglng | 发表于 2005-08-17 15:46 |
| 银牌会员 发帖 466 积分 1,200 来自 上海 | |
|
呵呵,我用VB编过一个。
|
|
| 第8楼 willsort | 发表于 2005-08-19 20:31 |
| 元老会员 发帖 1,512 积分 4,432 | |
|
Re brglng:
很好的代码,提三个建议: 1、加入命令行参数支持,即在允许在命令行参数中写入表达式或者/?; 2、set /p 的提示字符串可以写在 set 语句中,比如 set /p SaveEval=是否将表达式和计算结果存入文件? 3、if 语句中可以使用开关 /i 进行忽略大小写判断,比如: if /i "%SaveEval%"=="Y" goto save if /i "%SaveEval%"=="N" goto next 另外,待代码完善后,我有意将它收入我的批处理收集帖 {8905}《批处理编程的异类》,但是因为版面限制,可能会删除大部分的说明性文档代码,不知 brglng 兄是否同意? |
|
| 第9楼 agboy888 | 发表于 2005-08-20 01:20 |
| 新手上路 发帖 1 积分 1 | |
|
不错,谢谢
|
|
| 第10楼 brglng | 发表于 2005-08-23 14:56 |
| 银牌会员 发帖 466 积分 1,200 来自 上海 | |
Originally posted by willsort at 2005-8-19 08:31 PM: 谢谢Willsort高手的建议。关于收录,我没什么意见,反正本来就是随便写写的。 |
|
| 第11楼 brglng | 发表于 2005-08-25 11:39 |
| 银牌会员 发帖 466 积分 1,200 来自 上海 | |
|
以下是根据willsort建议改进后的代码(增加了很多功能):
|
|
| 第12楼 defrag | 发表于 2005-08-26 00:54 |
| 中级用户 发帖 570 积分 456 | |
|
用GW-BASIC编计算器并不是很难。。。
这个没测试过 没有错误处理 main.bas: 用QB7.1也可以(要用QBX运行,不能编译) 有错误处理 也没测试 main.bas: [ Last edited by defrag on 2005-8-30 at 19:41 ] |
|
| 第13楼 willsort | 发表于 2005-08-26 11:28 |
| 元老会员 发帖 1,512 积分 4,432 | |
|
Re Brglng:
在结构上作了一些变化,让程序执行流程更加清晰,核心代码并为做出更改,请 Brglng 兄做一下测试吧。关于表达式用法帮助,我起初使用了 for 的语句以节省代码,但后来考虑到可读性的问题,最后舍弃了,你也可以一起测试一下。 [ Last edited by willsort on 2005-9-11 at 13:19 ] |
|
| 第14楼 pfox | 发表于 2005-08-26 15:01 |
| 银牌会员 发帖 446 积分 1,451 | |
|
几位用其他语言编写的朋友,能不能随便编译成exe上传?
|
|
| 第15楼 defrag | 发表于 2005-08-27 16:43 |
| 中级用户 发帖 570 积分 456 | |
|
说过,我那个只能在IDE(急成开发环境)里运行。。。
|
|
| 1 2 下一页 |
|
[ 联系联盟系统管理团队 -
中国DOS联盟 -
标准版 ] Sponsored by ifanr Inc | © 2001–2023 |