Las funciones en BATCH, como todos sabemos al igual que las matrices no existen, pero podemos simularlas . ¿Cómo así?
Pues sencillo, al simular una matriz lo que hacemos en BATCH es asignarle las dimensiones con mas variables en la variable XD, con lo que conocemos de “Setlocal enabledelayedexpansion” le agregamos al CODE la posibilidad del las retrasadas je je , así usando “!” para la llamada de estas y una variable llamada “Hola”, seria matriz en “Hola[%n%]” y su contenido seria invocado con “!Hola[%n%]!”, etc. Este tema ya lo hemos tratado si quieren saber más pues busquen en el foro o GOOGLE, siempre se encuentran muchas cosas interesantes.
¿Qué es una función en programación?
Según: http://www.alegsa.com.ar/Dic/funcion.php
En programación, una función es un grupo de instrucciones con un objetivo en particular y que se ejecuta al ser llamada desde otra función o procedimiento. Una función puede llamarse múltiples veces e incluso llamarse a sí misma (función recurrente).
Las funciones pueden recibir datos desde afuera al ser llamadas a través de los parámetros y deben entregar un resultado.
Se diferencian de los procedimientos porque estos no devuelven un resultado.
¿Cómo la implementamos en BATCH?
Bueno, a lo que estamos aquí, las funciones en BATCH podemos simularlas con algo común, el comando “CALL”, la diferencia con esto es que estableceríamos los parámetros con %1 %2 %*, definiríamos los campos y/o variables etc.
Podemos hacerlo de dos maneras, definiendo los campos antes del CALL (cosa que no recomiendo) o enviando los campos al llamar las etiquetas.
El primer ejemplo de función a mi estilo es:
Código:
@echo off
Setlocal enabledelayedexpansion
Set/p "num=Digito a multiplicar por 2: "
Call:Funcion_multiplicarPorDos resultado !num!
echo.!resultado!
pause>nul&exit
:Funcion_multiplicarPorDos
set/a "%1=%2*2"
goto:EOF
Como vemos la función multiplica por 2 y el resultado es pasado por parámetro para ser establecido en la función.
Ok, está entendido, pero ¿qué hay de diferencia con el GOTO?
Pues sencillo, el GOTO nos confunde al usarlo,no nos permite "%n" , y la mejor simulación nos la provee CALL, el EOF de CALL lo podemos usar para finalizar una función y continuemos el CODE donde estaba, al igual que una función de otros lenguajes.
Revisión, entonces, veamos pues algunos dirán, pero yo implemento funciones a cada rato, y bueno quizás sí, pero en BATCH esto no veo que muchos lo hagan, lo que si veo mucho es que usan como dice la definición, un procedimiento, el cual no retorna nada.
Con esta forma de hacer una función podemos simular las funciones de C# que se asignan por OUT.
Me gustaría agregar que por convicción al usar una función en las etiquetas pongan function_nombreDeLaFuncion o funcion_nombreDeLaFuncion para diferenciarlas de los procedimientos.
Por ejemplo este es un procedimiento:
Código:
@echo off
:: Send the length of the variable %MyVar%
:: to the variable %length%
:: by Secret_Doom
set #=%MyVar%
set length=0
:loop
if defined # (set #=%#:~1%&set /A length += 1&goto loop)
echo MyVar is %length% characters long!
Podemos ver que aquí, al finalizar solo se se lleno la variable length sin llamadas ni continuacion del CODE.
Veo tambien que los batcheros usamos esto mucho con call y casi como una funcion, e incluso hemos creado funciones, pero como comandos externos.
Bueno ya tememos una forma de como hacer funciones. ¿Pero qué sucede si queremos hacer que nuestra función acepte más parametros?
Sencillo solo usamos los %1, %2, %3, ..., %9 y usar pue shift. Hay un manualsito aqui en el foro.
pero ti tomamos esto y lo mejoramos con la misma funcion, que podemos ahora llamar metodo para esto XD.
podemos.....
¿Adivinen qué?
Emular la sobracarga de metodos.
Seguro dirán, ¿Cómo?
sencillo, pues en el metodo ponemos if´s que nos diran cuantos parametros tiene y asunto resuelto.
aqui un ejemplito creado por mi XD.
Código:
@echo off
setlocal enabledelayedexpansion
::Simulacio de la sobrecarga de metodos.
::Simulation of overloading methods.
::Created by Guerrerohgp
::My aim is to show that this is possible XD.
::Mi objetivo es mostrarles que esto es posible XD.
:ini
set/p "str=Ingrese parametros (maximo 3): "
if not defined str goto:ini
call:factorial !str!
pause>nul
:factorial
if not "%3"=="" (echo. Tres parametros!!) else (
if not "%2"=="" (echo. Dos parametros!!) else (
if not "%1"=="" (echo. Un Parametro!!)
)
)
goto:eof
bueno, ya esta XD. si tienen sugerencias de mas cosas que puedan ir qui me avisan.
-Funciones como archivos externos
Bueno, pues como mencione antes hemos creado varios archivos externos y que al igual que con las etiquetas los llamamos con call y si se encuentran en el system32 o un path registrado entre las variables de entorno de GUINDOWS o en el mismo directorio solo escribimos su nombre y ya, pero como sea enviamos los paramentros si es que los necesita.
Todo lo anterior dicho se puede implementar en archivos externos al bat, pero hay un que se yo con esto, a los bacheros no nos gusta crear tanto archivo mientras hacemos nuestros scripts, siempre intentamos hacer todo en un solo archivo así que bueno, lo podemos implementar como archivos externos como ya lo habian visto de seguro.
Diferentes tipos de inplementacion de funciones
Bueno, las funciones nos gustan porque son cool XD. Naa, mentira.
Las funciones son muy utiles, y podemos usar en batch estas virtudes que nos entregan, por ejemplo.
las funciones recursivas.
Algunos se preguntaran. ¿Guerrerohgp, qué es la recursividad?
Bueno mis queridos batcheros, la recursividad es, en la forma mas simple de expresarlo: Cuando una funcion se llama a si misma dento de ella.
y dirán, bueno y ¿Para que sirve?
Pues para usar la misma funcion varias veces, la usamos mas para recorrer arboles.
Por ejemplo tomemos nuestro disco duro.
hay un directorio raiz, que es C:\ generalmente.
pero si queremos saber cuantos directorios hay en C:, la unica forma de hacerlo es usando una funcion recursiva que entre en cada directorio y sume retornando un valor cada vez.
parece largo y tedioso, pero es la unica forma de hacerlo.
incluso el comando "tree" eso es lo que hace.
y bueno no es que para todo sea necesario pero aca unos ejemplitos mios XD.
Calcular Factorial de un numero.
Código:
@echo off
setlocal enabledelayedexpansion
::Created By Guerrerohgp
:ini
set num=0
set result=1
set/p "num=Ingrese su numero: "
if not defined num goto:ini
call:Function_factorial !num!
echo.El factorial de !num! es !result!
pause>nul
exit
:Function_factorial
if %1==1 goto:eof
set/a "result*=%1"
set/a "n=%1-1"
call:Function_factorial !n!
Par o impar.
Código:
@echo off
::Created By Guerrerohgp
setlocal enabledelayedexpansion
goto:ini
:impar
if "%1"=="0" (echo.Impar) else (
set/a "n=%1-1"
call:par !n!
)
goto:EOF
:par
if "%1"=="0" (echo.par) else (
set/a "n=%1-1"
call:impar !n!
)
goto:EOF
:ini
set num=0
set/p "num=Ingrese su numero: "
if not defined num goto:ini
call:par !num!
pause>nul
exit
La solucion a las torres de hanoi
Código:
@echo off
setlocal enabledelayedexpansion
:::::::::::::::::::::::::::::::::::::::::
::Script Para Resolver Torres de Hanoi.::
::Creado por Hugo Guerrero (Guerrerohgp):
:::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::
::Script to solve Hanoi Towers::
:: Created By Guerrerohgp ::
:: 2011 ::
::::::::::::::::::::::::::::::::
:ini
set/p "cantidad=Ingrese el numero de discos en la torre: "
if not defined cantidad goto:ini
if !cantidad! lss 0 goto:ini
call:algoritmoHanoi !cantidad! Torre_1 Torre_2 Torre_3
pause>nul
exit
:algoritmoHanoi
setlocal
if "%1" equ "0" goto:eof
set/a "cnt=%1-1"
call:algoritmoHanoi !cnt! %2 %4 %3
echo.Mover disco %1 de %2 a %4
call:algoritmoHanoi !cnt! %3 %2 %4
endlocal
goto:eof
¿Cuáles son las desventajas?
Los problemas son los siguientes, si usamos setlocal/endlocal dentro de una funcion y a la vez la recursividad y queremos conservar un valor para retorno no seria posible Ya que se borran con endlocal, osea no lo usamos, pero gastaremos mas memoria si las usamos asi sin mas.
Al tener las variables en las funciones recursivas con retorno, seguiran precentes fuera de la funcion y nos impedira usar estas variables para otros motivos ya que nos hace mas suceptibles a errores. (la solucion es ponerle siglas de la funcion y tratar que no sea un nombre común para no equivocarnos con otras variables).
Y saber que solo es una simulacion, la realidad de la simulacion depende de como la implementemos cada uno, asi que puede mejorarse y adaptarse a las situaciones. Al final solo depende de nosotros XD.
Código:
Otra vez me cayó el sueño, es casi madrugada asi que chao,
estoy medio bobo, cualquier ajuste o error me dicen para arreglarlo,
tambien si quieren que se agregen mas cosas.
Bye, bytes,
Guerrerohgp.