3

在阅读了关于 Jon Skeet 的有趣内容后,我发现了一个字符串,我猜它是在 ROT13 中。在检查我的猜测之前,我想我会尝试用 PHP 解密它。这是我所拥有的:

$string = "Vs lbh nfxrq Oehpr Fpuarvre gb qrpelcg guvf, ur'q pehfu lbhe fxhyy jvgu uvf ynhtu.";
$tokens = str_split($string);
for ($i = 1; $i <= sizeof($tokens); $i++) {
    $char = $tokens[$i-1];
    for ($c = 1; $c <= 13; $c++) {
        $char++;
    }
    echo $char;
}

我的字符串回来了AIaf you aasakaead ABruacae Sacahnaeaiaer to adaeacrypt tahais, ahae'ad acrusah your sakualal waitah ahais alaauagah.

我的逻辑似乎很接近,但显然是错误的。你能帮我吗?

4

5 回答 5

8

试试str_rot13

http://us.php.net/manual/en/function.str-rot13.php

无需自己制作,它是内置的。

于 2012-05-04T17:10:18.823 回答
3

这是一个工作实现,不使用嵌套循环。您也不需要将字符串拆分为数组,因为您可以像 PHP 中的字符串数组一样对单个字符进行索引。

您需要知道 ASCII 大写字符的范围是 65 - 99,小写字符的范围是 97 - 122。如果当前字符在其中一个范围内,请将 13 添加到其 ASCII 值。然后,您检查是否应该滚动到字母表的开头。如果你应该翻转,减去 26。

$string = "Vs lbh nfxrq Oehpr Fpuarvre gb qrpelcg guvf, ur'q pehfu lbhe fxhyy jvgu uvf ynhtu.";

for ($i = 0, $j = strlen( $string); $i < $j; $i++) 
{
    // Get the ASCII character for the current character
    $char = ord( $string[$i]); 

    // If that character is in the range A-Z or a-z, add 13 to its ASCII value
    if( ($char >= 65  && $char <= 90) || ($char >= 97 && $char <= 122)) 
    {
        $char += 13; 

        // If we should have wrapped around the alphabet, subtract 26
        if( $char > 122 || ( $char > 90 && ord( $string[$i]) <= 90)) 
        {
            $char -= 26;
        }
    }
    echo chr( $char);
}

这会产生:

如果你让布鲁斯施奈尔解密这个,他会用他的笑来粉碎你的头骨。

于 2012-05-04T17:31:12.167 回答
2

这不起作用,因为 z++ 是 aa

$letter = "z";
$letter++;
echo($letter);

返回 aa 不是 a

编辑:不使用内置的可能替代解决方案是

$string = "Vs lbh nfxrq Oehpr Fpuarvre gb qrpelcg guvf, ur'q pehfu lbhe fxhyy jvgu uvf ynhtu.";
$tokens = str_split($string);

foreach($tokens as $char)
{
    $ord = ord($char);
    if (($ord >=65 && $ord <=90 ) || ($ord >= 97 && $ord <= 122))
    $ord = $ord+13;
    if (($ord > 90 && $ord < 110) || $ord > 122)
        $ord = $ord - 26;
    echo (chr($ord));
}
于 2012-05-04T17:32:58.407 回答
2

如果您想自己执行此操作,而不是使用现有的解决方案,您需要检查每个字母是在字母表的前半部分还是后半部分。您不能天真地为每个字符添加 13(另外,您为什么要使用循环来添加 13?!)。您必须将 13 加到 AM 并从 NZ 中减去 13。您还必须不更改任何其他字符,例如空格。

更改您的代码以在更改之前检查每个字符的内容,以便您知道是否以及如何更改它。

于 2012-05-04T17:18:16.907 回答
0

派对晚了几年,但我想我会给你另一个选择

function rot13($string) {
    // split into array of ASCII values
    $string = array_map('ord', str_split($string));

    foreach ($string as $index => $char) {
        if (ctype_lower($char)) {
            // for lowercase subtract 97 to get character pos in alphabet
            $dec = ord('a');
        } elseif (ctype_upper($char)) {
            // for uppercase subtract 65 to get character pos in alphabet
            $dec = ord('A');
        } else {
            // preserve non-alphabetic chars
            $string[$index] = $char;
            continue;
        }
        // add 13 (mod 26) to the character
        $string[$index] = (($char - $dec + 13) % 26) + $dec;
    }

    // convert back to characters and glue back together
    return implode(array_map('chr', $string));
}
于 2018-01-20T02:16:59.380 回答