我正在编写一个将莫尔斯电码消息解码为纯文本的函数。我遇到的问题是它没有在需要的地方添加空格。请记住,每个莫尔斯电码字符/字母均以空格分隔,每个完整单词均以 3 个空格分隔。我希望该函数在检测到莫尔斯电码中连续 3 个空格时向纯文本添加一个空格。我实在想不通,所以才来这里。
这是现在的功能。
public function decode($morseCode)
{
// 1 space between characters, 3 spaces between words
// split the string
$morseArray = preg_split('/\s+/', $morseCode, -1);
$plainText = '';
$blankSpaceCount = 0;
// set each string as a morse code character
foreach ($morseArray as $morseChar)
{
if ($morseChar != ' ')
{
// check if the morsecode character is in the array
if(isset($this->plainTextsByMorseCode[$morseChar]))
{
// if it is, convert it to the corresponding plain text
$plainText .= $this->plainTextsByMorseCode[$morseChar];
$blankSpaceCount = 0;
}
}
else {
$blankSpaceCount++;
if ($blankSpaceCount === 3)
{
$plainText .= ' '; // Append a single blank space
$blankSpaceCount = 0;
}
}
}
return trim($plainText);
}
如果有帮助,我正在尝试解码的短语如下:
-.-- --- ..- ... .... .- .-.. .-.. -. --- - .--. .- ... ...
上面写着“YOU SHALL NOT PASS”,你可以清楚地看到单词之间的三个空格以及字母之间的单个空格。
$morsecode='your morse code';
//empty array for decode words
$decoded_words=[];
//split the code in words on 3 spaces
$morse_words=explode(' ',$morsecode); //3 spaces
//loop the words
foreach($morse_words as $word){
//empty string for decoded characters
$plain_word='';
//split the word into characters on 1 space
$morse_chars=explode(' ',$word); //1 space
//loop the characters, decode and add to the plain word string
foreach($morse_chars as $char){
$plain_word.=decode_morse_character($char);
}
//Add decoded word to the words array
$decoded_words[]=$plain_word;
}
//implode the decoded_words array with a space between every word
$decoded=implode(' ',$decoded_words);
正如@Thefourthbird所指出的,您正在使用空格(无论数量多少)分成一个数组,然后您尝试在此之后再次计算空格。这是无关紧要的,因为您已经将单词解析为字母数组。
这个简单的测试说明了您的逻辑中的错误以及将密码分解为单词数组的正确正则表达式。
<?php
$morseCode = '-.-- --- ..- ... .... .- .-.. .-.. -. --- - .--. .- ... ...';
$morseArray = preg_split('/\s{3}/', $morseCode, -1);
var_dump($morseArray);
输出为:
array(4) {
[0]=>
string(12) "-.-- --- ..-"
[1]=>
string(21) "... .... .- .-.. .-.."
[2]=>
string(8) "-. --- -"
[3]=>
string(15) ".--. .- ... ..."
}
一旦获得单词数组,您只需转换为字母,并为单词数组中除最后一个单词之外的所有单词添加一个空格。
拆分后,这部分始终为 true
if ($morseChar != ' ')
,因此您不会到达 else 子句。
这是另一种做法,将莫尔斯电码映射到纯文本字符,首先在 3 个空格上爆炸,然后在单个空格上爆炸。
public function decode($morseCode)
{
$decodedWords = [];
foreach (explode(' ', $morseCode) as $morseWord) {
$decodedWords[] = implode('', array_map(
fn($morse) => $this->plainTextsByMorseCode[$morse] ?? '',
explode(' ', $morseWord)
));
}
return implode(' ', $decodedWords);
}
输出将是
YOU SHALL NOT PASS
不必费心创建任何临时数组并进行条件迭代和其他此类卷积。
您正在通过利用查找数组将规则格式的字符串转换为另一个字符串 - 这是
preg_replace_callback()
的理想场景。
代码:(演示)
class MyMorse
{
private function plainTextsByMorseCode(string $morseChar): string
{
$lookup = [
'.-' => 'A',
'....' => 'H',
'.-..' => 'L',
'-.' => 'N',
'---' => 'O',
'.--.' => 'P',
'...' => 'S',
'-' => 'T',
'..-' => 'U',
'-.--' => 'Y',
];
return $lookup[$morseChar] ?? ''; // or throw an exception if not found
}
public function decode(string $morseCode): string
{
return preg_replace_callback(
'/ ?(\S+)| {3}/',
fn($m) => ctype_space($m[0]) ? ' ' : $this->plainTextsByMorseCode($m[1]),
$morseCode
);
}
}
致电:
$obj = new MyMorse();
var_export(
$obj->decode('-.-- --- ..- ... .... .- .-.. .-.. -. --- - .--. .- ... ...')
);
输出(使用
var_export()
显示没有挥之不去/不需要的空格):
'YOU SHALL NOT PASS'
正则表达式模式匹配非空白字符序列之前的可选空格并捕获可见字符;或者匹配 3 个连续空格。回调函数中,如果匹配的只是空格,则返回单个空格(单词分隔符);否则翻译序列,省略前导空格,并返回字母。