Foros del Web » Programación para mayores de 30 ;) » Programación General »

No terminar hasta que no se elija una opción valida

Estas en el tema de No terminar hasta que no se elija una opción valida en el foro de Programación General en Foros del Web. Buenas, Siempre me he preguntado si existe alguna forma de hacer un menu, en el cual hay opciones y que si no se elije ninguna ...
  #1 (permalink)  
Antiguo 30/06/2010, 02:21
Avatar de neodani  
Fecha de Ingreso: marzo-2007
Mensajes: 1.811
Antigüedad: 17 años, 2 meses
Puntos: 20
No terminar hasta que no se elija una opción valida

Buenas,

Siempre me he preguntado si existe alguna forma de hacer un menu, en el cual hay opciones y que si no se elije ninguna opción válida te vuelva aparecer el menú de forma indefinida, hasta que aciertes con la opción.

Actualmente cuando eligen una opción invalida se termina el programa y no vuelve aparecer el menú.

¿Se os ocurre alguna forma de hacerlo? con perl v5.8.8

Código PERL:
Ver original
  1. sub Crear_Nuevas_Stats {
  2.     local $host;
  3.  
  4.     print colored(" - Selecciona el hosting donde apunta la web: ('q' para salir)",'cyan'),"\n";
  5.     print "\t1) HosAPA01\n";
  6.     print "\t2) HosAPA02\n";
  7.     print "\t3) HosIIS01\n";
  8.     print "\t4) HosIIS02\n";
  9.     print "\t5) HosIIS03\n";
  10.  
  11.     chop ($host = <STDIN>);
  12.  
  13.     switch ($host) {
  14.         case "1"    { print "Seleccionaste HOSAPA01\n" }
  15.         case "2"    { print "Seleccionaste HOSAPA02\n" }
  16.         case "3"    { print "Seleccionaste HosIIS01\n" }
  17.         case "4"    { print "Seleccionaste HosIIS02\n" }
  18.         case "5"    { print "Seleccionaste HosIIS03\n" }
  19.         else     { print "Selecciona una opcion valida\n" }
  20.     }
  21. }

Muchas gracias de antemano.
  #2 (permalink)  
Antiguo 30/06/2010, 03:40
Colaborador
 
Fecha de Ingreso: mayo-2006
Ubicación: Valladolid
Mensajes: 524
Antigüedad: 18 años
Puntos: 11
Respuesta: No terminar hasta que no se elija una opción valida

En el foro de Perl en Español hemos tratado ese tema, alguna vez.

Por ejemplo, Menú por consola.

Pero depende del tipo de terminal que vayas a usar.
__________________
JF^D Perl Programming en Español
  #3 (permalink)  
Antiguo 30/06/2010, 04:10
Avatar de neodani  
Fecha de Ingreso: marzo-2007
Mensajes: 1.811
Antigüedad: 17 años, 2 meses
Puntos: 20
Respuesta: No terminar hasta que no se elija una opción valida

Cita:
Iniciado por jferrero Ver Mensaje
En el foro de Perl en Español hemos tratado ese tema, alguna vez.

Por ejemplo, Menú por consola.

Pero depende del tipo de terminal que vayas a usar.
Uhm... no me funcionó

Código PERL:
Ver original
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5. use diagnostics;
  6. use Term::Menu;
  7.  
  8. my $var  = 0;
  9. my $sede = 0;
  10. my $prompt = Term::Menu->new(
  11.     beforetext      => 'Por favor, elija una de las siguientes opciones:',
  12.     aftertext       => 'Introduzca la sede por favor  ',
  13.     nooptiontext    => 'No seleccionaste ninguna opcion',
  14.     toomanytries    => 'Inicia el programa nuevamente y pulse alguna tecla por favor ',
  15. );
  16.  
  17. my $answer = $prompt->menu(
  18.     resguardo     => ["resguardo",                1 ],
  19.     sqlaltas      => ["sqlaltas",                 2 ],
  20.     sqlcronograma => ["sqlcronogramas",           3 ],
  21.     Ayuda         => ["Ayuda sobre el  Programa", 4 ],
  22.     Salir         => ["Salir del Programa",       5 ],
  23. );
  24.  
  25. print "\n";
  26. print "$answer \n";
  27.  
  28. if ($answer eq 'resguardo') {
  29.     print "Has elegido sede resguardo ";
  30. }
  31. elsif ($answer eq 'sqlaltas') {
  32.     print "Has elegido sede sqlaltas ";
  33.     }

Error que devuelve


Can't locate Term/Menu.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.8.8 /usr/local/share/perl/5.8.8 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.8 /usr/share/perl/5.8 /usr/local/lib/site_perl .) at ./test.pl line 6.
BEGIN failed--compilation aborted at ./test.pl line 6 (#1)
(F) You said to do (or require, or use) a file that couldn't be
found. Perl looks for the file in all the locations mentioned in @INC,
unless the file name included the full path to the file. Perhaps you
need to set the PERL5LIB or PERL5OPT environment variable to say where
the extra library is, or maybe the script needs to add the library name
to @INC. Or maybe you just misspelled the name of the file. See
perlfunc/require and lib.

Uncaught exception from user code:
Can't locate Term/Menu.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.8.8 /usr/local/share/perl/5.8.8 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.8 /usr/share/perl/5.8 /usr/local/lib/site_perl .) at ./test.pl line 6.
BEGIN failed--compilation aborted at ./test.pl line 6.
at ./test.pl line 6

Gracias de antemano
  #4 (permalink)  
Antiguo 30/06/2010, 11:43
Colaborador
 
Fecha de Ingreso: mayo-2006
Ubicación: Valladolid
Mensajes: 524
Antigüedad: 18 años
Puntos: 11
Respuesta: No terminar hasta que no se elija una opción valida

El error indica que el módulo Term::Menu no está instalado en tu sistema.

Tienes que convertirte en root del sistema y ejecutar el comando

cpan Term::Menu

Si es la primera vez que lo ejecutas, te hará una serie de preguntas. Luego, él solo se conectará a CPAN, bajará el módulo, lo compilará (si es necesario), hará un test de integridad del resultado, generará las páginas de manual y, finalmente, lo instalará.
__________________
JF^D Perl Programming en Español
  #5 (permalink)  
Antiguo 01/07/2010, 01:21
Avatar de neodani  
Fecha de Ingreso: marzo-2007
Mensajes: 1.811
Antigüedad: 17 años, 2 meses
Puntos: 20
Respuesta: No terminar hasta que no se elija una opción valida

Cita:
Iniciado por jferrero Ver Mensaje
El error indica que el módulo Term::Menu no está instalado en tu sistema.

Tienes que convertirte en root del sistema y ejecutar el comando

cpan Term::Menu

Si es la primera vez que lo ejecutas, te hará una serie de preguntas. Luego, él solo se conectará a CPAN, bajará el módulo, lo compilará (si es necesario), hará un test de integridad del resultado, generará las páginas de manual y, finalmente, lo instalará.
Lo instalé, me funciona el script que postee arriba, sin embargo cuando pulso una opción que no existe, el programa termina sin volver a reproducir el menú

Código:
Por favor, elija una de las siguientes opciones:
      1) resguardo
      2) sqlaltas
      3) sqlcronogramas
      4) Ayuda sobre el  Programa
      5) Salir del Programa
Introduzca la sede por favor  8
No seleccionaste ninguna opcion
Inicia el programa nuevamente y pulse alguna tecla por favor

Use of uninitialized value in concatenation (.) or string at ./test.pl line 26,
        <STDIN> line 1 (#1)
    (W uninitialized) An undefined value was used as if it were already
    defined.  It was interpreted as a "" or a 0, but maybe it was a mistake.
    To suppress this warning assign a defined value to your variables.

    To help you figure out what was undefined, perl tells you what operation
    you used the undefined value in.  Note, however, that perl optimizes your
    program and the operation displayed in the warning may not necessarily
    appear literally in your program.  For example, "that $foo" is
    usually optimized into "that " . $foo, and the warning will refer to
    the concatenation (.) operator, even though there is no . in your
    program.


Use of uninitialized value in string eq at ./test.pl line 28, <STDIN> line 1 (#1)
Se puede hacer que repita el menu cuando pulso una opción distinta a las preestablecidas?

Muchas gracias de antemano!
  #6 (permalink)  
Antiguo 01/07/2010, 03:22
Colaborador
 
Fecha de Ingreso: mayo-2006
Ubicación: Valladolid
Mensajes: 524
Antigüedad: 18 años
Puntos: 11
Respuesta: No terminar hasta que no se elija una opción valida

Ya lo dice el manual del módulo: si el usuario elige una opción que no está en el menú, devolverá un valor indefinido.

Lo que puedes hacer es meter la llamada al menú dentro de un bucle que no termine mientras el usuario no haya metido un valor válido.

Código Perl:
Ver original
  1. do {
  2.  
  3.     # llamamos al menú
  4.  
  5. } until ($answer);
__________________
JF^D Perl Programming en Español
  #7 (permalink)  
Antiguo 01/07/2010, 05:05
Avatar de neodani  
Fecha de Ingreso: marzo-2007
Mensajes: 1.811
Antigüedad: 17 años, 2 meses
Puntos: 20
Respuesta: No terminar hasta que no se elija una opción valida

Cita:
Iniciado por jferrero Ver Mensaje
Ya lo dice el manual del módulo: si el usuario elige una opción que no está en el menú, devolverá un valor indefinido.

Lo que puedes hacer es meter la llamada al menú dentro de un bucle que no termine mientras el usuario no haya metido un valor válido.

Código Perl:
Ver original
  1. do {
  2.  
  3.     # llamamos al menú
  4.  
  5. } until ($answer);
Lo intenté como dijiste, pero me devuelve un error

Código PERL:
Ver original
  1. 1 #!/usr/bin/perl
  2.   2
  3.   3 use strict;
  4.   4 use warnings;
  5.   5 use diagnostics;
  6.   6 use Term::Menu;
  7.   7
  8.   8 my $var  = 0;
  9.   9 my $sede = 0;
  10.  10 #my $answer = 0;
  11.  11
  12.  12     my $prompt = Term::Menu->new(
  13.  13         beforetext      => 'Por favor, elija una de las siguientes opciones:',
  14.  14         aftertext       => 'Introduzca la sede por favor  ',
  15.  15         nooptiontext    => 'No seleccionaste ninguna opcion',
  16.  16         toomanytries    => 'Inicia el programa nuevamente y pulse alguna tecla por favor ',
  17.  17     );
  18.  18 do {
  19.  19
  20.  20     my $answer = $prompt->menu(
  21.  21         resguardo     => ["resguardo",                1 ],
  22.  22         sqlaltas      => ["sqlaltas",                 2 ],
  23.  23         sqlcronograma => ["sqlcronogramas",           3 ],
  24.  24         Ayuda         => ["Ayuda sobre el  Programa", 4 ],
  25.  25         Salir         => ["Salir del Programa",       5 ],
  26.  26     );
  27.  27 } until ($answer);
  28.  28
  29.  29 print "\n";
  30.  30 print "$answer \n";
  31.  31
  32.  32 if ($answer eq 'resguardo') {
  33.  33     print "Has elegido sede resguardo ";
  34.  34 }
  35.  35 elsif ($answer eq 'sqlaltas') {
  36.  36     print "Has elegido sede sqlaltas ";
  37.  37     }


Código:
Global symbol "$answer" requires explicit package name at ./test.pl line 27.
Global symbol "$answer" requires explicit package name at ./test.pl line 30.
Global symbol "$answer" requires explicit package name at ./test.pl line 32.
Global symbol "$answer" requires explicit package name at ./test.pl line 35.
Execution of ./test.pl aborted due to compilation errors (#1)
    (F) You've said "use strict vars", which indicates that all variables
    must either be lexically scoped (using "my"), declared beforehand using
    "our", or explicitly qualified to say which package the global variable
    is in (using "::").

Uncaught exception from user code:
        Global symbol "$answer" requires explicit package name at ./test.pl line 27.
Global symbol "$answer" requires explicit package name at ./test.pl line 30.
Global symbol "$answer" requires explicit package name at ./test.pl line 32.
Global symbol "$answer" requires explicit package name at ./test.pl line 35.
Execution of ./test.pl aborted due to compilation errors.
 at ./test.pl line 37
root@monitor:/home/dperez# vim test.pl

Y si declaro la variable en la linea 10
10 my $answer = 0;

No me devuelve ningún error, pero me pregunta continuamente las opciones del menú, aunque elija una correcta, no entiendo porque se comporta así


Código:
Por favor, elija una de las siguientes opciones:
      1) resguardo
      2) sqlaltas
      3) sqlcronogramas
      4) Ayuda sobre el  Programa
      5) Salir del Programa
Introduzca la sede por favor  3
Por favor, elija una de las siguientes opciones:
      1) resguardo
      2) sqlaltas
      3) sqlcronogramas
      4) Ayuda sobre el  Programa
      5) Salir del Programa
Introduzca la sede por favor  9
No seleccionaste ninguna opcion
Inicia el programa nuevamente y pulse alguna tecla por favor
Por favor, elija una de las siguientes opciones:
      1) resguardo
      2) sqlaltas
      3) sqlcronogramas
      4) Ayuda sobre el  Programa
      5) Salir del Programa
Introduzca la sede por favor  1
Por favor, elija una de las siguientes opciones:
      1) resguardo
      2) sqlaltas
      3) sqlcronogramas
      4) Ayuda sobre el  Programa
      5) Salir del Programa
Introduzca la sede por favor
  #8 (permalink)  
Antiguo 01/07/2010, 11:11
Colaborador
 
Fecha de Ingreso: mayo-2006
Ubicación: Valladolid
Mensajes: 524
Antigüedad: 18 años
Puntos: 11
Respuesta: No terminar hasta que no se elija una opción valida

Debes quitar el my() de la línea 20.

En la línea 10 estabas, correctamente, definiendo la variable local $answer.

Pero en la 20 estabas definiendo "otra" "nueva" variable local $answer, que será local a las llaves donde se encuentra (el bucle do()).

Por eso también fallaba sin la línea 10: until() no sabía a qué variable $answer te estabas refiriendo porque la definías dentro, en la línea 20, y no es conocida fuera, ni siquiera en un until() pegado al bloque.

Código Perl:
Ver original
  1. my $respuesta;
  2.  
  3. do {
  4.     $respuesta = ... # presentamos el menú
  5.     # ...
  6. } until ($respuesta);
En este ejemplo, $respuesta de las líneas 4 y 6 se refieren a la única variable definida en la línea 1.

En Perl hay que tener claro el contexto o ámbito en que se mueven las variables. Puede ser lioso, pero es muy potente cuando quieres auténticas variables locales en sitios muy pequeños, que no quieres que influyan para nada en un código que está muchas líneas más allá.
__________________
JF^D Perl Programming en Español
  #9 (permalink)  
Antiguo 01/07/2010, 12:20
Avatar de neodani  
Fecha de Ingreso: marzo-2007
Mensajes: 1.811
Antigüedad: 17 años, 2 meses
Puntos: 20
Respuesta: No terminar hasta que no se elija una opción valida

Cita:
Iniciado por jferrero Ver Mensaje
Debes quitar el my() de la línea 20.

En la línea 10 estabas, correctamente, definiendo la variable local $answer.

Pero en la 20 estabas definiendo "otra" "nueva" variable local $answer, que será local a las llaves donde se encuentra (el bucle do()).

Por eso también fallaba sin la línea 10: until() no sabía a qué variable $answer te estabas refiriendo porque la definías dentro, en la línea 20, y no es conocida fuera, ni siquiera en un until() pegado al bloque.

Código Perl:
Ver original
  1. my $respuesta;
  2.  
  3. do {
  4.     $respuesta = ... # presentamos el menú
  5.     # ...
  6. } until ($respuesta);
En este ejemplo, $respuesta de las líneas 4 y 6 se refieren a la única variable definida en la línea 1.

En Perl hay que tener claro el contexto o ámbito en que se mueven las variables. Puede ser lioso, pero es muy potente cuando quieres auténticas variables locales en sitios muy pequeños, que no quieres que influyan para nada en un código que está muchas líneas más allá.
Muchas gracias de nuevo!

Pensaba que my variable, era la definición global y para definir una variable de forma local había poner local(variable).
  #10 (permalink)  
Antiguo 02/07/2010, 02:17
Avatar de neodani  
Fecha de Ingreso: marzo-2007
Mensajes: 1.811
Antigüedad: 17 años, 2 meses
Puntos: 20
Respuesta: No terminar hasta que no se elija una opción valida

Buenas,

Una pregunta mas sobre el menú, sabéis si existe la posibilidad de colorear la opción del menu? linea 15


Código PERL:
Ver original
  1. 1 #!/usr/bin/perl
  2.   2
  3.   3 use strict;
  4.   4 use warnings;
  5.   5 use diagnostics;
  6.   6 use Term::Menu;
  7.   7
  8.   8 my $answer = 0;
  9.   9
  10.  10     my $prompt = Term::Menu->new(
  11.  11         beforetext      => '',
  12.  12         aftertext       => 'Introduce una opcion por favor --> ',
  13.  13         nooptiontext    => '',
  14.  14         toomanytries    => "\nSeleccionaste una opcion no valida",
  15.  15         toomanytries    => colored("\nSeleccionaste una opcion no valida", 'bold red'),
  16.  16     );
  17.  17 do {
  18.  18
  19.  19     $answer = $prompt->menu(
  20.  20         resguardo     => ["resguardo",                1 ],
  21.  21         sqlaltas      => ["sqlaltas",                 2 ],
  22.  22         sqlcronograma => ["sqlcronogramas",           3 ],
  23.  23         Ayuda         => ["Ayuda sobre el  Programa", 4 ],
  24.  24         Salir         => ["Salir del Programa",       5 ],
  25.  25     );
  26.  26 } until ($answer);
  27.  27
  28.  28 print "\n";
  29.  29 print "$answer \n";
  30.  30
  31.  31 if ($answer eq 'resguardo') {
  32.  32     print "Has elegido sede resguardo ";
  33.  33 }
  34.  34 elsif ($answer eq 'sqlaltas') {
  35.  35     print "Has elegido sede sqlaltas ";
  36.  36     }


Lo probé con
toomanytries => colored("\nSeleccionaste una opcion no valida", 'bold red'),

Pero me arroja un error, imagino que no está permitido hacerlo así...

Undefined subroutine &main::colored called at ./test.pl line 10 (#1)
(F) The subroutine indicated hasn't been defined, or if it was, it has
since been undefined.

Uncaught exception from user code:
Undefined subroutine &main::colored called at ./test.pl line 10.
at ./test.pl line 10


Muchas gracias de antemano!
  #11 (permalink)  
Antiguo 02/07/2010, 17:03
Colaborador
 
Fecha de Ingreso: mayo-2006
Ubicación: Valladolid
Mensajes: 524
Antigüedad: 18 años
Puntos: 11
Respuesta: No terminar hasta que no se elija una opción valida

El error dice que Perl no tiene ni idea de dónde está definida la función colored().

Te falta por cargar el módulo Term::ANSIColor, con un use.
__________________
JF^D Perl Programming en Español
  #12 (permalink)  
Antiguo 05/07/2010, 09:36
Avatar de neodani  
Fecha de Ingreso: marzo-2007
Mensajes: 1.811
Antigüedad: 17 años, 2 meses
Puntos: 20
Respuesta: No terminar hasta que no se elija una opción valida

Cita:
Iniciado por jferrero Ver Mensaje
El error dice que Perl no tiene ni idea de dónde está definida la función colored().

Te falta por cargar el módulo Term::ANSIColor, con un use.
Ostras! es verdad, me descuidé. Gracias ;)

Etiquetas: terminar
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 11:26.