在 Perl 中,当用户输入无效输入时,如何要求用户重新输入?

发布于 2024-08-06 06:25:51 字数 622 浏览 8 评论 0原文

我有一个 Perl 子例程,它要求用户输入。我在该子例程本身内部执行检查输入的输入是否有效。

如果不是,我想再次调用子例程,让用户这次输入有效的输入。

我的子例程如下:

sub some_routine {    
    print "Enter a number to select   (1) Apple (2) Mango (3) grapes:"
    $value=STDIN;
    if($value =~ /[^1-3]/ ) {
        print "The input is not valid!";
        print "Do you want to continue selecting a fruit again (Y or N)?";
        $choice = STDIN;
        if( $choice eq "y") {
            ### I want to call the subroutine again to enter input ###
          } else {
            exit;
        }
    }
}

那么如何在其中递归子例程呢?

I've a Perl subroutine which asks input from User. I perform a check inside that subroutine itself whether the input entered is a valid input.

If it's not, I want to call the subroutine again to let the user enter a valid input this time.

My subroutine is as follows:

sub some_routine {    
    print "Enter a number to select   (1) Apple (2) Mango (3) grapes:"
    $value=STDIN;
    if($value =~ /[^1-3]/ ) {
        print "The input is not valid!";
        print "Do you want to continue selecting a fruit again (Y or N)?";
        $choice = STDIN;
        if( $choice eq "y") {
            ### I want to call the subroutine again to enter input ###
          } else {
            exit;
        }
    }
}

So how to recurse a subroutine in this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

梦里南柯 2024-08-13 06:25:52

使用 IO::Prompt 模块。

有了它,你可以这样写:

use IO::Prompt;
my @choices = qw( Apple Mango Grapes );
my $answer = prompt("Select :", "-menu" => \@choices);
print $answer;

Use IO::Prompt module.

With it you can write it like this:

use IO::Prompt;
my @choices = qw( Apple Mango Grapes );
my $answer = prompt("Select :", "-menu" => \@choices);
print $answer;
一念一轮回 2024-08-13 06:25:52

您的输入不是 eq“y”,而是“y\n”。

如果您将该行更改为 if ($choice =~ /^[Yy]/) 这将确保您在输入开头捕获 Y,而不用担心 y 或 yes 或 Y 或是的。

作为帮助,您应该使用 而不是单独使用 STDIN。始终添加 use strict;使用警告; 在顶部。这确保您需要使用以下方式定义 $value 和 $choice:

my $value = '';
my $choice = '';

正如其他人提到的。作为循环,这可能更简单。

#!/usr/bin/env perl
use strict;
use warnings;

some_routine();

sub some_routine {    
    my $value = '';
    my $choice = '';
    print "Enter a number to select   (1) Apple (2) Mango (3) grapes:";
    $value = <STDIN>;
    if($value !~ /[1-3]/ ) {
        print "The input is not valid!";
        print "Do you want to continue selecting a fruit again (Y or N)?";
        $choice = <STDIN>;
        if( $choice =~ /[Yy]/) {
            some_routine();
          } else {
            exit;
        }
    }
}

Your input is not eq "y" but "y\n".

If you change the line to if ($choice =~ /^[Yy]/) this will make sure you catch the Y at the start of the input and not worry about y or yes or Y or Yes.

As a help, you should use <STDIN> instead of STDIN alone. Always add use strict; use warnings; at the top. This makes sure you need to define $value and $choice using:

my $value = '';
my $choice = '';

As other people have mentioned. This is probably more straightforward as a loop.

#!/usr/bin/env perl
use strict;
use warnings;

some_routine();

sub some_routine {    
    my $value = '';
    my $choice = '';
    print "Enter a number to select   (1) Apple (2) Mango (3) grapes:";
    $value = <STDIN>;
    if($value !~ /[1-3]/ ) {
        print "The input is not valid!";
        print "Do you want to continue selecting a fruit again (Y or N)?";
        $choice = <STDIN>;
        if( $choice =~ /[Yy]/) {
            some_routine();
          } else {
            exit;
        }
    }
}
寄居人 2024-08-13 06:25:52

我使用的是一个简单的 goto:

START:
print "\n Name of the country (any one out of: china, japan or tokyo): ";
my $country_name = <>;
chomp($country_name);

unless ($country_name eq "china" || $country_name eq "japan" ||
    $country_name eq "tokyo") {
    print "\n Invalid country name entered. Please try again. \n";
    goto START;
}

这是一种非常幼稚的方法,但适合初学者。

What I use is a simple goto:

START:
print "\n Name of the country (any one out of: china, japan or tokyo): ";
my $country_name = <>;
chomp($country_name);

unless ($country_name eq "china" || $country_name eq "japan" ||
    $country_name eq "tokyo") {
    print "\n Invalid country name entered. Please try again. \n";
    goto START;
}

This is a very naive way but works for the beginners.

作死小能手 2024-08-13 06:25:51

要在 Perl 中递归地调用子例程,您只需从子例程本身调用子例程,就像在任何其他语言中一样:

sub factorial {
  my $num = shift;
  return 1 if $num < 2;
  return $num * factorial($num - 1);
}

但是,您实际上并不希望将递归用于“重复直到条件更改”场景。
这就是 while 循环的用途

my $valid;
while (!$valid) {
  print "Enter something: ";
  my $data = <STDIN>;
  $valid = validate($data);
  print "Bzzt!  Invalid - try again!\n" unless $valid;
}

To call a subroutine recursively in Perl, you just call the sub from itself, the same as in any other language:

sub factorial {
  my $num = shift;
  return 1 if $num < 2;
  return $num * factorial($num - 1);
}

However, you don't really want to use recursion for a "repeat until condition changes" scenario.
That's what while loops are for
:

my $valid;
while (!$valid) {
  print "Enter something: ";
  my $data = <STDIN>;
  $valid = validate($data);
  print "Bzzt!  Invalid - try again!\n" unless $valid;
}
情愿 2024-08-13 06:25:51

没有理由为此使用递归。一个简单的 while 循环就可以了。

my $input_valid = 0;
while( !$input_valid ) { 
    print "Enter some input: ";
    my $input = <STDIN>;
    $input_valid = validate_input( $input );
}

如果 validate_input 返回 0,则循环将重复。

There's no reason to use recursion for this. A simple while loop will do.

my $input_valid = 0;
while( !$input_valid ) { 
    print "Enter some input: ";
    my $input = <STDIN>;
    $input_valid = validate_input( $input );
}

If validate_input returns 0, the loop will repeat.

糖果控 2024-08-13 06:25:51

递归

sub select_fruit {    
    print "Enter a number to select   (1) Apple (2) Mango (3) grapes:"
    $value=<STDIN>;
    if($value =~ /[^1-3]/ ) {
        print "The input is not valid!";
        print "Do you want to continue selecting a fruit again (Y or N)?";
        $choice = <STDIN>;
        if( $choice eq "y") {
            $value = select_fruit();
          } else {
            exit;
        }
    }
    return $value;
}

goto - 尾调用优化 (TCO)

sub select_fruit {
    print "Enter a number to select   (1) Apple (2) Mango (3) grapes:"
    $value=<STDIN>;
    if($value =~ /[^1-3]/ ) {
        print "The input is not valid!";
        print "Do you want to continue selecting a fruit again (Y or N)?";
        $choice = <STDIN>;
        if( $choice eq "y") {
            goto &select_fruit;
          } else {
            exit;
        }
    }
    return $value;
}

或重做

sub select_fruit {
SELECT_FRUIT: {
       print "Enter a number to select   (1) Apple (2) Mango (3) grapes:"
       $value=<STDIN>;
       if($value =~ /[^1-3]/ ) {
           print "The input is not valid!";
           print "Do you want to continue selecting a fruit again (Y or N)?";
           $choice = <STDIN>;
           if( $choice eq "y") {
               redo SELECT_FRUIT; # same as goto SELECT_FRUIT;
             } else {
               exit;
            }
        }
        return $value;
    }
}

等等...

recursive

sub select_fruit {    
    print "Enter a number to select   (1) Apple (2) Mango (3) grapes:"
    $value=<STDIN>;
    if($value =~ /[^1-3]/ ) {
        print "The input is not valid!";
        print "Do you want to continue selecting a fruit again (Y or N)?";
        $choice = <STDIN>;
        if( $choice eq "y") {
            $value = select_fruit();
          } else {
            exit;
        }
    }
    return $value;
}

goto - Tail Call Optimization (TCO)

sub select_fruit {
    print "Enter a number to select   (1) Apple (2) Mango (3) grapes:"
    $value=<STDIN>;
    if($value =~ /[^1-3]/ ) {
        print "The input is not valid!";
        print "Do you want to continue selecting a fruit again (Y or N)?";
        $choice = <STDIN>;
        if( $choice eq "y") {
            goto &select_fruit;
          } else {
            exit;
        }
    }
    return $value;
}

or redo

sub select_fruit {
SELECT_FRUIT: {
       print "Enter a number to select   (1) Apple (2) Mango (3) grapes:"
       $value=<STDIN>;
       if($value =~ /[^1-3]/ ) {
           print "The input is not valid!";
           print "Do you want to continue selecting a fruit again (Y or N)?";
           $choice = <STDIN>;
           if( $choice eq "y") {
               redo SELECT_FRUIT; # same as goto SELECT_FRUIT;
             } else {
               exit;
            }
        }
        return $value;
    }
}

and so ...

☆獨立☆ 2024-08-13 06:25:51

调用例程的正确方法是

goto &some_routine;

......因为您拥有的是尾部调用 - 这是您在函数中执行的最后一件事。如果你正常调用它,你会为每次调用吃一个堆栈帧,并且内存分配会增加。像这样调用,您可以重复使用相同的堆栈帧。从你作为程序员的角度来看,这

return some_routine(@_);

与不吃内存是一样的。

适用于将自己称为最后一件事的例程 - 在其他情况下,您确实应该切换到其他人建议的 while 循环(并且,为了代码的吸引力,您可能想要无论如何都要这样做)。

The correct way to call the routine is

goto &some_routine;

...because what you have is a tail call - it's the last thing you do in your function. If you call it normally you eat a stack frame for each call and memory allocation goes up. Called like this, you re-use the same stack frame. From your perspective as a programmer, this is the same as

return some_routine(@_);

but without eating memory.

This only works for routines that call themselves as the last thing they do - in other cases, you should indeed be switching to the while loop that other people suggest (and, for code attractiveness, you may want to do that anyway).

迷离° 2024-08-13 06:25:51

编辑:出于各种原因(风格、性能等...),我强烈建议不要在这里进行递归调用,而是在 while 循环中检查它< /强>。

[原始回答者的免责声明]“从风格的角度来看,我不会在这里进行递归调用,而是在 while 循环中检查它,但我想在某种程度上,这也是一个品味问题。”

就使用递归而言,作为示例,您可以从函数内部调用该函数,如下所示:

sub get_positive_number {
    print "Please enter a positive number: ";
    my $number = <STDIN>;
    chomp $number;
    if ($number > 0) {
        return $number;
    }
    else {
        return get_positive_number();
    }
}

my $result = get_positive_number();
print "result: $result\n";

EDIT: For a variety of reasons (style, performance, etc...), I would strongly advise not do a recursive call here, though, but rather check it in a while loop.

[Original answerer's disclaimer] "From a style perspective, I would not do a recursive call here, though, but rather check it in a while loop, but I guess to a degree, that's a matter of taste as well."

As far as using recursion, as an example, you can just call the function from within the function, like so:

sub get_positive_number {
    print "Please enter a positive number: ";
    my $number = <STDIN>;
    chomp $number;
    if ($number > 0) {
        return $number;
    }
    else {
        return get_positive_number();
    }
}

my $result = get_positive_number();
print "result: $result\n";
一个人的旅程 2024-08-13 06:25:51
my $value;
until(defined $value = get_value()) {
  print"you didn't enter a valid value\n";
}

sub get_value {
 print "Enter a number to select   (1) Apple (2) Mango (3) grapes:"
    $value=<STDIN>;
    if($value =~ /[1-3]/ ) {
        return $value;
    } else {
        return undef;     
    }
}
my $value;
until(defined $value = get_value()) {
  print"you didn't enter a valid value\n";
}

sub get_value {
 print "Enter a number to select   (1) Apple (2) Mango (3) grapes:"
    $value=<STDIN>;
    if($value =~ /[1-3]/ ) {
        return $value;
    } else {
        return undef;     
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文