4

我正在尝试自学 Perl,我一直在苦苦挣扎……昨晚我做了一个程序来计算用户提供的一组数字的平均值,以便了解列表和用户输入,所以今天我想我会做一个摩尔斯电码解码器来了解哈希。我浏览了我买的那本书,它并没有很好地解释哈希......它实际上并没有很好地解释很多事情。任何帮助,将不胜感激!

无论如何,我想编写一个程序来解码用户输入的莫尔斯电码。所以用户会输入:

-.-.
.-
-
...
!
.-.
..-
.-..
.

感叹号将表示一个单独的词。此消息将向用户返回“Cats Rule”。下面是我到目前为止的代码......记住......我在 perl 中编程不到 24 小时哈哈。

代码:

  use 5.010;




my %morsecode=(
    '.-'    =>'A',  '-...'  =>'B',  '-.-.'  =>'C',  '-..'   =>'D',
    '.' =>'E',  '..-.'  =>'F',  '--.'   =>'G',  '....'  =>'H',
    '..'    =>'I',  '.---'  =>'J',  '-.-'   =>'K',  '.-..'  =>'L',
    '--'    =>'M',  '-.'    =>'N',  '---'   =>'O',  '.--.'  =>'P',
    '--.-'  =>'Q',  '.-.'   =>'R',  '...'   =>'S',  '-' =>'T',
    '..-'   =>'U',  '...-'  =>'V',  '.--'   =>'W',  '-..-'  =>'X',
    '-.--'  =>'Y',  '--..'  =>'Z',  '.----' =>'1',  '..---' =>'2',
    '...--' =>'3',  '....-' =>'4',  '.....' =>'5',  '-....' =>'6',
    '--...' =>'7',  '---..' =>'8',  '----.' =>'9',  '-----' =>'0',
    '.-.-.-'=>'.',  '--..--'=>',',  '---...'=>':',  '..--..'=>'?',
    '.----.'=>'\'', '-...-' =>'-',  '-..-.' =>'/',  '.-..-.'=>'\"'
);

my @k = keys %morsecode;
my @v = values %morsecode;

say "Enter a message in morse code separated by a line. Use the exclamation point (!) to separate words. Hit Control+D to signal the end of input.";
my @message = <STDIN>;
chomp @message;

my $decodedMessage = encode(@message);


sub encode {
    foreach @_ {
    if (@_ == @k) {
        return @k;

#This is where I am confused... I am going to have to add the values to an array, but I don't really know how to go about it.


        }
    else if(@_ == '!') {return ' '}
    else
    {
    return 'Input is not valid';
    }
    }
}
4

3 回答 3

6

您的代码包含两个语法错误:foreach需要一个列表来迭代;这意味着parens。与 C 和其他语言不同,Perl 不支持else if (...). 相反,使用elsif (...).

然后有一些语义错误:迭代的当前值存储在$_. 该数组@_包含调用函数的参数。

Perl 以不同的方式比较字符串和数字:

Strings Numbers
eq      ==
lt      <
gt      >
le      <=
ge      >=
ne      !=
cmp     <=>

为手头的任务使用正确的操作符,在这种情况下,是那些很复杂的操作符。

(您的代码@_ == @k做了一些事情,即在数字上下文中使用数组。这会产生元素的数量,然后进行比较。@_ == '!'这很奇怪。)


您真正想要做的是将输入的值映射到字符列表。您的哈希定义了这个映射,但我们想应用它。Perl 有一个map功能,它的工作方式类似于

@out_list = map { ACTION } @in_list;

在操作块内,当前值可用作$_.

我们希望我们的操作在哈希中查找适当的值,或者如果输入字符串没有映射,则包含错误消息:

my @letters = map { $morsecode{$_} // "<unknown code $_>" } @message;

这假设!在摩尔斯电码散列中注册为一个空格。

join然后,我们通过将它们与空字符串一起创建一个由这些字母组成的字符串:

my $translated_message = join "", @letters;

不要忘记打印结果!


完整代码:

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

my %morsecode=(
  '.-'    =>'A',  '-...'  =>'B',  '-.-.'  =>'C',  '-..'   =>'D',
  '.'     =>'E',  '..-.'  =>'F',  '--.'   =>'G',  '....'  =>'H',
  '..'    =>'I',  '.---'  =>'J',  '-.-'   =>'K',  '.-..'  =>'L',
  '--'    =>'M',  '-.'    =>'N',  '---'   =>'O',  '.--.'  =>'P',
  '--.-'  =>'Q',  '.-.'   =>'R',  '...'   =>'S',  '-'     =>'T',
  '..-'   =>'U',  '...-'  =>'V',  '.--'   =>'W',  '-..-'  =>'X',
  '-.--'  =>'Y',  '--..'  =>'Z',  '.----' =>'1',  '..---' =>'2',
  '...--' =>'3',  '....-' =>'4',  '.....' =>'5',  '-....' =>'6',
  '--...' =>'7',  '---..' =>'8',  '----.' =>'9',  '-----' =>'0',
  '.-.-.-'=>'.',  '--..--'=>',',  '---...'=>':',  '..--..'=>'?',
  '.----.'=>'\'', '-...-' =>'-',  '-..-.' =>'/',  '.-..-.'=>'"',
  '!'     =>' ',
);

say "Please type in your morse message:";
my @codes = <>;
chomp @codes;

my $message = join "", map { $morsecode{$_} // "<unknown code $_>" } @codes;

say "You said:";
say $message;

这会产生所需的输出。

于 2013-01-25T22:19:57.147 回答
3

学习如何和为什么有很多价值,但这里是什么:

sub encode {
  my $output;
  foreach my $symbol (@_) {
    my $letter = $morsecode{$symbol};
    die "Don't know how to decode $symbol" unless defined $letter;
    $output .= $letter
  }
  return $output;
}

甚至就像sub encode { join '', map $morsecode{$_}, @_ }您不太担心错误检查一样。@k并且@v不需要任何东西。

于 2013-01-25T22:09:33.117 回答
2

在散列中搜索值是一项非常繁重的工作,最好只使用反向散列。您可以使用Perl 中的reverse 函数轻松地反转散列。此外,在查看您的代码时,我发现您将能够输入小写输入。但是在搜索键的哈希时,这是区分大小写的。所以你需要大写你的输入。另外,我不太喜欢“结束”标准输入的方式。退出词/标志会更好更干净。

我对你的代码的看法

my %morsecode=(
    '.-'    =>'A',  '-...'  =>'B',  '-.-.'  =>'C',  '-..'   =>'D',
    '.' =>'E',  '..-.'  =>'F',  '--.'   =>'G',  '....'  =>'H',
    '..'    =>'I',  '.---'  =>'J',  '-.-'   =>'K',  '.-..'  =>'L',
    '--'    =>'M',  '-.'    =>'N',  '---'   =>'O',  '.--.'  =>'P',
    '--.-'  =>'Q',  '.-.'   =>'R',  '...'   =>'S',  '-' =>'T',
    '..-'   =>'U',  '...-'  =>'V',  '.--'   =>'W',  '-..-'  =>'X',
    '-.--'  =>'Y',  '--..'  =>'Z',  '.----' =>'1',  '..---' =>'2',
    '...--' =>'3',  '....-' =>'4',  '.....' =>'5',  '-....' =>'6',
    '--...' =>'7',  '---..' =>'8',  '----.' =>'9',  '-----' =>'0',
    '.-.-.-'=>'.',  '--..--'=>',',  '---...'=>':',  '..--..'=>'?',
    '.----.'=>'\'', '-...-' =>'-',  '-..-.' =>'/',  '.-..-.'=>'\"'
);
my %reversemorse = reverse %morsecode;
print "Enter a message\n";
chomp (my $message = <STDIN>);
print &encode($message);

sub encode{
    my $origmsg = shift(@_);
    my @letters = split('',$origmsg);
    my $morse = '';
    foreach $l(@letters)
    {
        $morse .= $reversemorse{uc($l)}." ";
    }    
    return $morse;
}
于 2013-01-25T22:33:22.547 回答