0

我想要破译某个文本。当我在字符串中遇到一个字母时,我想用字母表中的下一个字母替换它。然后在下一轮我想用第二个下一个字母替换。

a -> b

k -> l

然后在第二轮它应该尝试

a -> c

k -> 米

字符的问题是它包含了各种奇怪的字符,当你遇到 az 并尝试替换它时,它会被一个奇怪的符号替换。

谁能帮我从AZ制作某种循环列表?在下面的代码片段中,我创建了一个包含 a 到 z 的列表。在循环中选择一个字符,搜索并“调整”它的索引,并且应该检索新字符。但它不起作用。(列表不是循环的一个原因)

public static void decipher(){
    String cyphertext = "aVaqrprzoreoeratraWhyvhfraJnygreUbyynaqreqrgjrroebrefinaRqvguZnetbganneNzfgreqnzNaarjvytenntzrrxbzraznnezbrgabtrrarragvwqwrovwbznoyvwiraBznmnyurgzbrvyvwxuroorabzNaarabtrracnnejrxraqnnegrubhqrafpuevwsgRqvguSenaxvarraoevrsnnaTregehqAnhznaauhaiebrtrerohhezrvfwrvaSenaxshegnzZnva";
    char[] plaintext = new char[cyphertext.length()];

    List<Character> a2z = new ArrayList<Character>(26);
    for (char c = 'A'; c <= 'Z'; c++){
        a2z.add(Character.valueOf(c));
    }

    for(int i = 1; i < 26; i++){
        for(int j = 0; j < cyphertext.length(); j++){
            char currentChar = cyphertext.charAt(j);
            int newCharIndex = a2z.indexOf(currentChar)+i;
            plaintext[j] = a2z.get(newCharIndex);
        }
    }
}
4

3 回答 3

1

问题在这里:

int newCharIndex = a2z.indexOf(currentChar)+i;
plaintext[j] = a2z.get(newCharIndex);

这里的解码字符介于 0 到 25 之间。Ascii 的 AZ 从 65 到 90。您希望将索引移动a2z到从 A 到 Z 的范围内:

plaintext[j] = a2z.get(newCharIndex) + 'A';
于 2015-09-19T23:24:59.910 回答
1

如果我理解正确,您希望替换密码将字母向上移动 N,从Zto换行A,同时使用大写和小写字母,并保持所有其他字符不变。

例如,如果 N 为 2:

a → c  b → d  ...  x → z  y → a  z → b
A → C  B → D  ...  X → Z  Y → A  Z → B

像这样?

char[] text = "aVaqrprzoreoeratraWhyvhfraJnygreUbyynaqreqrgjrroebrefinaRqvguZnetbganneNzfgreqnzNaarjvytenntzrrxbzraznnezbrgabtrrarragvwqwrovwbznoyvwiraBznmnyurgzbrvyvwxuroorabzNaarabtrracnnejrxraqnnegrubhqrafpuevwsgRqvguSenaxvarraoevrsnnaTregehqAnhznaauhaiebrtrerohhezrvfwrvaSenaxshegnzZnva".toCharArray();
for (int n = 1; n < 26; n++) {
    for (int i = 0; i < text.length; i++) {
        char c = text[i];
        if (c >= 'A' && c <= 'Z')
            text[i] = (char)('A' + (c - 'A' + n) % 26);
        else if (c >= 'a' && c <= 'z')
            text[i] = (char)('a' + (c - 'a' + n) % 26);
    }
}
System.out.println(new String(text));

输出

nIndecemberbrengenJuliusenWalterHollanderdetweebroersvanEdithMargotnaarAmsterdamAnnewilgraagmeekomenmaarmoetnogeeneentijdjebijomablijvenOmazalhetmoeilijkhebbenomAnnenogeenpaarwekendaartehoudenschrijftEdithFrankineenbriefaanGertrudNaumannhunvroegerebuurmeisjeinFrankfurtamMain

当然,你确实意识到移动 1,然后移动 2,然后移动 3,......最后移动 26,与移动一次 (1 + 2 + 3 + ... + 26) 相同,即351 和351 % 26 = 13.

而移位 13 意味着编码和解码是相同的操作。


解释

如果你移动 26,你正在移动一个完整的回合,即a → a b → b ...,所以这与不移动相同,因此 N >= 26 的任何移动都与 N % 26 相同,例如N = 28与 相同N = 2

移位 1a → b再移位 2b → d再移位 3d → g与移位 1+2+3=6 相同a → g。所以移位 1+2+...+26=351 与移位 351 % 26 = 13 相同。

如果变量c是大写字母 (AZ),c - 'A'则为 0 到 25 之间的数字。添加 6 的示例移位,您将得到数字 6-31。做余数 26 ( % 26) 给你 6-25,0-5 然后+ 'A'给你G-Z,A-F,意思是A → G B → H ... Y → E Z → F,每个字母移动 6。

小写字母也一样。

于 2015-09-19T23:43:25.700 回答
1

您不需要循环列表来处理边缘情况。此外,您应该记住,字符A-Z的 ascii 值介于 65-90 和a-z97-122 之间。您可以创建两个循环列表,但不需要它们,因为边缘情况很容易处理:

public static void main(String[] args) {
    String cyphertext = "aVaqrprzoreoeratraWhyvhfraJnygreUbyynaqreqrgjrroebrefinaRqvguZnetbganneNzfgreqnzNaarjvytenntzrrxbzraznnezbrgabtrrarragvwqwrovwbznoyvwiraBznmnyurgzbrvyvwxuroorabzNaarabtrracnnejrxraqnnegrubhqrafpuevwsgRqvguSenaxvarraoevrsnnaTregehqAnhznaauhaiebrtrerohhezrvfwrvaSenaxshegnzZnva";
    char[] plaintext = new char[cyphertext.length()];

    // first shift
    shiftLetters(cyphertext, plaintext, 1);
    // update cyphertext with the intermediate result
    cyphertext = new String(plaintext);
    // second shift
    shiftLetters(cyphertext, plaintext, 2);
    // print result
    System.out.println(new String(plaintext));

}

private static void shiftLetters(String cyphertext, char[] plaintext, int shifts) {
    for (int i=0; i<cyphertext.length(); i++){
        int tmp = cyphertext.charAt(i) + shifts;
        tmp = handleEdgeCases(tmp);
        plaintext[i] = (char)(tmp);
    }
}

// here we handle the "circular" cases
private static int handleEdgeCases(int tmp) {
    if (tmp > 90 && tmp < 97) {
        tmp = tmp - 90 + 65;
    } else if (tmp > 122) {
        tmp = tmp - 122 + 97;
    }
    return tmp;
}
于 2015-09-19T23:44:07.043 回答