Board logo

标题: 【共同参与】"批处理函数库" [打印本页]

作者: plp626     时间: 2008-4-1 23:17    标题: 【共同参与】"批处理函数库"

为了防止某些人灌水设了积分限制,请谅解,,

学了几个月批处理感觉收获真不少,(主要是好玩)

只是感觉功夫长进没有原来那么明显了,大部分时间都是在编一些重复的代码,即使一个很有挑战行动代码,花了不少功夫编出来,回过头认真一搜,论坛以前就有类似的代码,只是需要把各种方法"整合"就可以完成自己的代码了,

借鉴别人的,然后改进综合,这样进步才会很快.

只是很少人做这个工作,起码willsort以前发的帖子注意的人就寥寥(个人认为, 只有足够的函数,才能往面向对象那里想)

大家把自己能知道的一些常用的函数,(基本是都是call调用)共享下,交流下,然后极少成多多了,以后编代码就光查,既省时有省力,

(对于"私藏者",我引用一个小朋友的话"别当那是个宝,说不定还是个...,大家交流下说不定还有更高效的算法,这对你总是有好处的).

感觉很好的子过程或函数请发到这个帖子:

http://www.cn-dos.net/forum/viewthread.php?tid=39777&fpage=1常用子过程、函数收集【专用帖】

我这里有篇文章,虽然是英文但说的很到位,就是告诉我们些批处理函数的标准格式,供他人方便调用.

函数也就分有参函数与无参函数:

无参函数
call:标签A


rem 注释....(该函数的功能等)

:标签A
任务A
goto :eof
有参函数:
call:标签A "参数1" "参数2"


rem 注释....(该函数的功能等)

:标签A
setlocal ENABLEEXTENSIONS

参数接收
任务A

endlocal&设定返回参数1,参数2,...
goto :eof
对于注释部分以及变量的定义与返回,需要个规范,大家参考下面文章,交流下,

我英文不好,就不翻译,英语差点自己到http://www.google.cn/language_tools搜.

[ Last edited by plp626 on 2008-4-27 at 12:12 AM ]
作者: plp626     时间: 2008-4-1 23:35    标题: Batch Function Library

[转载]

原文:http://commandline.co.uk/lib/treeview/index.php
●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
Batch Function Overview (批处理函数概述)

What are they?

A batch function is a block of batch code that can be called by a batch file, optionally with a number of parameters. The function performs its task without unintentionally modifying variables outside of its own scope, and then returns control to the statement following the one that called the function.

Why use them?

The primary benefit of functions is reusable code. Once a function has been written, it can be used over and over again. This reduces the time spent developing and debugging scripts

Scripts that use functions naturally have a modular structure and use fewer 'global' variables, therefore they are much easier to understand, debug and maintain.

What do they look like?

All the functions in the library are based on the following template(下面是提供的模板):

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:<Function Name> <Parameter list>
::
:: By:   <Author/date/version information>
::
:: Func: <Function description>
::
:: Args: <Argument description>
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
<Body of function>
endlocal&<Set return values>&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

<Function name> Name of the function, eg GetDate
<Parameter list> List of arguments. This list only serves as a reminder of how to call the function (everything after the function name is ignored by the command interpreter)
<Author/date/version information> Self explanatory
<Function description> Brief explanation of what the function does and which platforms it has been designed for (NT4, W2K or XP)
<Argument description> Detailed description of the functions arguments
<Body of function> This is where the function performs its main purpose
<Set return values> This is where the function 'returns' any local values back to the calling routine
●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
Batch Functions Explained (批处理函数解释)

Passing Arguments

Most high-level programming languages allow arguments to be passed to functions 'by value' and 'by reference'. Passing by value means that the function receives a copy of the arguments value. Any changes made to this copy by the function do no affect the original variable.

When a variable is passed by reference, the function receives a pointer to the original variable, and loosely speaking, changes made to this pointer by the function do affect the original variable.

In the batch programming language variables are passed by reference. Unfortunately the pointers to the original variables are read only and consequently cannot be assigned values and therefore are unable to alter the variable which they point to.

The good news is that with a little ingenuity, the batch language can be coerced into passing variables by value and by reference in a similar way to high-level languages such as C and Visual Basic.

By Value

Below is a very simple example showing how to pass an argument by value and how that value is then read by the function.

1. @echo off & setlocal ENABLEEXTENSIONS
2. set str=Hello
3. call :demoA %str%
4. goto :EOF
5.
6. :demoA
7. echo/%1
8. goto :EOF

In line 3, %str% is expanded to Hello, and then the memory location of where Hello is actually stored is assigned to %1. Line 7 then references %1 which is then expanded to Hello.

If two or more arguments were being passed, they could be referenced using %2, %3 and so on, all the way up to %9. If more than nine variables were being passed, then to reference the tenth, the shift command would have to be used.

shift effectively increments all the pointers. Before shift is used, %0 points to the name of the function or routine and %1 points to the first argument. After shift is used, %0 points to what %1 used to point to, %1 points to what %2 used to point to and so on. The tenth argument can now be referenced using %9.

By Reference

Here is a slighty different version of the example above. Instead of passing the value Hello to the function, the name of a variable that contains Hello is passed instead.

1. @echo off & setlocal ENABLEEXTENSIONS
2. set str=Hello
3. call :demoB str
4. goto :EOF
5.
6. :demoB
7. call echo/%%%1%%
8. goto :EOF

Inside the function demoB, %1 expands to str. To read the value contained in str, it is necessary to enclose %1 with double percents and instruct the command interpreter to perform another expansion. This is most easily accomplished by using the CALL command as shown in line 7. For a detailed explanation of variable expansion, see the thread in alt.msdos.batch.nt titled "Variable expansion (W2KSP2)".

Why would we want to pass arguments like this? Well now that the function knows the name of a variable, it can assign it a value and thereby the function can now return values.

Returning Values

So far the contrived examples have only served to illustrate the points being made. This next example demonstrates how a function can return a value and is typical of the functions in this library. The methods used guarantee this function can be inserted, as it stands, into any batch file without causing any side effects whatsoever.

The function below is called Area and it simply calculates the product of width and height and then returns the result. Three arguments are required, the first two should be passed by value, the third by reference.

[It is a convention of this library to document a function's arguments by including an argument list immediately after the function name (as shown below on line 08). This is a convenient location as anything after the function name is ignored by the command interpreter. This list serves no other purpose than to act as a reminder of the type and number of arguments a function expects.]

01. @echo off & setlocal ENABLEEXTENSIONS
02. set x=2
03. set y=3
04. call :Area %x% %y% answer
05. echo/The area is: %answer%
06. goto :EOF
07.
08. :Area %width% %height% result
09. setlocal
10. set /a res=%1*%2
11. endlocal & set "%3=%res%"
12. goto :EOF

Line 04 calls the Area function passing three arguments (it could equally have read call :Area 2 3 answer). The first command of the function (line 09) is setlocal. This command creates a copy of the current environment and this copy then becomes the current environment. Line 10 calculates the product of arguments %1 and %2 and saves the result in the variable called res.

The next line consists of two commands seperated by an ampersand (&). This causes the command interpreter to expand both commands and then execute them one after the other. So line 11, after it has been expanded equates to endlocal & set "answer=6". Now the endlocal command is executed, which deletes the copy of the environment created by the most recent setlocal command, and restores the previous environent. Then set "answer=6" is executed, and finally on line 12 goto :EOF exits the function and execution continues at line 05. The net result is that the Area function has returned a value.

If on line 11, the command set "%3=%res%", had been expanded after endlocal had been executed, then instead of expanding to set "answer=6" it probably would have been set "answer=" as the res variable was deleted by the endlocal command.

By Value or Reference

The rule of thumb is to pass arguments by value unless you need to modify the original values, in which case pass by reference. The Area function above demonstrates this rule as the first and second arguments (width and height) are passed by value, but in order to assign the result of the calculation to the answer variable, it was passed to the function by reference.

Sometimes it's necessary to pass arguments by reference even though read-only access is required. For example, when passing two or more unquoted arguments where at least one of them contains whitespace, the function would not be able to determine which argument was which if they had been passed by value. Calling by reference can also be used to pass arguments containing so-called 'poison' characters (such as " ! | < > ^ " & %).

Protecting out of Scope Variables

In order to create truely reusable functions, you must ensure that they do not unintentionally modify variables outside of their own scope. This is accomplished by enclosing your function's main routine with the setlocal and endlocal statements as shown in the example above.

Unfortunately things get a little more complicated when two or more arguments are passed by reference and those arguments need to be read by your function (as opposed to just being assigned values). This is best illustrated by the Swap function shown below.

Protecting Arguments

When passing two or more arguments by reference where those arguments need to be read, care must be taken not to destroy any of the arguments before they have all been read. Consider this example below.

01. @echo off & setlocal ENABLEEXTENSIONS
02. set a=one
03. set b=two
04. echo/Before call   :swap a b [%a% %b%]
05. call :Swap a b
06. echo/After call 1 :swap a b [%a% %b%]
07. call :Swap b a
08. echo/After call 2 :swap b a [%a% %b%]
09.
10. goto :EOF
11.
12. :Swap
13. setlocal
14. call set a=%%%1%%
15. call set b=%%%2%%
16. endlocal & set "%1=%b%" & set "%2=%a%" & goto :EOF

The above example displays:-

Before call   :swap a b [one two]
After call 1 :swap a b [two one]
After call 2 :swap b a [one one]

This function is supposed to swap the contents of two variables. Notice it succeed the first time, but failed on the second. This was caused by variable names outside of the function clashing with duplicate names inside the function. Specifically, this is what went wrong:-

Line 07 called Swap, the first argument is b, the second a.

Line 14 is expanded twice because of the call command, after the second expansion, the line equates to set a=one, and once this command is executed, a is overwritten.

Line 15 is also expanded twice and equates to set b=one, in other words both a and b are now the one

The usual workaround for this problem is to use variable names that are unique to your function by preceeding all function variables with the function name separated by a period. However, if using that approach, it's actually only necessary to use unique names for vulnerable variables. Rewriting lines 14-16 of the Area function as shown below would prevent any arguments being overwritten before they had been saved.

14. call set Swap.a=%%%1%%
15. call set b=%%%2%%
16. endlocal&set %1=%b%&set %2=%Swap.a%&goto :EOF

This method has several drawbacks. Firstly, you must never use a period in any variable name outside of your functions. Secondly, if the function doesn't have a really short name and reads a number of variables by reference, the number of lines of code in the function can double if you want to avoid 'long' lines of code.
An alternative method is to read the variables with the FOR /F command using a delimiter character not present in any of the argument values. Using this method the Swap function could be rewritten as follows:-

12. :Swap
13. setlocal ENABLEEXTENSIONS
14. for /f "tokens=1-2 delims=¬" %%a in ('echo/%%%1%%¬%%%2%%') do (
15.    set a=%%a&set b=%%b
16. )
17. endlocal&set %1=%b%&set %2=%a%&goto :EOF

The delimiter character is a '¬' (ASCII 172, which looks like a back-to-front 'L' on its side). It was chosen because it's rarely used and it appears on a UK keyboard (above the TAB key). If you don't have this key, you can type it by holding down the Alt key and typing 172 on the numeric keypad. The only drawback of this method being your variables must never contain the delimiter character otherwise you may obtain incorrect results.

This issue was covered in alt.msdos.batch.nt in a thread titled "Function parameters".

●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●

Using the Functions(函数的使用)

Copy the Function

To use any of the functions, just copy and paste them to the end of your batch file. To prevent the function(s) from being executed after your main batch file code has run, add goto :EOF after your main batch file code but before the function(s). For example:-

Example 1a

<-- Your main batch file code goes here
goto :EOF
<-- 1st function here
<-- 2nd function here
<-- and so on...

[The documentation for each function includes an example that demonstrates how the function should be called. In these examples the actual function itself has been omitted to avoid unnecessarily duplicating code. When using any of the examples, remember to append the function to the end of your batch file.]

Calling the Function

The documentation for each function describes the number of required and optional parameters, the type of data each parameter should contain and whether the parameter must be passed 'by value' or 'by reference'. Both terms are used very loosely here and the reason is covered in great detail in the next section. Suffice to say that to pass a variable by value, call the function with a constant or expanded variable. And to pass by reference, call the function with the name of a variable.

By Value

To pass a parameter 'by value', either call the function with a constant or an expanded variable that contains the value. As an example, the Sleep function expects one parameter (a number of seconds) to be passed by value. Here are three ways to call the Sleep function with the value 9:-

Example 2a

call :Sleep 9


Example 2b

set AnyVarName=9
call :Sleep %AnyVarName%


Example 2c

call :Sleep %1

Notes: In example 2b, practically any variable name could have been used. Example 2c assumes the value of 9 was passed to the batch file as a commandline parameter.

By Reference

To pass a value 'by reference' simply use the name of a variable. As an example, the GetDate function expects three parameters, all passed by reference. Here's how to call the GetDate function and use the 'returned' values:-

Example 3a

call :GetDate yy mm dd
echo/Todays date is: %yy%-%mm%-%dd%

Note that although example 3a used the variable names yy, mm and dd, practically any variable names could have been used. For instance, example 3b is functionally equivalent to example 3a (but not so easy to understand).

Example 3b

call :GetDate x y z
echo/Todays date is: %x%-%y%-%z%
●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●
应用举例:

DateToDOW

The DateToDOW function returns the day of week number for a given calendar date..

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:DateToDOW %yy% %mm% %dd% dow
::
:: By:   Ritchie Lawrence, 2003-04-29. Version 1.1
::
:: Func: Creates a day of week number from a calendar date, where 1 = Mon
::       and 7 = Sun. For NT4/2000/XP/2003.
::
:: Args: %1 year component to be converted, 2 or 4 digits (by val)
::       %2 month component to be converted, leading zero ok (by val)
::       %3 day of month to be converted, leading zero ok (by val)
::       %4 var to receive day of week number, 1 to 7 (by ref)
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
setlocal ENABLEEXTENSIONS
set yy=%1&set mm=%2&set dd=%3
if 1%yy% LSS 200 if 1%yy% LSS 170 (set yy=20%yy%) else (set yy=19%yy%)
set /a dd=100%dd%%%100,mm=100%mm%%%100
set /a z=14-mm,z/=12,y=yy+4800-z,m=mm+12*z-3,dow=153*m+2
set /a dow=dow/5+dd+y*365+y/4-y/100+y/400-2472630,dow%%=7,dow+=1
endlocal&set %4=%dow%&goto :EOF
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::  

Parameters

%1 year component to be converted, 2 or 4 digits (by val)
%2 month component to be converted, leading zero ok (by val)
%3 day of month to be converted, leading zero ok (by val)
%4 var to receive day of week number, 1 to 7 (by ref)

Return Values

See parameters above.

Example

@echo off & setlocal ENABLEEXTENSIONS
call :GetDate y m d
call :DateToDOW %y% %m% %d% dow
call :DayName %dow% day
echo/Today is %day%
goto :EOF

Remarks

The DateToWeek function also returns day of week (in addition to year and month).

See Also

DateToWeek, DayName, DayNumber
作者: plp626     时间: 2008-4-2 00:22
真就这么无动于衷吗?
fastslz zh159 HAT 26933062
你们在线呀!我就不信你们也不感兴趣.

有多少人因为这样相继离去,(当然我不会的,∵我还没成为高手)
作者: HAT     时间: 2008-4-2 01:01
别人写的,我帮忙贴一下吧:
rem 字符串长度计算
set str=abc
for /f "skip=1 delims=:" %%a in ('^(echo "%str%"^&echo.^)^|findstr /o ".*"') do set /a length=%%a-5
echo %length%

作者: Shinaterry     时间: 2008-4-2 14:35


弱弱请教一下..

假如A.bat内容如下:
@echo off
:c
echo "do"
goto :eof
现时B.bat能否利用call直接调用A.bat->:c(标签)?

[ Last edited by Shinaterry on 2008-4-2 at 02:38 PM ]
作者: huahua0919     时间: 2008-4-2 14:48
不是无动于衷,BAT没什么函数及方法之类的东东,全是靠命令堆积起来的,变化的只是头脑,缺少的只是经验!如果真的想了解函数库,那还不如多了解JS,VBS,JAVA,C的函数,及相关联的组建,如COM.DLL之!
作者: Shinaterry     时间: 2008-4-2 15:30
谢谢两位! abcd 兄的方法正正是我原先所使用的, 因为觉得笨拙, 所以特意请教有没有方法可直接调用..

看来楼主, 看透我的意图, 因为这样"批处理函数库"的存在才有更大意义..



[ Last edited by Shinaterry on 2008-4-2 at 03:36 PM ]
作者: zh159     时间: 2008-4-2 17:04
真正常用的子过程并不多,而且不一定能通用,或多或少都需要适当修改,基本上是根据实际应用再编写
作者: knoppix7     时间: 2008-4-7 19:26
个人感觉:
函数库很有必要.
貌似目前更需要"方法库".给人写了一堆代码。该不会的还不会.(BC到搜索都懒得用.同一个问题回答N便很让人烦..)
直接给出大致方法.他们自己发挥去.
作者: plp626     时间: 2008-4-23 16:04
[code]:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::输出彩色字符{code by jvive@cn-dos.net|2008-4-9}
::call:Colstr <attr> <sp> <"str"> <bk> <sp> <enter>  
::               |     |     |      |    |     |
::             颜色   空格  字符串   退格  空格 回车换行
::效率:      约18次/s  (XP 5.1/2.4GHz/256M)      
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::说明:
::   attr   16进位数字颜色属性。请参考16进位数字颜色属性配置演示代码。
::   sp     范围:{0,
作者: plp626     时间: 2008-4-23 16:05
.....

[ Last edited by plp626 on 2008-4-25 at 07:15 PM ]
作者: metoo     时间: 2008-4-24 21:04
发了一个用来删除文件的
http://www.cn-dos.net/forum/viewthread.php?tid=39723&fpage=2
。。貌似没多少人感兴趣 - -! 这个可以直接加参数用call调用,当然要调用的话重启那段代码可以去掉
call :delf 要删的文件1 要删的文件2 。。。。
:delf
@echo off
set t=0
title=文件删除工具  code by 逐月鹰
:begin
set/a t=%t%+1
del/a/f/s/q %1 >nul 2>nul
rd /s /q %1 >nul 2>nul
if %ERRORLEVEL%==1 GOTO end1
if exist "%~1" echo %~nx1被锁定,将尝试重启后删除&&goto redel
shift
GOTO begin
:end1
IF not "%t%"=="1" GOTO end2
title=文件删除工具使用说明  code by 逐月鹰
color 0a
echo.
echo 请将需要删除的文件拖到这个程序的图标上
echo 本代码支持多个文件、文件夹同时删除
echo 当遇到文件因为正在使用而无法删除时
echo 会尝试在下次重启后删除,当文件夹中有
echo 文件运行时,会提示先删除其中的文件
echo.
pause
goto :eof
:end2
if "%u%"=="%%0%" (
echo del %u%>>"%userprofile%\「开始」菜单\程序\启动\runonce.bat"
goto reb
)else if "%u%"=="error" (
echo 某些文件夹在使用中,请尝试先删除其中的文件
)else ECHO 文件/文件夹已被全部删除
pause
goto :eof
:redel
Attrib -r -a -s -h %1
set a=%random%
ren %1 "%~nx1.%a%" 2>nul||ECHO 失败!请尝试先删除文件夹中的文件&&SHIFT&&set u=error&&goto begin
echo 123>%1
attrib +r +a +s +h %1
set u=%%0%
ECHO ^@ECHO OFF>>"%userprofile%\「开始」菜单\程序\启动\runonce.bat"
echo del /a/f/s/q %1>>"%userprofile%\「开始」菜单\程序\启动\runonce.bat"
echo del /a/f/s/q "%~dpnx1.%a%">>"%userprofile%\「开始」菜单\程序\启动\runonce.bat"
SHIFT
goto begin
:reb
set/p shut=是否马上重启?Y(是)其他任意键退出:
if /i "%shut%"=="y" shutdown -r -t 0 -f
goto :eof
pause
[ Last edited by metoo on 2008-4-24 at 09:07 PM ]
作者: slore     时间: 2008-4-24 21:07
还是用DEL 和RD命令?又不能强删,所以实用性不高呀
UNLOCKER,右键很方便……
作者: metoo     时间: 2008-4-24 21:09
加上了重命名后重启删除,确实实用性一般,我写这也就是想作为一个函数调用的  p终究不是万能的

正在考虑寻找一些更加霸道的命令加入代码,这个只能算一个雏形把,慢慢完善

[ Last edited by metoo on 2008-4-24 at 09:10 PM ]
作者: metoo     时间: 2008-4-24 21:13
还有一段查看网络性息的事别人写的
::调用格式:
call :select "ip address" "ip"
call :select "Physical Address" "mac"
call :select "Default Gateway" "gateway"
call :select "DNS Servers" "dns"
call :select "Description" "netcard"

:: 演示效果
echo IP:%ip%
echo MAC:%mac%
echo DNS:%dns%
echo GATEWAY:%gateway%
echo NETCARD:%netcard%
pause>nul
goto :eof

::**************************************************************
::              解析ipconfig命令输出通用函数
::**************************************************************
:select
    for /f "tokens=2 delims=:" %%i in ('ipconfig /all ^| findstr /i /c:%1') do if not "!%~2!" == "" set "%~2=%%i"
goto :eof

作者: vkill     时间: 2008-4-25 13:29
我觉得用到什么了找别人的来修改来使用,直接用?怕不怎么好使
作者: plp626     时间: 2008-4-25 13:36


  Quote:
Originally posted by vkill at 2008-4-25 01:29 PM:
我觉得用到什么了找别人的来修改来使用,直接用?怕不怎么好使

这个zh159兄说过,就是通用性,我开始不以为然,做了许多尝试过后,确有感触。

确实要想完全通用不加修改,有一定困难,这样的代码不是很多,并且当做为通用函数时,代码的效率还会降低,

但是,这只是开始,你如果去老外的论坛,你会对次肯定的。

它即使起不到”函数库的作用“ 它起码提供了个方法库,这对我们引用别人的很方便,新手学习也较集中。
作者: plp626     时间: 2008-4-25 14:16
大家能否讨论下下 set做浮点运算的函数
参考论坛里的有关浮点运算的经典帖子(这些请搜索关键字“浮点”),(除数位数多于8位的现在有困难)个人认为完全可以建立一个批处理浮点运算的函数+ - * /,因为set支持位运算,从这点来所,est原先说的计算什么方程的根,倒数了,是可行的,可以好不夸张地说,计算圆周率pi,自然对数e都是可行的,效率当然无法与高级语言相比,但理论上可行。

至于实用性-----没有,这个只当是弥补批处理没有提供浮点运算的现成命令了。
不过很好玩啊。
作者: moniuming     时间: 2009-1-19 18:43    标题: 批处理乘法函数


@echo off
::Code By cn-dos moniuming 2008-12-31
if "%1"=="" goto :hlp
setlocal enabledelayedexpansion
:bgn
for %%a in (dot ceng fuhao wei answer strax strbx) do (set %%a=)
set "stra=%1"&set "strb=%2"
if "%stra:~,1%"=="+" (set stra=%stra:~1%)
if "%strb:~,1%"=="+" (set strb=%strb:~1%)
if "%stra:~,1%"=="-" (set /a fuhao+=1&set stra=%stra:~1%)
if "%strb:~,1%"=="-" (set /a fuhao+=1&set strb=%strb:~1%)
for /f "tokens=1,2 delims=." %%a in ("%stra%") do (
  set "stral=%%a"&set "strar=%%b"
)
for /f "tokens=1,2 delims=." %%a in ("%strb%") do (
  set "strbl=%%a"&set "strbr=%%b"
)
:agn1
if defined strar (
  set "strax=%strax%%strar:~-1% "
  set /a "dot+=1","wei+=1"
  if not "%strar:~0,-1%"=="" (
    set "strar=%strar:~0,-1%"&goto :agn1
  )
)
:agn2
if defined strbr (
  set "strbx=%strbx%%strbr:~-1% "
  set /a "dot+=1","wei+=1"
  if not "%strbr:~0,-1%"=="" (
    set "strbr=%strbr:~0,-1%"&goto :agn2
  )
)
:agn3
set "strax=%strax%%stral:~-1% "
set /a "wei+=1"
if not "%stral:~0,-1%"=="" (set "stral=%stral:~0,-1%"&goto :agn3)
:agn4
set "strbx=%strbx%%strbl:~-1% "
set /a "wei+=1"
if not "%strbl:~0,-1%"=="" (set "strbl=%strbl:~0,-1%"&goto :agn4)
for %%a in (%strax%) do (
  set /a "ceng+=1"&set "lie=!ceng!"&set "jinwei=0"
  for %%b in (%strbx%) do (
    set /a "sth=%%a*%%b"
    set "sthl=!sth:~0,-1!"
    set "sthr=!sth:~-1!"
    set /a "var=ans!lie!+!jinwei!+!sthr!"
    set "jinwei=0"
    set "varl=!var:~0,-1!"
    set "varr=!var:~-1!"
    if not "!sthl!"=="" (set /a "jinwei+=!sthl!")
    if not "!varl!"=="" (set /a "jinwei+=!varl!")
    set "ans!lie!=!varr!"
    set /a "lie+=1"
  )
  set "ans!lie!=!jinwei!"
)
for /l %%a in (1 1 %wei%) do (
  set "answer=!ans%%a!!answer!"
  set "ans%%a="
)
if defined dot (
  if not "%4"=="" (
    if "%4"=="0" (
      set "answer=!answer:~0,-%dot%!"
    ) else (
      set "answer=!answer:~0,-%dot%!.!answer:~-%dot%,%4!"
    )
  ) else (
    set "answer=!answer:~0,-%dot%!.!answer:~-%dot%!"
  )
)
:cut
if "%answer:~0,1%"=="0" (
  if not "%answer:~1,1%"=="." (
    set answer=%answer:~1%
    goto :cut
  )
)
if "%fuhao%"=="1" (set answer=-%answer%)
endlocal&set "%3=%answer%"&goto :eof
:hlp
color 3f
echo.&echo  使用方法:
echo.&echo  1.把本批处理脚本命名为 chengfa.bat 复制到系统目录里
echo.&echo  2.不带参数运行本批处理脚本显示此帮助信息
echo.&echo  3.格式: call chengfa.bat 参数1 参数2 参数3 [参数4]
echo.&echo    参数1 为乘数1
echo.&echo    参数2 为乘数2
echo.&echo    参数3 为变量名
echo.&echo    参数4 为保留小数位数,可选参数,如不选则保留所有小数.
echo.&echo  4.例: call chengfa.bat 100 123.456789 ans 2
echo.&echo   意思为给变量 ans 赋值,其值等于 100 和 123.456789 的乘积,
echo.&echo   并保留两位小数,结果为: 12345.67
echo.&set/p= 按任意键退出...<nul&pause>nul&color&goto :eof
[ Last edited by moniuming on 2009-1-19 at 21:17 ]
作者: moniuming     时间: 2009-1-20 19:17    标题: 批处理加法函数


@echo off
::Code By cn-dos moniuming
if "%1"=="" goto :hlp
setlocal enableextensions
set "jinwei=0"
for %%a in (lastans bu dot) do (set %%a=)
set "stra=%1"
set "strb=%2"
if not "%4"=="" (
  if "%4"=="0" (
    set bu0=1
    set dot=dot
  ) else (
    set bu0=%4
  )
) else (
  set bu0=2
)
for /l %%a in (1 1 %bu0%) do (call set bu=%%bu%%0)
for /f "tokens=1,2 delims=." %%a in ("%stra%") do (
  set stral=%%a
  set "strar=%%b%bu%"
)
for /f "tokens=1,2 delims=." %%a in ("%strb%") do (
  set strbl=%%a
  set "strbr=%%b%bu%"
)
call set "jiashu1=%stral%%%strar:~0,%bu0%%%"
call set "jiashu2=%strbl%%%strbr:~0,%bu0%%%"
:agn
set /a "var=%jiashu1:~-1%+%jiashu2:~-1%+%jinwei%"
if %var% gtr 9 (set jinwei=1) else (set jinwei=0)
set "lastans=%var:~-1%%lastans%"
if not "%jiashu1:~0,-1%"=="" (
  set "jiashu1=%jiashu1:~0,-1%"
) else (
  set "jiashu1="
)
if not "%jiashu2:~0,-1%"=="" (
  set "jiashu2=%jiashu2:~0,-1%"
) else (
  set "jiashu2="
)
if defined jiashu1 (
  if defined jiashu2 (
    goto :agn
  ) else (
    call :count1
  )
) else (
  if defined jiashu2 (call :count2)
)
if "%jinwei%"=="0" (set "jinwei=")
call set "cn_ans=%jinwei%%%lastans:~0,-%bu0%%%.%%lastans:~-%bu0%%%"
if defined dot (set cn_ans=%cn_ans:~,-2%)
:cut0
if "%cn_ans:~,1%"=="0" (
  if not "%cn_ans:~1%"=="" (
    if not "%cn_ans:~1,1%"=="." (
      set "cn_ans=%cn_ans:~1%"
      goto :cut0
    )
  )
)
endlocal&set "%3=%cn_ans%"&goto :eof

:count1
set /a "var=%jiashu1:~-1%+%jinwei%"
if "%var:~0,-1%"=="1" (set jinwei=1) else (set jinwei=0)
set "lastans=%var:~-1%%lastans%"
if not "%jiashu1:~0,-1%"=="" (
  set "jiashu1=%jiashu1:~0,-1%"
  goto :count1
) else (goto :eof)
:count2
set /a "var=%jiashu2:~-1%+%jinwei%"
if "%var:~0,-1%"=="1" (set jinwei=1) else (set jinwei=0)
set "lastans=%var:~-1%%lastans%"
if not "%jiashu2:~0,-1%"=="" (
  set "jiashu2=%jiashu2:~0,-1%"
  goto :count2
) else (goto :eof)
:hlp
color 1f
echo.
echo  声明: 此脚本不支持负数的加法
echo  使用方法:
echo  把本批处理脚本复制到系统目录里
echo  不带参数运行本脚本 显示此帮助信息
echo.
echo  格式: call jiafa.bat 参数1 参数2 参数3 [参数4]
echo    参数1   为加数1
echo    参数2   为加数2
echo    参数3   为变量名
echo    [参数4] 可选参数,为保留小数的位数,如果空则默认保留2位小数
echo.
echo  例: call jiafa.bat 100.78965 123.45 ans 4
echo  意思为给变量 ans 赋值,其值等于100.78965与123.45的和,并保留四位小数
echo  结果为:224.2396
echo.&set/p= 按任意键退出...<nul
pause>nul&color&goto :eof

作者: 523066680     时间: 2009-1-21 10:38
嘿嘿,大家有必要讨论一下把函数放在什么地方合适哦
比如说system32  以后可以直接调用,又比如说%userprofile%
可以编一些很有个性的函数,大大地减少鼠标的使用
可能会另外开贴,再议
作者: WANKOILZ     时间: 2009-1-21 15:45
个人觉得“函数库”的通用性不强,“过程库”应该更容易移植,多发点不需要参数的“过程”还不错...
作者: moniuming     时间: 2009-2-9 10:15    标题: 20楼加法函数的修改版

修改的内容为:如果参数4(保留小数位数)为空,则保留原有的小数位数...
@echo off
::Code By cn-dos moniuming 2009-02-08
if "%1"=="" goto :hlp
setlocal enableextensions
set /a jinwei=0,mm=0,mn=0
for %%a in (lastans bu baoliu dot tmp_) do (set %%a=)
set "stra=%1"
set "strb=%2"
if not "%4"=="" (
  if "%4"=="0" (
    set dot=dot
  ) else (
    set baoliu=%4
  )
)
for /f "tokens=1,2 delims=." %%a in ("%stra%") do (
  set stral=%%a
  set strar=%%b
)
for /f "tokens=1,2 delims=." %%a in ("%strb%") do (
  set strbl=%%a
  set strbr=%%b
)
::如果不保留小数则跳过对小数部分的计算
if defined dot (
  set jiashu1=%stral%
  set jiashu2=%strbl%
  goto :agn
)
::如果没有小数则跳过对小数部分的计算
if "%strar%"=="" (
  if "%strbr%"=="" (
    set dot=dot
    set jiashu1=%stral%
    set jiashu2=%strbl%
    goto :agn
  )
)
::计算加数1的小数位数
set "tmp_=%strar%"
:cnt1
if defined tmp_ (
  set /a mm+=1
  set tmp_=%tmp_:~1%
  goto :cnt1
)
set "bu0=%mm%"
set "tmp_="
::计算加数2的小数位数
set "tmp_=%strbr%"
:cnt2
if defined tmp_ (
  set /a mn+=1
  set tmp_=%tmp_:~1%
  goto :cnt2
)
if %mn% gtr %mm% (set bu0=%mn%)
::将两个加数的小数对齐
for /l %%a in (1 1 %bu0%) do (call set bu=%%bu%%0)
set strar=%strar%%bu%
set strbr=%strbr%%bu%
call set strar=%%strar:~,%bu0%%%
call set strbr=%%strbr:~,%bu0%%%
set "bu="
::如果定义小数位数,则取定义的位数
if defined baoliu (
  for /l %%a in (1 1 %baoliu%) do (call set bu=%%bu%%0)
  call set strar=%strar%%%bu%%
  call set strbr=%strbr%%%bu%%
  call set "jiashu1=%stral%%%strar:~,%baoliu%%%"
  call set "jiashu2=%strbl%%%strbr:~,%baoliu%%%"
) else (
  set jiashu1=%stral%%strar%
  set jiashu2=%strbl%%strbr%
)
::计算
:agn
set /a "var=%jiashu1:~-1%+%jiashu2:~-1%+%jinwei%"
if %var% gtr 9 (set jinwei=1) else (set jinwei=0)
set "lastans=%var:~-1%%lastans%"
if not "%jiashu1:~0,-1%"=="" (
  set "jiashu1=%jiashu1:~0,-1%"
) else (
  set "jiashu1="
)
if not "%jiashu2:~0,-1%"=="" (
  set "jiashu2=%jiashu2:~0,-1%"
) else (
  set "jiashu2="
)
if defined jiashu1 (
  if defined jiashu2 (
    goto :agn
  ) else (
    call :count
  )
) else (
  if defined jiashu2 (
    set jiashu1=%jiashu2%
    call :count
  )
)
::对小数点进行定位
if not defined dot (
  if defined baoliu (
    call set "cn_ans=%jinwei%%%lastans:~0,-%baoliu%%%.%%lastans:~-%baoliu%%%"
  ) else (
    call set "cn_ans=%jinwei%%%lastans:~,-%bu0%%%.%%lastans:~-%bu0%%%"
  )
) else (
  set cn_ans=%jinwei%%lastans%
)
::对得数进行首位除0的处理
:cut0
if "%cn_ans:~,1%"=="0" (
  if not "%cn_ans:~1%"=="" (
    if not "%cn_ans:~1,1%"=="." (
      set "cn_ans=%cn_ans:~1%"
      goto :cut0
    )
  )
)
endlocal&set "%3=%cn_ans%"&goto :eof

::如果两个加数长度不一样,单独对长出来的部分进行计算
:count
set /a "var=%jiashu1:~-1%+%jinwei%"
if "%var:~0,-1%"=="1" (set jinwei=1) else (set jinwei=0)
set "lastans=%var:~-1%%lastans%"
if not "%jiashu1:~0,-1%"=="" (
  set "jiashu1=%jiashu1:~0,-1%"
  goto :count
)
goto :eof

:hlp
color 1f
echo.
echo  声明: 此脚本不支持负数的加法
echo.
echo  使用方法:
echo  把本批处理脚本复制到系统目录里
echo  不带参数运行本脚本 显示此帮助信息
echo.
echo  格式: call jiafa.bat 参数1 参数2 参数3 [参数4]
echo     参数1    为加数1
echo     参数2    为加数2
echo     参数3    为变量名
echo     [参数4]  可选参数,为保留小数的位数,如果空则保留原有小数
echo.
echo  例: call jiafa.bat 100.78965 123.45 ans 4
echo  意思为给变量 ans 赋值,其值等于100.78965与123.45的和,并保留四位小数
echo  结果为:224.2396
echo.&set/p= 按任意键退出...<nul
pause>nul&color&goto :eof

作者: moniuming     时间: 2009-2-9 16:42    标题: 减法函数


@echo off
rem Code By cn-dos moniuming 2009-02-09
if "%1"=="" goto :hlp
setlocal enableextensions
for %%a in (jie mm mn tm) do (set %%a=0)
for %%a in (baoliu fu last_ans m n no tmp_) do (set %%a=)
set beij=%1
set jian=%2
rem 把被减数首位除0
:cut1
if "%beij:~,1%"=="0" (
  if not "%beij:~1%"=="" (
    if not "%beij:~1,1%"=="." (
      set beij=%beij:~1%
      goto :cut1
)))
rem 把减数首位除0
:cut2
if "%jian:~,1%"=="0" (
  if not "%jian:~1%"=="" (
    if not "%jian:~1,1%"=="." (
      set jian=%jian:~1%
      goto :cut2
)))
rem 判断保留小数的位数
if not "%4"=="" (
  if "%4"=="0" (
    set no=no
  ) else (
    set baoliu=%4
  )
)
rem 把被减数和减数分为整数和小数两个部分
for /f "tokens=1,2 delims=." %%a in ("%beij%") do (
  set "stral=%%a"&set "strar=%%b"
)
for /f "tokens=1,2 delims=." %%a in ("%jian%") do (
  set "strbl=%%a"&set "strbr=%%b"
)
rem 如果不保留小数,则跳过对小数部分的计算
if defined no (
  set stra=%stral%
  set strb=%strbl%
  goto :agn1
)
rem 如果没有小数,则跳过对小数部分的计算
if "%strar%"=="" (
  if "%strbr%"=="" (
    set no=no
    set stra=%stral%
    set strb=%strbl%
    goto :agn1
  )
)
rem 计算被减数小数部分的位数
set "tmp_=%strar%"
:cnt1
if defined tmp_ (
  set /a mm+=1
  set tmp_=%tmp_:~1%
  goto :cnt1
)
set "bu0=%mm%"
rem 计算减数小数部分的位数
set "tmp_=%strbr%"
:cnt2
if defined tmp_ (
  set /a mn+=1
  set tmp_=%tmp_:~1%
  goto :cnt2
)
if %mn% gtr %mm% set bu0=%mn%
rem 将两个减数的小数部分对齐
for /l %%a in (1 1 %bu0%) do (call set bu=%%bu%%0)
set strar=%strar%%bu%
set strbr=%strbr%%bu%
call set strar=%%strar:~,%bu0%%%
call set strbr=%%strbr:~,%bu0%%%
set "bu="
rem 如果定义小数位数,则取定义的位数
if defined baoliu (
  for /l %%a in (1 1 %baoliu%) do (call set bu=%%bu%%0)
  call set strar=%strar%%%bu%%
  call set strbr=%strbr%%%bu%%
  call set stra=%stral%%%strar:~,%baoliu%%%
  call set strb=%strbl%%%strbr:~,%baoliu%%%
) else (
  set stra=%stral%%strar%
  set strb=%strbl%%strbr%
)
rem 计算被减数整数部分的位数
:agn1
set /a m+=1
if not "%stral:~1%"=="" (set stral=%stral:~1%&goto :agn1)
rem 计算减数整数部分的位数
:agn2
set /a n+=1
if not "%strbl:~1%"=="" (set strbl=%strbl:~1%&goto :agn2)
rem 判断正负
if %n% gtr %m% (
  set fu=fu
  set "beijshu=%strb%"
  set "jianshu=%stra%"
) else (
  if "%n%"=="%m%" (
    set tmp1=%stra%
    set tmp2=%strb%
    goto :pk
  ) else (
    set "beijshu=%stra%"
    set "jianshu=%strb%"
  )
)
rem 计算
:agn
set /a sth=%beijshu:~-1%-%jianshu:~-1%-%jie%
if %sth% lss 0 (
  set jie=1
  set /a sth+=10
) else (
  set jie=0
)
set last_ans=%sth%%last_ans%
if not "%beijshu:~,-1%"=="" (
  if not "%jianshu:~,-1%"=="" (
    set "beijshu=%beijshu:~,-1%"&set "jianshu=%jianshu:~,-1%"&goto :agn
  ) else (
    set "beijshu=%beijshu:~,-1%"&set "jianshu=0"&goto :agn
  )
)
rem 不保留小数的除0以及正负数处理
:cut0
if defined no (
  if not "%last_ans:~,1%"=="0" (
    if not defined fu (
      endlocal&set %3=%last_ans%&goto :eof
    ) else (
      endlocal&set %3=-%last_ans%&goto :eof
      )
  ) else (
    set last_ans=%last_ans:~1%
    goto :cut0
  )
)
rem 对小数点进行定位
if defined baoliu (
  call set last_ans=%%last_ans:~,-%baoliu%%%.%%last_ans:~-%baoliu%%%
) else (
  if bu0 gtr 0 (
    call set last_ans=%%last_ans:~,-%bu0%%%.%%last_ans:~-%bu0%%%
  )
)
rem 首位除0处理
:cut_
if "%last_ans:~,1%"=="0" (
  if not "%last_ans:~1,1%"=="." (
    set last_ans=%last_ans:~1%
    goto :cut_
  )
)
rem 正负处理
if defined fu (
  set last_ans=-%last_ans%
) else (
  set last_ans=%last_ans%
)
rem 退出脚本
endlocal&set %3=%last_ans%&goto :eof
rem 判断相同位数的大小
:pk
if %tmp1:~,1% gtr %tmp2:~,1% (
  set beijshu=%stra%
  set jianshu=%strb%
  goto :agn
) else (
  if %tmp2:~,1% gtr %tmp1:~,1% (
    set fu=fu
    set beijshu=%strb%
    set jianshu=%stra%
    goto :agn
  ) else (
    if not "%tmp1:~1%"=="" (
      set tmp1=%tmp1:~1%
      set tmp2=%tmp2:~1%
      goto :pk
    ) else (
      endlocal&set %3=0&goto :eof
    )
  )
)
:hlp
color 1f
echo.&echo  使用方法:
echo.&echo  1.把本批处理脚本命名为 jianfa.bat 复制到系统目录里
echo.&echo  2.不带参数运行本批处理脚本显示此帮助信息
echo.&echo  3.格式: call jianfa.bat 参数1 参数2 参数3 [参数4]
echo.&echo    参数1     为被减数
echo.&echo    参数2     为减数
echo.&echo    参数3     为变量名
echo.&echo    [参数4]   可选参数,为保留小数位数,如不选则保留原有小数.
echo.&echo  4.例: call jianfa.bat 100 123.456789 ans 2
echo.&echo    意思为给变量 ans 赋值,其值等于 100 减去 123.456789 的差,
echo.&echo    并保留两位小数,结果为: -23.45
echo.&set/p=   按任意键退出...<nul&pause>nul&color&goto :eof

作者: netbenton     时间: 2009-2-9 19:17
直接调用实用性不是很强,效率太低,
但是把各种功能存在库目录,以文件名简单说明用途,
并且文件内都有说明如何用,用在何处,和注意问题。
到用到时,再贴到BAT里,还是很好的,
毕竟一般人记不得那么多的代码,就算懂得,敲进来也费时。

我贴一个:
@echo off
goto :begin
f 100 l14 B8 00 B8 50 1F BF 00 02 B9 D0 07 BD 02 08 BA 50 00 AD 3C 20
f 114 l14 75 03 43 75 02 31 DB AA 4A 75 0D B8 0D 0A 29 DF 29 DD 31 DB
f 128 l0e AB BA 50 00 E2 E3 06 1F 89 E9 31 DB 90 90
t=100
g 134
w 200
q
:begin
if '%1'=='' set of=abcec.txt
debug %1%of%<%~f0>nul
start notepad %1%of%
goto :eof
::DOS下保存整个屏幕内容到文件,不支持中文(即图型模式)
::在图型模式将输出一个只有空行的文件
::用debug 取显示缓存区内容。输出%1指定的文件,
::如果%1为空,输出到abcec.txt
::用在程序输出有进度显示时,得到的最终屏幕信息


::注意:本函数调用必独立存为一个BAT文件调用,不可以放在BAT程序内作子程序。
::行 start notepad %1%of% 用作测试显示结果,用时可删除

[ Last edited by netbenton on 2009-4-12 at 23:08 ]
作者: plp626     时间: 2009-4-13 00:09
纵使我们的“过程代码”效率很低,幼稚也罢;但这是大家学习提高的一个平台,只要坚持,总会越来越精简,越来越高效,重复的工作必然会越来越少
作者: netbenton     时间: 2009-4-13 01:00    标题: 那好,我也来个加法的。


@echo off
set aa=%1
set bb=%2

::调用浮点加法函数
echo %time%
call :add cc aa bb
echo %time%

echo %cc%
goto :eof

:::::::::::::::::::::::::::::::
::浮点加法函数
:add <接收变量> <被加数变量> <加数变量>
::
::
::支持49位整数,49小数
::自动丢弃首尾无效0
::别看代码那么长,速度可不慢哦
:::::::::::::::::::::::::::::::

@echo off&setlocal enabledelayedexpansion
set za=!%2:*.=!
set xa=!%2:.%za%=!
set zb=!%3:*.=!
set xb=!%3:.%zb%=!
if "!zb!."=="!%3!." set zb=0
if "!za!."=="!%2!." set za=0
set za=%za%0
set zb=%zb%0
set zm=0
for /l %%a in (0,9,81) do (
        if "!za:~%%a,9!!zb:~%%a,9!"=="" goto :xok
        set "za%%a=!za:~%%a,9!000000000"
        set "zb%%a=!zb:~%%a,9!000000000"
        set za%%a=1!za%%a:~0,9!
        set zb%%a=1!zb%%a:~0,9!
        set zm=%%a
)
:xok
set zy=0
for /l %%a in (%zm%,-9,0) do (
        set/a "zz=!zy:~0,-9!+za%%a-1000000000+zb%%a-1000000000"
        set zy=000000000!zz!
        set zx=!zy:~-9!!zx!
)
set/a zm+=9,n=zm
for /l %%a in (1,1,%zm%) do if "!zx:~-%%a,1!"=="0" (set n=-%%a) else (goto :cok)
:cok
if "!zx:~-%zm%,%n%!" gtr "0" (set cc=.!zx:~-%zm%,%n%!) else (set cc=)

set zy=
for /l %%a in (9,9,81) do (
        if "!xa!!xb!"=="" goto :end
        set cc=!zy!!cc!
if defined xa (set "aa=000000000!xa:~-9!"&set xa=!xa:~0,-9!) else (set aa=000000000)
if defined xb (set "bb=000000000!xb:~-9!"&set xb=!xb:~0,-9!) else (set bb=000000000)
        set/a zz=!zz:~0,-9!+1!bb:~-9!-1000000000+1!aa:~-9!-1000000000
        set zy=000000000!zz!
        set zy=!zy:~-9!
)
:end
set cc=%zz%%cc%
if "%cc%"=="0" goto :endok
if "%cc:~0,2%"=="0." goto :endok
for /l %%a in (0,1,36) do if not "!cc:~%%a,1!"=="0" (set cc=!cc:~%%a!&goto :endok)
:endok
endlocal&set cc=%cc%&goto :eof
[ Last edited by netbenton on 2009-4-12 at 23:07 ]
作者: netbenton     时间: 2009-4-13 01:01    标题: 减法


@echo off&setlocal enabledelayedexpansion
set a=%1
set b=%2
echo %time%
call :sub c a b
echo %time%

echo %c%
goto :eof

:::::::::::::::::::::::::::::::
::浮点减法函数
:sub <接收变量> <被减数变量> <减数变量>
::
::
::支持49位整数,49小数
::自动丢弃首尾无效0
::别看代码那么长,速度可不慢哦
:::::::::::::::::::::::::::::::
@echo off&setlocal enabledelayedexpansion
set cc=0
set za=!%2:*.=!
set xa=!%2:.%za%=!
set zb=!%3:*.=!
set xb=!%3:.%zb%=!
if "!zb!."=="!%3!." set zb=0
if "!za!."=="!%2!." set za=0
set za=%za%0
set zb=%zb%0
::补0对齐
for /l %%a in (0,9,81) do (
if "!xa!!xb!"=="" set n=%%a&goto :bu0
if defined xa (set ya=!xa:~-9!!ya!&set xa=!xa:~0,-9!) else (set ya=000000000!ya!)
if defined xb (set yb=!xb:~-9!!yb!&set xb=!xb:~0,-9!) else (set yb=000000000!yb!)
)
:bu0
set ya=0000000000%ya%
set yb=0000000000%yb%
set xa=!ya:~-%n%!
set xb=!yb:~-%n%!
if "%xa%%za%" gtr "%xb%%zb%" (
        set zz=!za!&set xx=!xa!&set fh=
) else (
        set zz=!zb!&set xx=!xb!&set zb=!za!&set xb=!xa!&set fh=-
)

::预处理完成

for /l %%a in (0,9,81) do (
        if "!zz:~%%a,9!!zb:~%%a,9!"=="" goto :xok
        set "zz%%a=!zz:~%%a,9!000000000"
        set "zb%%a=!zb:~%%a,9!000000000"
        set zz%%a=1!zz%%a:~0,9!
        set zb%%a=1!zb%%a:~0,9!
        set zm=%%a
)
:xok
set jw=0
for /l %%a in (%zm%,-9,0) do (
        set/a "zz=jw+zz%%a-zb%%a"
        if !zz! lss 0 (set/a zz=1000000000+zz&set jw=-1) else (set jw=0)
        set zy=000000000!zz!
        set zx=!zy:~-9!!zx!
)
set/a zm+=9,n=zm
for /l %%a in (1,1,%zm%) do if "!zx:~-%%a,1!"=="0" (set n=-%%a) else (goto :cok)
:cok
if "!zx:~-%zm%,%n%!" gtr "0" (set cc=.!zx:~-%zm%,%n%!) else (set cc=)
set zy=
for /l %%a in (9,9,81) do (
        if "!xx!!xb!"=="" goto :end
        set cc=!zy!!cc!
if defined xx (set "aa=000000000!xx:~-9!"&set xx=!xx:~0,-9!) else (set aa=000000000)
if defined xb (set "bb=000000000!xb:~-9!"&set xb=!xb:~0,-9!) else (set bb=000000000)
        set/a zz=jw+1!aa:~-9!-1!bb:~-9!
        if !zz! lss 0 (set/a zz=1000000000+zz&set jw=-1) else (set jw=0)
        set zy=000000000!zz!
        set zy=!zy:~-9!
)
:end
set cc=%zz%%cc%
if "%cc%"=="0" goto :endok
if "%cc:~0,2%"=="0." goto :endok
for /l %%a in (0,1,36) do if not "!cc:~%%a,1!"=="0" (set cc=!cc:~%%a!&goto :endok)
:endok

endlocal&set %1=%fh%%cc%&goto :eof
[ Last edited by netbenton on 2009-4-12 at 23:07 ]
作者: netbenton     时间: 2009-4-13 01:07    标题: 乘法


@echo off
set aa=%1
set bb=%2

::调用浮点乘法函数
echo %time%
call :mul cc aa bb %3
echo %time%

echo %cc%
goto :eof
::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:mul <接收变量名> <被乘数> <乘数> [指定保留小数位]
::
::浮点乘法函数,头尾都可带0,支持乘积为:49位整数,49位小数。
::第一个参数为接收变量名,第二、三个为相乘数变量名,第四个批定要保留小数位数
::最大位数计算仅需12毫秒
::别看代码那么长,速度可不慢
::::::::::::::::::::::::::::::::::::::::::::::::::::::::
@echo off&setlocal enabledelayedexpansion
set cc=0
set ka=!%2:*.=!
set kb=!%3:*.=!

set maa=!%2:.=!
set mb=!%3:.=!

for /l %%a in (0,1,49) do if not "!maa:~%%a,1!"=="0" (set maa=!maa:~%%a!&goto :maaok)
:maaok

for /l %%a in (0,1,49) do if not "!mb:~%%a,1!"=="0" (set mb=!mb:~%%a!&goto :mbok)
:mbok

if "!kb!."=="!%3!." set kb=
if "!ka!."=="!%2!." set ka=
set kab=!kb!!ka!#
for /l %%a in (0,1,49) do if "!kab:~%%a,1!"=="#" (set kab=%%a&goto :lp1)
set mz=
:lp1
if defined mb (set al=!mb:~-4!
if "!al:~0,1!"=="0" set/a al=1!al!-10000
set mb=!mb:~0,-4!
) else (goto :endmul)
set ma=!maa!
set "cl= "
for /l %%a in (1,4,91) do (
        if not defined ma (goto :end1)
        set bl=!ma:~-4!
        if "!bl:~0,1!"=="0" set/a bl=1!bl!-10000
        set/a bl=!cl:~0,-%%a!+bl*al
        set ma=!ma:~0,-4!
        set cl=0000!cl:~-%%a!
        set cl=!bl!!cl:~-%%a!
)
:end1
set cl=%cl:~0,-1%%mz%
set mz=!mz!0000

set xa=%cc%
set xb=%cl%
set cc=
set zz=0
set zy=
for /l %%a in (9,9,81) do (
        if "!xa!!xb!"=="" goto :end2
        set cc=!zy!!cc!
if defined xa (set "aa=000000000!xa:~-9!"&set xa=!xa:~0,-9!) else (set aa=000000000)
if defined xb (set "bb=000000000!xb:~-9!"&set xb=!xb:~0,-9!) else (set bb=000000000)
        set/a zz=!zz:~0,-9!+1!bb:~-9!-1000000000+1!aa:~-9!-1000000000
        set zy=000000000!zz!
        set zy=!zy:~-9!
)
:end2
set cc=%zz%%cc%
if not %cc% gtr 0 goto :lp1
for /l %%a in (0,1,36) do if not "!cc:~%%a,1!"=="0" (set cc=!cc:~%%a!&goto :lp1)
goto :lp1

:endmul
if not %kab%==0 (
set ka=00000000000000000000000000000000000000000000000000%cc%
if "!cc:~0,-%kab%!"=="" (set cc=0.!ka:~-%kab%,%4!) else (set cc=!cc:~0,-%kab%!.!cc:~-%kab%,%4!)
)
endlocal&set %1=%cc%&goto :eof

作者: plp626     时间: 2009-4-13 07:03
看来大家都对论坛还是热爱,这长的代码得花些时间,

现在讨论制定个规范,方便他人阅读

:标签 // 注释 [参数1] [参数2] ...
干什么用的,参数的要求,等等,有个大致的格式
作者: uiopuiop     时间: 2009-6-7 04:18    标题: 短鸣和长鸣函数


usage:
call :beep
call :Long_Beep

goto eof


:: ----------------------------------------------------------------------

:beep
@echo 
goto :eof

:: ----------------------------------------------------------------------

:Long_Beep
choice /? >nul 2>&1 && ( echo zy|CHOICE /C YN /D Y /T 1 >nul )
choice /? >nul 2>&1 || call :beep
goto :eof

:: ----------------------------------------------------------------------

作者: uiopuiop     时间: 2009-6-7 04:20    标题: speak 函数


:speak \\ call :speak "speak the words ...."
mshta vbscript:createobject("sapi.spvoice").speak(%1)(window.close)
goto :eof
大家有好的函数,拿出来贴啊,不要藏着!!!

[ Last edited by uiopuiop on 2009-6-7 at 04:27 ]
作者: netbenton     时间: 2009-10-9 22:24
批处理浮点加法函数,再次精简提速了!
@echo off

set aa=%time%
for /l %%a in (1,1,1000) do call :_ADD 123456722222222222222890.3212222222222222222222222 1222222222222222222.789233333333333333333333333

set/p =计算1000次,用时:<nul&call :etime %aa% %time%

goto :eof
::前面为演示用

:::::::::::::::::::::::::::::::::::::
::浮点加法 call _ADD  <被加数> <加数> [返回变量]
:_ADD <num><num> [var]   //made by netbenton on 2009.10.09
::
::分别支持十进制的64位整数和小数,一次计算小于0.01秒
:::::::::::::::::::::::::::::::::::::
(setlocal enabledelayedexpansion
set L=&for /l %%a in (1,1,8) do set L=!L!00000000
for /f "tokens=1-3 delims=." %%a in ("!L!%1.!L!") do set at=%%a&set aw=%%b%%c
for /f "tokens=1-3 delims=." %%a in ("!L!%2.!L!") do set bt=%%a&set bw=%%b%%c
set a=!at:~-64!!aw:~,64!
set b=!bt:~-64!!bw:~,64!
set e=
set v=200000000
for /l %%a in (8,8,128)do set/a v=1!b:~-%%a,8!+1!a:~-%%a,8!+!v:~-9,-8!-2&set e=!v:~-8!!e!
set e=!e:0= !
for /f "tokens=*" %%a in ("!e:~,-64!.!e:~64!") do set e=%%~nxa
for %%a in ("!e: =0!") do endlocal&(if %3.==. (echo %%~a) else set %3=%%~a)
exit/b)

::计算时差函数
:etime <begin_time> <end_time> [return]  // By plp626 On 09-7-20
setlocal enabledelayedexpansion&set be=%~1;%~2&set be=!be::=;1!&set n=
for %%a in (%be:.=%)do set/a n+=1&set t!n!=%%a
set/a n=((t4-t1)*60+t5-t2)*6000+t6-t3,s=n/100,w=n%%100/10,f=n%%100%%10
endlocal&(if %3.==. (echo %s%.%w%%f%) else set %3=%n:-=%)&exit/b
[ Last edited by netbenton on 2009-10-10 at 06:04 ]
作者: plp626     时间: 2009-10-9 23:49
难得高手也对数学计算有兴趣,
那我写个除法的
@echo off
set begin=%time%

call:div 17 %random% 1000
call:etime %begin% %time%
rem 计算1000位 用时0.1秒
exit/b

rem -------------------------------- 子过程 -------------------------------------
:div <dividend> <divisor> <precision> [return]  //返回两个除数商的小数部分
Setlocal Enabledelayedexpansion&set/a b=%2,R=%1%%b*10&set "dc="
For /l %%z In (1 1 %3)Do (set/a d=R/b,R=R%%b*10&set dc=!dc!!d!)
endlocal&(if %4.==. (echo %dc%) else set %4=%dc%)&exit/b

:etime <begin_time> <end_time> [return] // 返回 两个时间点的差
setlocal enabledelayedexpansion&set be=%~1;%~2&set be=!be::=000;1!&set c=
(for %%a in (%be:.=%)do set/a c+=1&set t!c!=%%a)&set p=-8640000*("c>>31")
set/a c=(t4-t1)*360+(t5-t2)*6+t6-t3,c+=%p%,s=c/100,w=c%%100/10,f=c%%100%%10
endlocal&(if %3.==. (echo %s%.%w%%f%) else set %3=%c%)&exit/b

作者: k515413928     时间: 2009-10-19 15:39
初学批处理 也有楼主的一些想法 希望大家给点建议 下面的东西写了一整天喇
@echo off
setlocal Enabledelayedexpansion
::例如去某文本含有字符0的行并赋值给KK
::得到的值将寄存在KK1~ KK0为数组总个数
call :G_getstrrow 0 a.txt kk
echo %kk1%
echo %kk0%
pause
exit

::1.取文本行中指定的第N行 G_getrowstr 行数 文本 返回寄存变量
::2.取文本的总行数 G_getrows 文本 返回寄存变量
::3.合并多个字符串字符串 G_mergestr 返回寄存变量 字符串1 字符串2 ...
::4.将某字符串插入某文本尾部 G_inserttail 文本 字符串1 字符串2 ...
::5.统计文本长度G_counttxt 文本 返回长度变量
::6.统计变量长度G_countstr 变量 返回长度
::7.取文本出现行G_getstrrow 字符串 文本 寄存 (返回数组总个数保存

在0位)

::7
:G_getstrrow
set G_getstrrowsum=
set G_getstrrowtmp=
set G_getstrrowtmps=
set G_getstrrows=%3
for /f "delims=" %%i in ('findstr "%1" %2') do (
set /a "G_getstrrowsum+=1"
set G_getstrrowtmp=%%i
call :G_mergestr getstrrowtmpa %G_getstrrows% !G_getstrrowsum!
call :G_getstrrow_set !getstrrowtmpa!
)
set %G_getstrrows%0=!G_getstrrowsum!
set G_getstrrows=
set G_getstrrowtmp=
set G_getstrrowtmps=
goto :eof
:G_getstrrow_set
set G_getstrrowtmps=%1
set %G_getstrrowtmps%=!G_getstrrowtmp!
goto :eof


::6
:G_countstr
set G_string=%1
set G_countstr=%2
:G_countstrstart
if not "%G_string%"=="" (
set /a %G_countstr%+=1
set "G_string=%G_string:~1%"
goto G_countstrstart
)
set G_string=
set G_countstr=
goto :eof


::5
:G_counttxt
set G_counttxt=
set G_count=%2
for /f "delims=" %%i in (%1) do set G_counttxt=!G_counttxt!%%i
:G_counttxtstart
if not "%G_counttxt%"=="" (
set /a %G_count%+=1
set "G_counttxt=%G_counttxt:~1%"
goto G_counttxtstart
)
set G_count=
set G_counttxt=
goto :eof

::1
:G_getrowstr
set %3=
for /f "skip=%1 delims=" %%i in (%2) do (
set %3=%%i
goto :eof
)

::2
:G_getrows
set %2=0
for /f %%i in ('findstr /n .* %1') do (
set /a %2=%2+1
)
goto :eof

::3
:G_mergestr
set G_mergestr=%1
:G_getstr
if "%2"=="" goto mergestrend
set G_mergestrs=%G_mergestrs%%2
shift /2
goto G_getstr
:mergestrend
set %G_mergestr%=%G_mergestrs%
set G_mergestrs=
goto :eof

::4
:G_inserttail
set G_inserttailtxt=%1
:getG_inserttail
if "%2"=="" goto G_inserttailend
echo %2 >>%G_inserttailtxt%
shift /2
goto getG_inserttail
:G_inserttailend
set G_inserttailtxt=
goto :eof
[ Last edited by k515413928 on 2009-10-19 at 15:42 ]
作者: sfcctv     时间: 2009-11-16 23:09
可惜,批处理不能实现对象的封装。
作者: acaigg     时间: 2010-12-28 17:04
强烈支持,但我很菜。