凯撒密码的实现

Implementation of the Caesar cipher

我必须在 class Functionality.java 中实现一个名为 encodeCaesar 的静态 public 方法,它使用凯撒加密对文本进行编码,我是一个完整的新手Java.

Signature: encodeCaesar(String s, int val) : String

The method gets a string value and an integer value as input parameters. The letters (characters) from the string value are to be shifted by the integer value. For simplicity, I can assume that there are only letters and no spaces, numbers or special characters.

The string value should be converted to lower case before the encryption is performed. The method should return a string where each letter has been moved according to the specified integer value.

Example: encodeCaesar("Ac",3) returns "df". If the given integer value is less than 0 or greater than 26, an empty string should be returned.

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

    public static String encodeCaesar(String s, int val) {
        char[] newString = s.toCharArray();
        for (int i = 0; i < s.length(); i++) {
            int newChar = newString[i] + val + 26;

            // Handle uppercase letters
            while (Character.isUpperCase(newString[i]) && newChar >= 65 + 26) {
                newChar -= 26;
            }

            // Handle lowecase letters
            while (Character.isLowerCase(newString[i]) && newChar >= 97 + 26) {
                newChar -= 26;
            }

            newString[i] = (char) (newChar);
        }

        return String.valueOf(newString);
    }
}

我的问题是,在 return 中,它只给我正确或错误的信息。我该如何解决这个问题:该方法应该 return 一个字符串,其中每个字符都已根据指定的整数值移动。

public static String caesar(String s, int val) {
    char[] newString = s.toLowerCase().toCharArray();
    for (int i = 0; i < s.length(); i++) {
        int newChar = newString[i] + val + 26;
        // Handle lowercase letters
        while (Character.isLowerCase(newString[i]) && newChar >= 97 + 26) {
            newChar -= 26;
        }
        newString[i] = (char) (newChar);
    }
    return String.valueOf(newString);
}

我解决了问题。

以下代码片段解决了一些小问题:

  • 非字母字符(如果有)由密码保持不变
  • while 循环替换为 if
  • 使用模运算符将值包装在 z
public static String encodeCaesar(String s, int val) {
    char[] newString = s.toLowerCase().toCharArray();
    for (int i = 0; i < newString.length; i++) {
        char newChar = newString[i];

        if (newChar >= 'a' && newChar <= 'z') {
            newString[i] = (char) ('a' + (newChar + val - 'a') % 26); 
        }
    }

    return new String(newString); // String.valueOf calls it anyway
}

比较:

System.out.println("encode: " + encodeCaesar("Viva Caesar! Morituri te salutant!", 3));
System.out.println("caesar: " + caesar("Viva Caesar! Morituri te salutant!", 3));

输出:

encode: ylyd fdhvdu! prulwxul wh vdoxwdqw!
caesar: ylyd=fdhvdu>=prulwxul=wh=vdoxwdqw>

您可以使用 String.codePoints 方法迭代此字符串字符的 int 值,并将它们移动给定值:

public static String encodeCaesar(String s, int val) {
    if (val < 0 || val > 26) return "";
    return s.codePoints()
            // Stream<Character>
            .mapToObj(i -> (char) i)
            // convert to lowercase
            .map(Character::toLowerCase)
            // filter out non-letters
            .filter(ch -> ch >= 'a' && ch <= 'z')
            // if a letter should be shifted
            // outside the alphabetical range,
            // then move it before the beginning
            .map(ch -> ch + val > 'z' ? ch - 'z' + 'a' - 1 : ch)
            // shift letter by a given value
            .map(ch -> ch + val)
            // each character as a single string
            .map(Character::toString)
            // join characters into one string
            .collect(Collectors.joining());
}
public static void main(String[] args) {
    System.out.println(encodeCaesar("Ac", 3)); // df
    System.out.println(encodeCaesar("YZx 32*d", 3)); // bcag
}

另请参阅:Replace non ASCII character from string