4

私はPerlを独学しようとしていて、苦労しています... 昨夜、リストとユーザー入力について学ぶために、ユーザーが提供した一連の数値の平均を計算するプログラムを作成したので、今日はそうしようと思いましたハッシュについて学ぶためのモールス信号デコーダ。購入した本に目を通しましたが、ハッシュについてはあまり詳しく説明されていません...実際には、多くのことをうまく説明していません。どんな助けでも大歓迎です!

とにかく、ユーザーが入力したモールス符号をデコードするプログラムを書きたいと思っています。したがって、ユーザーは次のように入力します。

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

感嘆符は別の単語を意味します。このメッセージは、ユーザーに「Cats Rule」を返します。以下は私がこれまでに持っているコードです...覚えておいてください..私は24時間以内にperlでプログラミングしています(笑)。

コード:

  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

コードには 2 つの構文エラーがあります。反復するにはリストforeachが必要です。これは括弧を意味します。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 関数を使用すると、ハッシュを簡単に逆にすることができます。また、あなたのコードを見ていると、小文字の入力を入力できることがわかりました。ただし、キーのハッシュを検索するときは、大文字と小文字が区別されます。したがって、入力を大文字にする必要があります。また、STDIN を「終了」する方法もあまり好きではありません。終了の単語/記号は、より良く、よりクリーンになります。

あなたのコードに対する私の見解

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 に答える