2014-01-18 61 views
3

我想對字符串執行此搜索和替換,例如password如何用「d」替換「a」,用「e」替換「b」,用「f」替換「c」。 。 。 「x」帶「a」,「y」帶「b」,「z」帶「c」?

正如您從問題中可以理解的那樣,替換後字符串應該變成sdvvzrug

但不幸的是下面的代碼輸出bbbbcaab

$search = range("a", "z"); 
$replace = array_merge(range("d", "z"), range("a", "c")); 
echo str_replace($search, $replace, "password"); 

什麼可導致此問題?起初我懷疑使用數組中str_replace,所以我用了一個循環,並試圖一次更換一個字符:

$search = range("a", "z"); 
$replace = array_merge(range("d", "z"), range("a", "c")); 
$str = "password"; 
    for($i = 0; $i < 26; $i++) 
    { 
    $str = str_replace($search[$i], $replace[$i], $str); 
    } 
echo $str; 

要我徹底失望,結果仍然相同。我做錯了什麼,我該如何取得正確的結果?

+2

看到一個正確的實現:http://www.php.net/manual/en/function.str-rot13.php#107475'str_rot('password',3);' – Federkun

+1

如果你還喜歡做字符替換,嘗試使用strtr而不是str_replace。 – TwilightSun

+1

這通常稱爲[凱撒密碼](https://en.wikipedia.org/wiki/Caesar_cipher)。 – icktoofay

回答

2

其他答案已經解釋你如何能做到這一點,所以我將重點部分。

所以,你for -loop是相同的:

$str = str_replace('a', 'd', $str); 
$str = str_replace('b', 'e', $str); 
$str = str_replace('c', 'f', $str); 
$str = str_replace('d', 'g', $str); 
$str = str_replace('e', 'h', $str); 
$str = str_replace('f', 'i', $str); 
$str = str_replace('g', 'j', $str); 
// ... 
$str = str_replace('z', 'c', $str); 

正如你所看到的,這種字母「通過掃蕩」的:a獲取與d替換,後來d被替換g,後來g被替換爲j。問題是,當您將d替換爲g時,無論d是代表原來的d還是最初的a。每個str_replace正在丟棄信息;第一行之後,你不能告訴字符串是否ddd原是add,或原本dad,而當你改變dg,你ggg而不是dgggdg或諸如此類的東西。

只有一個str_replace版本的結果相同的原因是str_replace與您的循環做同樣的事情:它只是迭代搜索數組,執行替換,並不能確保它永遠不會「重新替換「一個子串。這就是爲什麼你需要使用專門爲此設計的方法,如strtr

1

在這裏,我們走了,

$search = range("a", "z"); 
$replace = array_merge(range("d", "z"), range("a", "c")); 
$str = "password"; 
$newstr = ''; 
for($i = 0; $i < strlen($str); $i++) 
{ 
    $key = array_search($str[$i],$search); 
    $newstr .= $replace[$key]; 
}  
echo $newstr; 

DEMO.

1

str_replace不按順序全部更換,無論字符串是否是派生值或一個新的。使用strtr而不是做所有的替換一氣呵成:

documentation for str_replace

更換爲了疑難雜症

由於str_replace()函數替換左到右,它可能會取代先前插入進行多次替換時的價值。

我做了一些修改,您for循環,幫助你瞭解你是怎麼認爲的輸出:

<?php 

$str = "password"; 
$search = range("a", "z"); 
$replace = array_merge(range("d", "z"), range("a", "c")); 

header('Content-Type: text/plain'); 

for($i = 0; $i < 26; $i++) 
{ 
    $beforeStr = $str; 
    $str = str_replace($search[$i], $replace[$i], $str); 

    //var_dump($search[$i], $replace[$i], $str); 

    if ($beforeStr !== $str) { 
     echo "$i) $search[$i] -> $replace[$i]\n"; 
     echo "Replacement: $before -> $str"; 
    } else { 
     echo "$i) $search[$i] -> $replace[$i]\n"; 
     echo "Replacement: none"; 
    } 
    echo "\n\n"; 
} 

echo $str; 

Demo

解決辦法是使用strtr。具體方法如下:

$replacePairs = array_combine($search, $replace); 
echo strtr('password', $replacePairs); // => sdvvzrug 

Demo


注:   不要試圖推出自己的加密算法或協議;這是非常容易出錯的。使用經過嘗試和測試的庫。請參閱this security.SE post,瞭解爲何不應推出自己的加密算法。

3

做這種多通替換是錯誤的。使用strtr將解決問題,因爲它不會更改已替換個字符。

這是你如何bbbbcaab:「什麼?我做錯了」

:password 
a->d:pdssword 
b->e:pdssword 
c->f:* 
d->g:pgssworg 
e->h:* 
f->i:* 
g->j:pjssworj 
h->k:* 
i->l:* 
j->m:pmssworm 
k->n:* 
l->o:* 
m->p:ppssworp 
n->q:* 
o->r:ppsswrrp 
p->s:sssswrrs 
q->t:* 
r->u:sssswuus 
s->v:vvvvwuuv 
t->w:* 
u->x:vvvvwxxv 
v->y:yyyywxxy 
w->z:yyyyzxxy 
x->a:yyyyzaay 
y->b:bbbbzaab 
z->c:bbbbcaab 
相關問題