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

在Perl中,当用户输入无效输入时,如何要求用户重新输入?,perl,recursion,subroutine,Perl,Recursion,Subroutine,我有一个Perl子例程,它向用户请求输入。我在子程序内部检查输入的输入是否有效 如果不是,我想再次调用子例程,让用户这次输入一个有效的输入 我的子程序如下: 因此,如何在此递归子例程?编辑:出于各种原因(风格、性能等),我强烈建议不要在此处进行递归调用,而是在while循环中检查它 [原始回答者的免责声明]“从风格的角度来看,我不会在这里进行递归调用,而是在while循环中检查它,但我猜在某种程度上,这也是一个品味的问题。” 就使用递归而言,例如,您可以从函数内部调用函数,如下所示: sub g

我有一个Perl子例程,它向用户请求输入。我在子程序内部检查输入的输入是否有效

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

我的子程序如下:


因此,如何在此递归子例程?

编辑:出于各种原因(风格、性能等),我强烈建议不要在此处进行递归调用,而是在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";
sub-get\u正数{
打印“请输入正数:”;
我的$number=;
chomp$number;
如果($number>0){
返回$number;
}
否则{
返回get_正数();
}
}
my$result=获取正数值();
打印“结果:$result\n”;

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

my $input_valid = 0;
while( !$input_valid ) { 
    print "Enter some input: ";
    my $input = <STDIN>;
    $input_valid = validate_input( $input );
}
my$input\u valid=0;
而(!$input_有效){
打印“输入一些输入:”;
我的$input=;
$input\U valid=验证输入($input);
}

如果
validate\u input
返回0,循环将重复

要在Perl中递归调用子例程,只需从自身调用子例程,与在任何其他语言中调用子例程相同:

sub factorial {
  my $num = shift;
  return 1 if $num < 2;
  return $num * factorial($num - 1);
}
我的$value;
直到(定义的$value=get_value()){
打印“您没有输入有效值\n”;
}
子get_值{
打印“输入数字以选择(1)苹果(2)芒果(3)葡萄:”
$value=;
如果($value=~/[1-3]/){
返回$value;
}否则{
返回未定义;
}
}

调用例程的正确方法是

goto &some_routine;
…因为你有一个尾部调用-这是你在函数中做的最后一件事。如果您正常调用它,那么每次调用都会占用一个堆栈帧,内存分配就会增加。这样调用,可以重复使用相同的堆栈帧。从程序员的角度来看,这与

return some_routine(@_);
但是没有消耗记忆

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

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;
}
子选择_水果{
打印“输入数字以选择(1)苹果(2)芒果(3)葡萄:”
$value=;
如果($value=~/[^1-3]/){
打印“输入无效!”;
打印“是否要再次继续选择水果(Y或N)”;
$choice=;
if($choice eq“y”){
$value=选择水果();
}否则{
出口
}
}
返回$value;
}
goto-Tail呼叫优化(TCO)

sub-select\u水果{
打印“输入数字以选择(1)苹果(2)芒果(3)葡萄:”
$value=;
如果($value=~/[^1-3]/){
打印“输入无效!”;
打印“是否要再次继续选择水果(Y或N)”;
$choice=;
if($choice eq“y”){
goto&选择水果;
}否则{
出口
}
}
返回$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;
    }
}
sub-select\u水果{
选择水果:{
打印“输入数字以选择(1)苹果(2)芒果(3)葡萄:”
$value=;
如果($value=~/[^1-3]/){
打印“输入无效!”;
打印“是否要再次继续选择水果(Y或N)”;
$choice=;
if($choice eq“y”){
重做选择水果;#与转到选择水果相同;
}否则{
出口
}
}
返回$value;
}
}
所以…

使用模块

有了它,你可以这样写:

use IO::Prompt;
my @choices = qw( Apple Mango Grapes );
my $answer = prompt("Select :", "-menu" => \@choices);
print $answer;
您的输入不是eq“y”,而是“y\n”

如果将行更改为
If($choice=~/^[Yy]/)
,这将确保您在输入的开始处捕捉到Y,而不必担心Y或yes或Y或yes

作为帮助,您应该使用
,而不是单独使用
STDIN
。始终添加
使用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;
        }
    }
}
#/usr/bin/env perl
严格使用;
使用警告;
一些例行公事;
子例程{
我的美元价值=“”;
我的$choice='';
打印“输入数字以选择(1)苹果(2)芒果(3)葡萄:”;
$value=;
如果($value!~/[1-3]/){
打印“输入无效!”;
打印“是否要再次继续选择水果(Y或N)”;
$choice=;
如果($choice=~/[Yy]/){
一些例行公事;
}否则{
出口
}
}
}

我使用的是一个简单的转到:

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;
}
开始:
打印“\n国家名称(来自中国、日本或东京的任何国家):”;
我的$country_name=;
chomp($country_name);
除非($country_name eq“china”| |$country_name eq“japan”||
$country_name eq“东京”){
打印“\n输入的国家名称无效。请重试。\n”;
转到开始;
}

这是一种非常幼稚的方法,但对初学者有效。

为什么?也许是一段时间的循环?当我使用一些_例程时();什么也不发生递归(它不会返回要求用户再次输入以进行选择)。。。我该怎么办?大家好。。。谢谢你的回答。。。。我的上述评论是因为以下一件事:当我给出值“y”时$选项变为“y\n”,并且不会进入if sttmnt,因为它附加了一个换行符。。。递归
use IO::Prompt;
my @choices = qw( Apple Mango Grapes );
my $answer = prompt("Select :", "-menu" => \@choices);
print $answer;
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;
        }
    }
}
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;
}