Home > Software design >  perl script does not print after first run of do-while statement
perl script does not print after first run of do-while statement

Time:06-01

I am trying to make an script for a simple menu in a server using Perl, this menu has three options ranging from 1 to 3 and if you input any other number it should prompt you to input a number fron 1 to 3. The code is as folows:

sub main_menu ()
{
        system('clear');
        print ('########## BIENVENIDOS A TERMINAL SERVER DE GOSIT ##########\n\n\n\n\n
            Seleccione una accion:\n\n
                1) Administracion de dispositivos\n
                2) Gestion de backups\n
                3) Salir del Terminal Server\n\n\n
        Ingrese opcion:   ');
        $action = <>;
        do
        {
                if ($action < '1' || $action > '3')
                {
                        print (" Por favor seleccione una opcion valida:    ");
                        $action = <>;
                        print ("\n\n");
                }
                elsif ($action == '1')
                {
                        #admin_menu();
                        print ("to admin menu\n");
                }
                elsif ($action == '2')
                {
                        #backup_menu();
                        print ("to backup menu\n");
                }
                elsif ($action == '3')
                {
                        print ("Saliendo de TERMINAL SERVER\n\n");
                        exit
                }
        } until ($action == '1' || $action == '2' ||$action == '3' );
}

main_menu();

While testing this script if the user inputs a number greater than 3 or lower than 1 the error message is prompted but if later any input value is enterd the script ends, here are the tests I made:

Valid input 1

Valid input 2

Valid input 3

Invalid input 1

script misbehaviour

CodePudding user response:

Your problem is that your loop control and print statements separate when you put the retry function inside the if-clause. Then execution will continue from the first if-clause, skip over all the other elsifs and skip right to the end, where it will satisfy the until and exit.

You also try to use \n inside a single quoted string. That will not work, you need a double quoted string.

What you need is to have just one read statement, and just retry the whole loop when the read fails. Like this

use strict;
use warnings;

sub main_menu {
        while (1) {     # loop can only be exited manually
            system('clear');
            print '########## BIENVENIDOS A TERMINAL SERVER DE GOSIT ##########\n\n\n\n\n
            Seleccione una accion:\n\n
                1) Administracion de dispositivos\n
                2) Gestion de backups\n
                3) Salir del Terminal Server\n\n\n
        Ingrese opcion:   ';
            my $action = <>;
            no warnings 'numeric';    # disable numeric warnings

            if ($action == 1) {
                    print ("to admin menu\n");
            } elsif ($action == 2) {
                    print ("to backup menu\n");
            } elsif ($action == 3) {
                    print ("Saliendo de TERMINAL SERVER\n\n");
                    exit
            } else {
                    print (" Por favor seleccione una opcion valida.\n");
            }

            print "Press any key to continue...";    # needed to be able to read message
            <>;                                      # for pausing the screen
        };
}

main_menu();

Note the no warnings 'numeric' addition. This code relies on you running it with warnings off, or else you get warnings about numerical comparisons:

Argument "asd" isn't numeric in numeric eq (==) at ...

One way to fix it is to clean up the input and force it to be numerical, even when it is not. E.g.

$action =~ s/\D //g;          # remove non-numbers
$action = 0 unless $action;   # if "" turn it into 0

Or you can just ignore those warnings

no warnings 'numeric';
  • Related