问题描述

本文主要讲述如下几个问题:

  1. 什么是函数,怎么创建函数?

  2. 怎么调用一个函数?

  3. 函数是怎么工作的?

  4. 怎么向函数传递参数?

  5. 函数怎么返回值和返回一个局部变量的值。

一、创建函数(什么是函数)

  1. 函数以一个标签开始,并以goto:eof结束,如下:
  1. @echo off
  2. :myDosFunc - 函数的开始,用一个标签标识
  3. echo. 函数体,可以执行很多命令
  4. echo.
  5. echo.&pause&goto:eof

二、调用函数

call:函数名 [参数1,参数2,…]

三、函数怎么工作

调用函数的脚本将其分成两部分。

  1. main script: 从第一行开始并且以 GOTO:EOF命令结束
  2. 函数部分:由多个函数组成,由main script调用。
@echo off  
echo.开始调用函数  
call:myDosFunc  
echo.从函数返回myDosFunc  
echo.&pause&goto:eof  
::--------------------------------------------------------  
::-- 函数部分开始  
::--------------------------------------------------------  
:myDosFunc    - here starts my function identified by it`s label  
echo.  here the myDosFunc function is executing a group of commands  
echo.  it could do a lot of things  
goto:eof

四、怎么传递参数,并且在函数中获取参数的值

1.用空格或者逗号将参数分开

2.用双引号将带有空格的字符串参数括起来

 @echo off  
echo.going to execute myDosFunc with different arguments  
call:myDosFunc 100 YeePEE  
call:myDosFunc 100 "for me"  
call:myDosFunc 100,"for me"  
call:myDosFunc 100,for me  
echo.&pause&goto:eof  
::--------------------------------------------------------  
::-- Function section starts below here  
::--------------------------------------------------------  
:myDosFunc    - here starts my function identified by it's label  
echo.  
echo. here the myDosFunc function is executing a group of commands  
echo. it could do %~1 of things %~2.  
goto:eof

五、函数返回值

1.调用命令不像其他语言那样能有返回值,最常用的做法是在函数中将该值保存在全局变量中,调用结束后,直接用该全局变量。如下:

@echo off
set "var1=some hopefully not important string"  
echo.var1 before: %var1%  
call:myGetFunc  
echo.var1 after : %var1%  
echo.&pause&goto:eof
:myGetFunc    - get a value  
set "var1=DosTips"  
goto:eof

脚本输出如下:
var1 before: some hopefully not important string
var1 after : DosTips

2.通过引用返回值,调用者通过传递一个变量给函数来存储返回值

@echo off
set "var1=some hopefully not important string" 
call:myGetFunc var1  
echo.var1 after : %var1%  
echo.&pause&goto:eof

:myGetFunc    - passing a variable by reference  
set "%~1=DosTips"  
goto:eof

脚本输出如下:
var1 after : DosTips

返回局部变量值

1.怎么保证局部变量和全局变量不冲突,SETLOCAL命令能让处理器当做是局部变量,用ENDLOCAL解除局部变量。ENDLOCAL 会被自动调用,当批处理执行到文件末尾的时候,即GOTO:EOF。SETLOCAL可以很好的保护函数内与外面的变量不会冲突。

@echo off  
set "aStr=Expect no changed, even if used in function"  
set "var1=No change for this one.  Now what?"  
echo.aStr before: %aStr%  
echo.var1 before: %var1%  
call:myGetFunc var1  
echo.aStr after : %aStr%  
echo.var1 after : %var1%  
echo.&pause&goto:eof  
::--------------------------------------------------------  
::-- Function section starts below here  
::--------------------------------------------------------  
:myGetFunc    - passing a variable by reference  
SETLOCAL  
set "aStr=DosTips"  
set "%~1=%aStr%"  
ENDLOCAL  
goto:eof

脚本输出:
aStr before: Expect no changed, even if used in function
var1 before: No change for this one. Now what?
aStr after : Expect no changed, even if used in function
var1 after : No change for this one. Now what?

2.怎么跳过ENDLOCAL的屏障,返回局部变量值?

采用”变量扩充“,在SETLOCAL与ENDLOCAL之间的全局变量的值会备份,当退出ENDLOCAL,该值将恢复。让命令处理器来执行ENDLOCAL 和SET命令。

@echo off 
set "aStr=Expect no changed, even if used in function" 
set "var1=Expect changed" 
echo.aStr before: %aStr% 
echo.var1 before: %var1% 
call:myGetFunc var1 
echo.aStr after : %aStr% 
echo.var1 after : %var1% 
echo.&pause&goto:eof 
::——————————————————– 
::– Function section starts below here 
::——————————————————– 
:myGetFunc - passing a variable by reference 
SETLOCAL 
set "aStr=DosTips" 
( ENDLOCAL 
set "%~1=%aStr%" 
) 
goto:eof 
:myGetFunc2 - passing a variable by reference 
SETLOCAL 
set "aStr=DosTips" 
ENDLOCAL&set "%~1=%aStr%" &rem THIS ALSO WORKS FINE 
goto:eof

脚本输出:
aStr before: Expect no changed, even if used in function
var1 before: Expect changed
aStr after : Expect no changed, even if used in function
var1 after : DosTips

六、编写递归函数

  1. 让函数局部变量的变换对调用者是可见的,循环调用函数,让变量可重用。下面编写一个函数计算Fibonacci数列。
@echo off  
set "fst=0"  
set "fib=1"  
set "limit=1000000000"  
call:myFibo fib,%fst%,%limit%  
echo.The next Fibonacci number greater or equal %limit% is %fib%.  
echo.&pause&goto:eof  

::--------------------------------------------------------  
::-- Function section starts below here  
::--------------------------------------------------------  
:myFibo  -- calculate recursively the next Fibonacci number greater or equal to a limit  
::       -- %~1: return variable reference and current Fibonacci number  
::       -- %~2: previous value  
::       -- %~3: limit  
SETLOCAL  
set /a "Number1=%~1"  
set /a "Number2=%~2"  
set /a "Limit=%~3"  
set /a "NumberN=Number1 + Number2"  
if /i %NumberN% LSS %Limit% call:myFibo NumberN,%Number1%,%Limit%  
(ENDLOCAL  
    IF "%~1" NEQ "" SET "%~1=%NumberN%"  
)  
goto:eof