2

我对 Perl 相当陌生,并且很难掌握以下密码输入代码片段的行为:

use Win32::Console;

my $StdIn = new Win32::Console(STD_INPUT_HANDLE);
my $Password = "";

$StdIn->Mode(ENABLE_PROCESSED_INPUT());
local $| = 1;

print "Enter Password: ";
while (my $Data = $StdIn->InputChar(1)) {
    if ("\r" eq $Data ) {
        last;
    } 
    elsif ("\ch" eq $Data ) {
        if ( "" ne chop( $Password )) {
            print "\ch \ch";
        }
        next;
    }
    $Password .=$Data;
    print "*";
}

while (my $Data = $StdIn->InputChar(1)) {
    print "\nShow password? [y/n] ";
    if ("n" eq $Data) {
        last;
    }
    elsif ("y" eq $Data) {
        print "\nPassword: $Password\n";
        last;
    }
}

基本上发生的情况是脚本提示用户输入密码并按*预期显示每个字符输入,但需要Enter按两次才能接受输入。但是,如果我删除第二个 while 循环(或用print $password语句替换),输入只需要按一次Enter.

我还注意到,在第二个 while 循环中,提示用户输入yn(无需按Enter)如果用户输入“y”,则Show password? [y/n]在显示密码之前重复该行。

对此行为的一些见解将不胜感激。

4

1 回答 1

3

第一个Enter让你脱离第一个while循环。然后第二个while循环在显示提示之前等待另一个字符。您应该在询问另一个字符之前显示提示(并且只显示一次)。

将事物分解为子例程有助于构建基本块。

use strict; use warnings;
use Win32::Console;

run();

sub run {
    my $StdIn = Win32::Console->new(STD_INPUT_HANDLE);
    $StdIn->Mode(ENABLE_PROCESSED_INPUT);

    my $Password = prompt_password($StdIn, "Enter Password: ", '*');

    if ( prompt_echo($StdIn, "\nShow password? [y/n] ") ) {
        print "\nPassword = $Password\n"
    }

    return;
}

sub prompt_password {
    my ($handle, $prompt, $mask) = @_;
    my ($Password);

    local $| = 1;
    print $prompt;

    $handle->Flush;

    while (my $Data = $handle->InputChar(1)) {
        last if "\r" eq $Data;

        if ("\ch" eq $Data ) {
            if ( "" ne chop( $Password )) {
                print "\ch \ch";
            }
            next;
        }

        $Password .= $Data;
        print $mask;
    }

    return $Password;
}

sub prompt_echo {
    my ($handle, $prompt) = @_;

    local $| = 1;
    print $prompt;
    $handle->Flush;

    while (my $Data = $handle->InputChar(1)) {
        return if "n" eq $Data;
        return 1 if "y" eq $Data;
    }

    return;
}
于 2012-06-27T02:36:11.233 回答