PHP 摩尔斯电码转换器


PHP Morse code converter

我正在用PHP编写一个基本的莫尔斯电码转换器,它可以获取字符串并将其转换为莫尔斯电码。它使用关联数组、foreach 循环和 for 循环。它可以工作,除了由于某种原因,它在每个转换字符后输出等效的摩尔斯电码"0"。我不知道 0 是从哪里来的。如果我从关联数组中删除 0,没有问题,但我也希望能够转换数字。如果有人能够给我一些反馈,那将不胜感激。

这是代码:

<?php
$string = "dog";
$string_lower = strtolower($string);
$assoc_array = array(
    "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"=>"--..", 
    "0"=>"-----",
    "1"=>".----", 
    "2"=>"..---", 
    "3"=>"...--", 
    "4"=>"....-", 
    "5"=>".....", 
    "6"=>"-....", 
    "7"=>"--...", 
    "8"=>"---..", 
    "9"=>"----.",
    "."=>".-.-.-",
    ","=>"--..--",
    "?"=>"..--..",
    "/"=>"-..-.",
    " "=>" ");
    for($i=0;$i<strlen($string_lower);$i++){
        foreach($assoc_array as $letter => $code){
            if($letter == $string_lower[$i]){
                echo "$code<br/>";
            }
        }
    }
?>

主要问题是你做的"更多"超过了必要的。当您可以使用字符串从中获取所需的数据时,无需像这样循环遍历$assoc_array

这也使用更少的资源,因为您不是从a-z 0-9循环,而是只循环所需的字母/数字/空格的确切数量。

/*Rest of your code above*/
for($i=0;$i<strlen($string_lower);$i++){
    echo (isset($assoc_array[$string_lower[$i]])) ? $assoc_array[$string_lower[$i]] . '<br />' : 'ERROR';       
} 

由于您的数组包含从a-z0-9的所有内容,因此您可以轻松地调用所需的字母,而不必担心丢失数据。

编辑:添加了isset()检查,几乎不需要,因为$assoc_array涵盖了每个需要的字母/数字,但安全总比抱歉好。(感谢@Farkie提醒我)

最简单的解决方法很简单,就是在回显后添加一个"中断":

foreach($assoc_array as $letter => $code){
                if($letter == $string_lower[$i]){
                        echo "$code<br/>";
                        break;
                }
        }

真正的问题是 0 的计算结果为 false,这意味着当它循环时,它将是一个 truey (false == false)。

您可以通过执行相同的(===)匹配来更好地解决它:

foreach($assoc_array as $letter => $code){
                if($letter === $string_lower[$i]){
                        echo "$code<br/>";
                        break;
                }
        }
你也可以

使用一些php函数式编程,比如array_reduce()函数 http://php.net/manual/en/function.array-reduce.php

避免所有这些丑陋的 for 循环并大大简化您的代码:

$convert = function($carry, $item) {
    $table = array(
        "a" => ".-",
        "b" => "-...",
        "c" => "-.-.",
        "d" => "-..",
        "g" => "--.",
        "o" => "---");
    // Get the correspondent value for the given letter
    $morse = $table[$item];
    // Return the string with appended morse character
    return $carry . $morse;
};
// Split 'dog' into an array, then apply a reduce to convert it to morse
array_reduce(str_split('dog'), $convert);
// ➜  ~ php morse.php                                                     
// -..-----.

我知道自从问题发布和给出答案以来已经有一段时间了。我想我会添加我为将来发现这个问题的人编写的这个功能。

法典

/**
 * Convert string to morse
 *
 * @param string $string
 * @return string
 */
function str_to_morse(string $string) {
    // Make the string lowercase and create an array of the characters
    $stringParts = str_split(strtolower($string));
    // Define the dictionary
    $morseDictionary = [
        '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' => '--..',
        '0' => '-----',
        '1' => '.----',
        '2' => '..---',
        '3' => '...--',
        '4' => '....-',
        '5' => '.....',
        '6' => '-....',
        '7' => '--...',
        '8' => '---..',
        '9' => '----.',
        '.' => '.-.-.-',
        ',' => '--..--',
        '?' => '..--..',
        '/' => '-..-.',
        ' ' => ' ',
    ];
    $morse = '';
    foreach ($stringParts as $stringPart) {
        if (array_key_exists($stringPart, $morseDictionary)) {
            $morse .= $morseDictionary[$stringPart] . '<br />';
        }
    }
    return $morse;
}

这似乎是 PHP 语言最早出现的摩尔斯电码编码/解码问题,所以我想这是表明 PHP 具有可以使用关联数组翻译子字符串的本机函数的最佳位置。

strtr()将寻找最长的排位赛并替换找到的子字符串。 与str_replace()不同,strtr()不会更换替代品。 preg_技术似乎没有必要用于这项任务。

一旦你的输入字符串强制为小写(以匹配你的查找/转换数组键),并且每个字符之间有某种分隔字符,你就不需要循环——只需要strtr()

摩尔斯编码代码:(演示)

$string = "d o g";
echo strtr($string, CHAR_TO_MORSE);
// output: -.. --- --.
反转翻译

就像翻转查找/翻译数组一样简单。

摩尔斯解码代码(演示)

$string = "-.. --- --.";
echo strtr($string, array_flip(CHAR_TO_MORSE));
// output: d o g

查找常量(基于 asker 的翻译数组)可以像这样声明:

const CHAR_TO_MORSE = [
    "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" => "--..",  "0" => "-----",  "1" => ".----",  "2" => "..---",  "3" => "...--", 
    "4" => "....-", "5" => ".....",  "6" => "-....",  "7" => "--...",  "8" => "---..", 
    "9" => "----.", "." => ".-.-.-", "," => "--..--", "?" => "..--..", "/" => "-..-.",
];