Recursividad en batch

Iniciado por Slikp, 20 Diciembre 2013, 00:11 AM

0 Miembros y 1 Visitante están viendo este tema.

Slikp

- Buenas quisiera pedirles ayuda con varias dudas que tengo ya que nunca programe en si y por simple curiosidad inicie con batch y he estado practicando o mejor dicho experimentando, en primer lugar no se si sea la forma correcta de llamarlo (recursividad) a lo que tengo en mente pero antes de preguntar sobre lo de la recursividad por favor espero me aclaren esta duda ya que para lo de la recursividad necesito entender esto que aun no logro decifrarlo y me da mucha curiosidad porque no siento que lo que hice sea muy efeciente que digamos.

- Les muestro lo que hice

Código (dos) [Seleccionar]


 @Echo OFF
color 0a
  set /p Ename=                 ¿ Este Equipo Sera Asignado a ?:
cls
       MODE CON cols=90 lines=40

echo  +-------------------------Departamento Asignado?-----------------------------------+
echo  +----------------------------------------------------------------------------------+
echo  + 1- Alta Tension T     + 2- Automatizacion     + 3- Part 11     + 4- Bare 1o      +
echo  +----------------------------------------------------------------------------------+
echo  + 5- Biblioteca Tecnica + 6-Bariven (Canp Ter)  + 7- C.A.I       + 8-C.C.A         +
echo  +----------------------------------------------------------------------------------+
echo  +----------------------------------------------------------------------------------+


echo:
set /p Ubicacion=           Seleccione La Ubicacion O Departamento De Este Equipo (Ingrese Un Numero):


if %Ubicacion%==1 goto 1
if %Ubicacion%==2 goto 2
if %Ubicacion%==3 goto 3

:1

echo Tu Respuesta Es %Ename%
echo Tu Otra Respuesta Es Alta Tension T
pause

:2

echo Tu Respuesta Es %Ename%
echo Tu Otra Respuesta Es Automatizacion
pause

:3

echo Tu Respuesta Es %Ename%
echo Tu Otra Respuesta Es Part 11
pause

   Exit


- Ok con esos 3 Goto se entiende el Proceso y con eso llegan las Dudas.

     Duda #1.  En realidad bajo el script que estoy Trabajando hay 45 Opciones por lo tanto tendria que realizar 45 Goto con 45 codigo similares porque practicamente todos los Goto son lo mismo con execcion del segundo Echo de cada Goto.

- Hay alguna forma de simplificar el codigo? Pense en los If Else pero basicamente tendria que hacer 40 y tantos Else... Por otro lado se me ocurrio otra idea aunque no se como hacerlo y tampoco se si se podra hacer así ya que lei sobre los Arreglos o Arrays pero no en batch si no en C, Sera que hay alguna manera de definir un Arreglo de 45 x 45 como una constante donde esten ya definidos las 45 opciones y capturar el numero de la opcion y mediante un For recorrer el arreglo y donde la posicion Y coinsida con el numero X capturado y se Imprima lo que este en este arreglo?

    Duda #2. Aqui es lo de la recusividad, hay alguna forma de mostrarle al usuario lo que hizo de manera que el compruebe lo que el mismo hizo y preguntar si es correcto o no y en caso de no ser correcto, volver denuevo al principio de todo el proceso y comenzar? y en caso de ser correcto todo continuar?

- En C segun lo que lei se puede hacer "Creo" mediante Funciones donde si no es correcto la recursividad te retorna nuevamente a la funcion principal y la si es correcta te permite continuar con los demas procesos de la funcion.

- Bueno por ahora eso, espero puedan aclararme esas dudas o si tienen una mejor forma de hacerlo pues bienvenida sea, pero segun mi logica eso es lo que se ocurre hacer.

Eleкtro

#1
Cita de: Slikp en 20 Diciembre 2013, 00:11 AMtodos los Goto son lo mismo con execcion del segundo Echo de cada Goto.

- Hay alguna forma de simplificar el codigo?

Este consejo es válido para cualquier lenguaje:
Si necesitas repetir código ...símplemente no lo hagas, evítalo, escribe un método para llamarlo las veces que necesites.
Repetir código es feo, muy feo, aunque la forma de simplificar código repetitivo en Batch tambien es igual de fea.

Cita de: Slikp en 20 Diciembre 2013, 00:11 AMSera que hay alguna manera de definir un Arreglo de 45 x 45 como una constante donde esten ya definidos las 45 opciones

¿Arrays en Batch? ...chorradas, creo que sigues sin ser consciente del 'lenguaje' tan simple que es Batch, no busques donde no hay.
Se puede llegar a simular un Array, pero nada más, es tontería seguir pensando en ello.

CitarDuda #2. Aqui es lo de la recusividad (...) preguntar si es correcto o no y en caso de no ser correcto, volver denuevo al principio de todo el proceso y comenzar?
En C (...) mediante Funciones donde si no es correcto la recursividad te retorna nuevamente a la funcion principal

No es necesario usar métodos recursivos para escribir código eficiente, además la recursividad no es algo bueno y se debe evitar siempre que sea posible, desde luego no es algo de lo que haya que abusar, aunque en Batch puede llegar a ser una pesadilla codear sin generar más recursividad de la que reálmente es necesaria ...así que tampoco importa mucho si hablamos de ese 'lenguaje' en particular, pero por otro lado algo que comparten todos los lenguajes es un límite de llamadas recursivas que puede provocar un error de desbordamiento (Overflow), ¿por ejemplo dices en C/C++ escribir una función que te mande a otro método sin terminar las instrucciones del bloque y por ende sin devolver un valor específico?, no hagas ni caso de las personas que "programen" así en otros lenguajes, por Dios.




Aquí tienes una forma de simplificar el código principal:

Código (dos) [Seleccionar]
@Echo OFF & Setlocal EnableDelayedExpansion


Set "Answers=Alta Tension T;Automatizacion;Part 11"
Set "Answer =" & REM aquí allmacenaré el "EName" seleccionado.


:SetAnswer
CLS
Choice.exe /C "123" /M "Seleccione La Ubicacion O Departamento De Este Equipo (Ingrese Un Numero): "
Call :GetAnswer "%ErrorLevel%"
Goto :Verify


:GetAnswer
Set /A "UserChoose=%~1"
Set /A "AnswerCount=0"

Echo+
Echo: Tu Respuesta Es '%UserChoose%'

For %%# in (%Answers: =[-_-]%) Do (
Set /A "AnswerCount+=1"
If !AnswerCount! EQU %UserChoose% (
Set "Answer=%%#"
Set "Answer=!Answer:[-_-]= !"
Echo: Tu Otra Respuesta Es '!Answer!'
Goto :EOF
)
)
Goto :OnError


:Verify
Echo+ | MORE
Choice.exe /M "Son correctos los datos?"
If %ErrorLevel% EQU 2 (
Goto :SetAnswer
) Else (
Goto :Continue
)


:OnError
Echo: [ERROR] No se ha encontrado la respuesta '%UserChoose%'
Pause&Exit


:Continue
REM Escribir código de continuación aquí...
Pause&Exit


Saludos








Slikp

#2
- Buenas ElektroSoft, te comento que probe tu script y tuve problemas con el Choice ya que no se reconocia como comando interno o externo, luego de indagar un poco di con la solucion en Xp ese comando no existe y segun fue reemplazado por Set /p, Sin embargo pude descargarlo y todo bien.

- Dicho eso quiero comentarte que tuve que cambiar en tu script el /M ya que me generaba errores y luego de buscar y buscar me di cuenta que era el /M y segun la documentacion de Choice /M no exite asi que los /M en tu script los reemplaze por /N, no se si es correcto lo que hice pero me funciono y sin ninguna complicacion ni error alguno al ejecutar las distintas instrucciones, por otro lado recuerdas que dije bajo el script que estoy trabajando tengo 45 opciones?

- Por lo que vi con choise solo puedo tener 10 opciones comenzando por el 0, pero si quiero marcar la opcion 11? como lo haria? ya que no puedo marcar 11 porque a penas tecleo UNO "1" se procesa la orden... Y tengo otra duda pero sera en otra ocasion espero puedas ayudarme con esto y Gracias de ante mano.

Eleкtro

#3
El comando choice en Windows XP, existe, en tu caso no se encontraba donde debería estar (quizás estés usando un Windows XP Lite, u otro motivo) pero por defecto viene incluido, y efectívamente la sintaxis del comando difiere de una version de Windows a otra, pero eso tiene facil solución, accediendo a la ayuda dle comando en tu versión de windows...

Choice /?

Como opciones del comando choice puedes usar valores numéricos desde el 0 hasta el 9, como valores alfabéticos desde la A a la Z, incluyendo caracteres de habla hispana como la ñ y la Ç trencada, áéíóú, àèìòù, así como äëïöü, lo que en total da posibilidad a más que 45 opciones.

Código (dos) [Seleccionar]
Choice.exe /C "¤€µ,¡¢£...Š•—,,‰‹"" /M "Selecciona una opcion"



No es un comando perfecto, no puedes usar "11", "12", !3", etc, esto es Batch.

Si prefieres hacerlo usando el comando Set /P para que todas las opciones sean numéricas, puedes hacerlo perféctamente, solo tienes que reemplazar el comando choice por Set /P, y reemplazar la variable ErrorLevel que uso cuando llamo a la función Getanswer, por la variable establecida por el comando Set /P.

Saludos








ivancea96

Gracias a vosotros, me vino la idea de llamar programas desde consola, cosa q aun nunca había hecho jaja

Slikp

#5
- Gracias por la ayuda que me has brindado ElektroSoft, Te comento que hice los cambios que me sugeristes pero surgio otro error y con mis pocos conocimientos no e podido dar con la solucion.

- En primer lugar hice respectivamente el cambio que me planteastes, pero al Set /p le pase el ErrorLevel Para asi no cambiar las demas variables ErrorLeval que ya estaban.

Citar
set /p Ename=                 ¿ Este Equipo Sera Asignado a ?:
cls

       MODE CON cols=150 lines=40

echo:
Setlocal EnableDelayedExpansion
    Set "Answers=Alta Tension T;Automatizacion;Bare 11;Bare 1o;Bariven San Tome;Biblioteca Tecnica;C.A.I;C.C.A;Cad;Sun Rant;Mart Trunt;"
    Set "Answer =" & REM aquí almacena La Respuesta.
:SetAnswer

echo  +-------------------------Departamento Asignado?-------------------------------+
echo  +-------------------------------------------------------------------------------------+
echo  + 1- Alta Tension T     + 2- Automatizacion     + 3- Part 11     + 4- Bare 1o +
echo  +-------------------------------------------------------------------------------------+
echo  + 5- Biblioteca Tecnica+ 6-Bariven (Canp Ter)+ 7- C.A.I        + 8-C.C.A---+
echo  +-------------------------------------------------------------------------------------+
echo  + 10- Cad---------------+11- Sun Rant----------+-12- Mart Trunt--------------+

         
  Set /p ErrorLevel=                       Seleccione La Ubicacion O Departamento De Este Equipo (Ingrese Un Numero):
   Call :GetAnswer "%ErrorLevel%"
   Goto :Verify
   
   
   :GetAnswer
   Set /A "UserChoose=%~1"
   Set /A "AnswerCount=0"
   
   Echo+
   Echo                                              El Equipo Sera Asignado a: %Ename%
   Echo:                                             Numero Seleccionado %UserChoose%
   
   For %%# in (%Answers: =[-_-]%) Do (
   Set /A "AnswerCount+=1"
   If !AnswerCount! EQU %UserChoose% (
   Set "Answer=%%#"
   Set "Answer=!Answer:[-_-]= !"
   Echo:                                             Departamento Asignado: !Answer!
   Goto :EOF
   )
   )
   Goto :OnError
   
   
   :Verify
   Echo+ | MORE
   choice.exe /M "                                                        Son correctos los datos Y o N? "
   If %ErrorLevel% EQU 2 (
       cls
   Goto :SetAnswer
   ) Else (
   Goto :Continue
   )
   
   
   :OnError
   Echo: [ERROR] No se ha encontrado la respuesta '%UserChoose%'
   Pause&Exit
   
REM Escribir código de continuación aquí...  
   :Continue
   
    Echo !...Continuacion del Programa...!
Pause&Exit


- Entonces en teoria todo deberia de funcionar bien ya que no es necesario cambiar el Otro Choice porque obviamente sirve para capturar cualquiera de las 2 opciones S/N pero al pareser algo esta mal ya que al llegar a la pregunta " Son correctos los datos Y o N? " Al teclear cualquiera me genera un error y se cierra el programa, intente cambiar esas lineas por esto.

Citar
:Verify
   Echo+ | MORE
Set /p comprueba=                                             Son correctos los datos Y o N?:
   If %comprueba%==n  Goto :SetAnswer
   If %comprueba%==s  Goto :Continue

- Y solo la opcion "n" me funciono pero la "s" a veces me dice acceso denegado y se termina el programa o en ocasiones me dice no se encontro el valor "X" donde "X" asumo yo que es ErrorLevel... E intente otras cosas pero sin exito, Que podria estar pasando?.

Eleкtro

#6
Citar   Set /p ErrorLevel=                       Seleccione La Ubicacion O Departamento De Este Equipo (Ingrese Un Numero):

   choice.exe /M "                                                        Son correctos los datos Y o N? "
   If %ErrorLevel% EQU 2 ...

La integridad del código está complétamente mal.

1. El mensaje del comando Set /P debes encerrarlo entre comillas dobles como en el ejemplo que te puse (Para evitar en el futuro posibles errores/fallos humanos con caracteres ilegales, como los parentesis que lleva tu mensaje).

2. La variable %ErrorLevel% es una variable dinámica que devuelve el código de salida del último comando procesado, pero tu la estas reemplazando por una variable local que se llama exáctamente igual,
por ese motivo la pregunta booleana del comando Choice no te va a devolver un código de salida (1/2), te va a devolver el valor numérico que usaste para definir tu propia variable ErrorLevel en el comando Set /P.

Por algo te dije que debias reemplazar dicha variable.
Para solucionarlo símplemente vuelve a seguir los pasos que te indiqué ...pero esta vez hazlo al pie de la letra, crea una variable con un nombre distinto para usar en el comando SET /P y usa ese mismo nombre de variable como parámetro de la función "GetAnswer", y así el otro Choice [Y/N] te funcionará con la variable %ErrorLevel% corriente.

Saludos!








Slikp

#7
- Muchas Gracias ElektroSoft ahora entiendo, en cuanto pueda pruebo y te comento... Por otra parte quisiera preguntarte si se puede hacer lo siguiente, claro hay otras formas de hacerlo (No mediante la programacion), pero por ahora necesito hacer lo siguiente seguro pensaras que me gusta complicarme la vida jaja.

- Bueno el caso es que tengo una carpeta con una Aplicacion "X" y en mi pendriver tengo un archivo que abre con dicha aplicacion, lo que pasa es que cada vez que ejecuto el archivo se abre la tipica ventana de Abrir Con y debo examinar en busca de la Aplicacion "X" para poder abrir el archivo correctamente, esto sucede por que no tengo la Aplicacion instalada y por ese motivo cada vez que intento abrir el archivo desde cualquier lugar debo especificarle con que aplicacion debe abrirse.

- Me podrias mostrar una manera en Batch para que el archivo abrar con la aplicacion directamente sin tener que pasar por el proceso de la ventana Abrir Con y examinar en busqueda del ejecutable de la aplicacion?.

Eleкtro

Cita de: Slikp en 23 Diciembre 2013, 01:55 AMesto sucede por que no tengo la Aplicacion instalada y por ese motivo cada vez que intento abrir el archivo desde cualquier lugar debo especificarle con que aplicacion debe abrirse.

Exacto, al no tener la aplicación instalada, no existe ninguna asociación establecida para ese tipo de archivo específico que intentas abrir...

Si tu escribes este comando:
Código (dos) [Seleccionar]
Start /B "" "Archivo.elek"

...Sin tener la aplicación asociada que pueda abrir archivos con extensión "elek", la shell no va a saber que hacer ...mas que preguntarte por la aplicación en cuestión.

Tienes dos soluciones:

1. Especificar el programa al usar el comando Start, y pasarle el archivo como parámetro:

Código (dos) [Seleccionar]
Start /B "Título cualquiera" "\..\Ruta del pendrive\Programa.exe" "\..\Ruta del Archivo.elek"

\..\ equivale al directorio Root de la ubicación actual desde la que se ejecuta el Script (Ejemplo: "C:\"), así que no deberías tener problemas para localizar los archivos necesarios.

2. Crear una asociación para ese tipo de archivo, en este caso "elek".

Código (dos) [Seleccionar]
Assoc ".elek"="ElektroSoft"
Ftype "ElektroSoft"=".\Notepad.exe"
REM O bien con soporte para recibir parámetros:
REM Ftype "ElektroSoft"=".\Notepad.exe" "%%1" %%*


Código (dos) [Seleccionar]
Start /B "" "Archivo.elek"

Saludos.