【问题标题】:Vigenere cipher while maintaining space and encrypt only words starting with consonent letters [Java]Vigenere 密码,同时保持空间并仅加密以辅音字母开头的单词 [Java]
【发布时间】:2021-12-02 22:59:28
【问题描述】:

我正在尝试编写一个程序,该程序将使用 Vigenere 密码加密一个句子,但只有以辅音字母开头的单词,同时存储空格。 我对Java还不是很好,但是我写了一个方法来加密任何给定的单词(所有小写字母)我曾认为使用数组在需要的地方打印空格并忽略以元音开头的单词就足够了,但这样做实际上是每当我打印数组的第二个单词左右时给我错误的输出。有人可以指导我做错了什么吗?有没有更好的方法来做到这一点? 到目前为止,这是我的代码:

public class Main {
public static void main(String[] args) {

    Scanner u = new Scanner(System.in);
    final String k = u.next();
    u.nextLine();
    String message = u.nextLine();
    String[] f = message.split(" ");
    System.out.println(encipher(message,k));

    for (String s : f) {
        if (s.charAt(0) == 'a' || s.charAt(0) == 'e' || s.charAt(0) == 'i' ||
                s.charAt(0) == 'o' || s.charAt(0) == 'u') {
            System.out.println(s);
        } else {
            System.out.println(encipher(s, k));
        }

    }
}


public static String encipher(String message, final String key)
{
    String output = "";

    for (int x = 0, y = 0; x < message.length(); x++)
    {
        char c = message.charAt(x);
        if (c < 'a' || c > 'z')
            continue;
        output += (char) ((c + key.charAt(y) - 2 * 'a') % 26 + 'a');
        y = ++y % key.length();
    }

    return output;
}}

您可以看到正常输出(忽略空格和元音/辅音)和数组输出之间的区别。对于字符串键obi和字符串消息“olimpiada brasileira de informatica”,它应该打印“olimpiada psigjtsjzo em informatica”,但在数组中打印“olimpiada psigjtsjzo rf informatica”[暂时忽略打印行的事情,我会在我修复它正确加密]

【问题讨论】:

    标签: java string encryption


    【解决方案1】:

    当逐字应用加密时,为每个字重置密钥,"de" 使用"ob" 加密:

    brasileira
    obiobiobio
    
    de
    ob
    

    当整个消息被加密时,密钥不会被重置("olimpiada" 有 9 个字母可以被"obi".length() == 3 整除),并且"de""bi" 加密:

    olimpiada brasileira de informatica
    obiobiobi obiobiobio bi obiobiobiob
    

    因此,如果可能需要以某种方式记住 y 索引,或者应该实施另一种方法来在 next 索引处的非空白键中提供一个字符:

    private static Map<String, Integer> keyIndexes = new HashMap<>();
    
    private static char getNextPosition(String key) {
        return key.charAt(keyIndexes.compute(
            key, (k, v) -> v == null ? 0 : (v + 1) % k.length()
        ));
    }
    
    private static void resetKey(String key) {
        keyIndexes.remove(key);
    }
    

    那么encipher方法可以更新为:

    public static String encipher(String message, final String key)
    {
        StringBuilder output = new StringBuilder();
    
        for (char c : message.toCharArray())
        {
            if (c < 'a' || c > 'z')
                continue; // skip non-letters
    
            output.append((char) ((c + getNextPosition(key) - 2 * 'a') % 26 + 'a'));
        }
    
        return output.toString();
    }
    

    测试:

    String message = "olimpiada brasileira de informatica";
    String k = "obi";
    System.out.println(encipher(message, k));
    // !!!
    resetKey(k);
    
    for (String s : message.split(" ")) {
        if (s.matches("[aeiou]\\w*")) { // use regexp to detect a word starting with a vowel
            System.out.println(s);
        } else {
            System.out.println(encipher(s, k));
        }
    }
    

    输出:

    cmqaqqoeipsigjtsjzoemwoncsuouqqb   // full message, spaces skipped
    olimpiada
    psigjtsjzo
    em
    informatica
    

    如果需要将非字母和以元音开头的单词保持原样用于整个消息(不仅仅是单个单词),则应添加几个标志来跟踪当前字符是否在单词中,并且如果检测到第一个元音:

    public static String encipherWork(String message, final String key) {
        StringBuilder output = new StringBuilder();
        
        boolean inWord = false;
        boolean firstVowel = false;
    
        for (char c : message.toCharArray()) {
            if ('a' <= c && c <= 'z') {
                if (!inWord) {
                    firstVowel = (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u');
                    inWord = true;
                }
                if (!firstVowel) {
                    output.append((char) ((c + getNextPosition(key) - 2 * 'a') % 26 + 'a'));
                    continue;
                }
            } else {
                inWord = false;
                firstVowel = false;
            }
            output.append(c); // print non-enciphered characters
        }
    
        return output.toString();
    }
    

    此方法的输出:

    olimpiada psigjtsjzo em informatica // full message
    olimpiada
    psigjtsjzo
    em
    informatica
    

    【讨论】:

    • 非常感谢你的朋友!!
    猜你喜欢
    • 2020-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多