【问题标题】:Implementation of the Caesar cipher凯撒密码的实现
【发布时间】:2021-03-01 04:47:53
【问题描述】:

我必须在Functionality.java 类中实现一个名为encodeCaesar 的静态公共方法,该方法使用凯撒加密对文本进行编码,而我是一个Java 新手。

签名:encodeCaesar(String s, int val) : String

该方法获取一个字符串值和一个整数值作为输入参数。字符串值中的字母(字符)将移动整数值。为简单起见,我可以假设只有字母,没有空格、数字或特殊字符。

在执行加密之前,字符串值应转换为小写。该方法应返回一个字符串,其中每个字母已根据指定的整数值移动。

示例:encodeCaesar("Ac",3) 返回"df"。如果给定的整数值小于 0 或大于 26,则应返回空字符串。

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

我的问题是,作为回报,它只给我真或假。我该如何解决:该方法应返回一个字符串,其中每个字符已根据指定的整数值移动。

【问题讨论】:

    标签: java string replace char caesar-cipher


    【解决方案1】:

    以下代码 sn-p 解决了一些小问题:

    • 密码保持不变的非字母字符(如果有)
    • 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>
    
    

    【讨论】:

      【解决方案2】:
      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);
      }
      

      我解决了这个问题。

      【讨论】:

        【解决方案3】:

        您可以使用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

        【讨论】:

          最近更新 更多