2012-05-04 37 views
3

在閱讀了關於Jon Skeet的有趣的東西之後,我發現了一個字符串,我猜測它是在ROT13中。在檢查我的猜測之前,我想我會試着用PHP解密它。下面是我有什麼:用PHP實現ROT13

$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.

我的邏輯似乎很接近,但它顯然是錯誤的。你能幫我嗎?

+1

爲什麼它的價值(將其標記爲加密的人),rot13不是加密,而是密碼。加密涉及使用關鍵數據難以讀取的密鑰,從而難以不擁有加密密鑰而無法獲得數據。 – damianb

+2

@damianb好吧,它是關鍵的值爲13的ROT加密:)。雖然我可以理解[tag:encryption]標籤,但是它吸引了正確的人羣,人們可能會用這個詞來尋找問題/解決方案,它在這方面確實起作用。 –

回答

3

這是一個工作實現,不使用嵌套循環。您也不需要將字符串拆分爲數組,因爲您可以像使用PHP中的字符串一樣對單個字符進行索引。

您需要知道ASCII大寫字符範圍是65-99,而小寫字母範圍是97- 122.如果當前字符在其中一個範圍內,則將其值加上13。然後,你檢查你是否應該翻到字母表的開頭。如果您已經翻了個身,減去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); 
} 

這將產生:

如果你問布魯斯解密此,他會暗戀你的頭骨與他的笑聲。

7

嘗試str_rot13

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

沒有必要使自己的,它的內置。

+0

啊,謝謝。我不知道那件事。儘管如此,關鍵還是要鍛鍊我的大腦,所以我仍然想自己去做。 –

+0

@jezenthomas - 那麼,與rot13,空格是字面的... – damianb

2

如果你想自己做,而不是使用現有的解決方案,你需要檢查每個字母是否在字母表的前半部分或後半部分。你不能天真地爲每個角色添加13個(也是,爲什麼你使用一個循環來添加13?!)。您必須將13添加到A-M並從N-Z中減去13。你也必須,不要改變任何其他角色,如空間。

改變你的代碼來檢查每個字符的改變之前它是什麼,所以你知道是否以及如何改變它。

2

這不是工作因爲Z ++是AA

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

回報AA不是

編輯:不使用內置的是

$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)); 
} 
+0

這裏有更多的問題,比只是... ... – nickb

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)); 
}