【问题标题】:Using StringBuilder getting null as output使用 StringBuilder 获取 null 作为输出
【发布时间】:2016-10-01 09:00:17
【问题描述】:

我正在做一个编码问题,我尝试解密输入字符串。解密过程如下: 从 0 到 9 它代表从 a 到 i 的字母。 那么10#代表j,11#代表k等等。

import java.util.HashMap;

public class Julia {

    public static void main(String[] args) {

        String s="10#21#12#91";
        Julia obj=new Julia();
        String result=obj.decrypt(s);
        System.out.println(result);
    }
    public String decrypt(String msg)
    {
        HashMap<String,Character> hs=new HashMap<>();
        hs.put("1",'a');
        hs.put("2",'b');
        hs.put("3",'c');
        hs.put("4",'d');
        hs.put("5",'e');
        hs.put("6",'f');
        hs.put("7",'g');
        hs.put("8",'h');
        hs.put("9",'i');
        hs.put("10",'j');
        hs.put("11",'k');
        hs.put("12",'l');
        hs.put("13",'m');
        hs.put("14",'n');
        hs.put("15",'o');
        hs.put("16",'p');
        hs.put("17",'q');
        hs.put("18",'r');
        hs.put("19",'s');
        hs.put("20",'t');
        hs.put("21",'u');
        hs.put("22",'v');
        hs.put("23",'w');
        hs.put("24",'x');
        hs.put("25",'y');
        hs.put("26",'x');
        StringBuilder n=new StringBuilder();
        for(int i=msg.length()-1;i>=0;i--)
        {

            if(msg.charAt(i)=='#' && i>=2)
            {
                StringBuilder s=new StringBuilder().append(msg.charAt(i-2)).append(msg.charAt(i-1));
                System.out.println(s);
                n.append(hs.get(s));
                System.out.println(n);
                i=i-2;
            }
            else
            {
                n.append(hs.get(msg.charAt(i)));
            }

        }
        return n.toString();
    }
}

那是我写的代码。但我得到的输出是nullnullnullnullnull。 我认为问题在于StringBuilder。任何人都可以帮助我并解释这个概念吗?如果有人有更好的解决方案,请指导。

【问题讨论】:

标签: java string collections stringbuilder


【解决方案1】:

当您可以使用简单的公式时,您不应该使用数据(地图)。

我的建议:

import java.util.ArrayList;
import java.util.List;

public final class Julia {

    public static void main(final String[] args) {
        final String s = "10#21#12#91";
        final String result = decrypt(s);
        System.out.println(result);
    }

    private static String decrypt(final String s) {
        final List<Integer> crypt = new ArrayList<>();
        final String[] groups = s.split("#");
        for (int i = 0; i < groups.length; i++) {
            final String group = groups[i];
            int j = 0;
            // Special case for last group
            if ((i == (groups.length - 1)) && !s.endsWith("#")) {
                j = group.length();
            }
            if (group.length() > 2) {
                j = group.length() - 2;
            }
            for (int k = 0; k < j; k++) {
                crypt.add(Integer.valueOf(group.substring(k, k + 1)));
            }
            if (j < group.length()) {
                crypt.add(Integer.valueOf(group.substring(j, group.length())));
            }
        }
        final StringBuilder n = new StringBuilder(crypt.size());
        for (final Integer c : crypt) {
            final char d = (char) (('a' + c) - 1);
            n.append(d);
        }
        return n.toString();
    }
}

请注意题中有两个错误:字母a是1,不是0,26的值是z,不是x。当您使用公式可以执行的数据时,后一种错误是典型的。

由于您正在学习,我会注意到解密方法(我的建议和您的建议)应该是静态的,因为它们不使用任何字段,因此不需要实例化。

【讨论】:

  • 您的输出不正确。使用您的解决方案输出是 jul>>,但实际输出是 julia。谢谢指导:)
  • 没有约翰。问题是从 0 到 9 no # is there.eg: a --> 1 b --> 2 i -->9 j -->10# k -->11# z-- >26#
  • 你的算法很完美。我测试过了。
【解决方案2】:

这是模式匹配问题,可以通过Regex解决。

您的代码有一些错误,其他人已经指出了这些错误。我没有看到任何看起来比简单的正则表达式解决方案更好的解决方案。

下面的正则表达式代码将为输入“10#21#12#91”输出“julia”。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Julia {

public static void main(String[] args) {

    String s="10#21#12#91";

    Julia obj=new Julia();
    String result=obj.decrypt(s);
    System.out.println(result);
}

public String decrypt(String msg)
{
    Pattern regex = Pattern.compile("((\\d\\d#)|(\\d))");
    Matcher regexMatcher = regex.matcher(msg);
    StringBuffer result = new StringBuffer();
    while (regexMatcher.find())
        regexMatcher.appendReplacement(result, getCharForNumber(Integer.parseInt(regexMatcher.group(1).replace("#",""))));
    return result.toString();
}

private String getCharForNumber(int i) {
    return i > 0 && i < 27 ? String.valueOf((char)(i + 96)) : null;
}
}

希望对你有帮助。

【讨论】:

    【解决方案3】:

    hs.get(s) 将始终返回null,因为s 不是String

    试试hs.get(s.toString())

    hs.get(msg.charAt(i)) 也将始终返回 null,因为您将 char 传递给 get 而不是 String

    你的代码也可能有逻辑问题,但很难说。

    【讨论】:

    • 谢谢它的工作:) 你能推荐任何其他好的解决方案吗??
    • @SahilArora 使用整数键而不是字符串或简单的公式。
    【解决方案4】:

    代码的优化版本

    public class Main {
    
        public static void main(String[] args) {
            String cipher = "10#21#12#91";
    
            System.out.print(decrypt(cipher));
    
            //output : julia
        }
    
        static String decrypt(String cipher) {
            //split with # to obtain array of code in string array
            String[] cipher_char_codes = cipher.split("#");
    
            //create empty message
            StringBuilder message = new StringBuilder();
    
            //loop for each code
            for (String code : cipher_char_codes) {
    
                //get index of character
                int index = Integer.parseInt(code);
    
                if (index > 26) {
                    char[] pair = code.toCharArray();
                    for (int i = 0; i < pair.length; i++) {
                        int x = Integer.parseInt("" + code.charAt(i));
                        message.append((char) ('a' + ((x - 1) % 26)));
                    }
                } else {
                    //map index into 1 to 26
                    //find ascii code and cast into char
                    message.append((char) ('a' + ((index - 1) % 26)));
                }
            }
            return message.toString();
        }
    
    }
    

    【讨论】:

    • 您的输出不正确。 91 表示 9--> 'i' 和 1-->'a'。所以使用这个 %26 会给出错误的答案。
    • 该算法仅适用于特定输入。当我尝试“ajulia”(110#21#12#91)时它不起作用。
    【解决方案5】:

    Regex 确实是要走的路,Pirate_Jack 提出的代码可以改进。它调用了昂贵的正则表达式两次多余的时间(替换是一个正则表达式操作)。

    以下是一个改进的版本:

       import java.util.regex.Matcher;
       import java.util.regex.Pattern;
    
       public final class Julia3 {
    
           public static void main(final String[] args) {
    
               final String s = "10#21#12#91";
    
               final String result = decrypt(s);
               System.out.println(result);
           }
    
           public static String decrypt(final String msg) {
               final Pattern regex = Pattern.compile("((\\d\\d)(#)|(\\d))");
               final Matcher regexMatcher = regex.matcher(msg);
               final StringBuffer result = new StringBuffer();
               String c;
               while (regexMatcher.find()) {
                   if (regexMatcher.group(2) == null) {
                       c = regexMatcher.group(1);
                   } else {
                       c = regexMatcher.group(2);
                   }
                   result.append((char) ((Integer.parseInt(c) + 'a') - 1));
               }
               return result.toString();
           }
       }
    

    【讨论】:

      【解决方案6】:

      这是不对的:

      hs.get(s)
      

      s 是StringBuilder。应该是hs.get(Char)

      编辑:可选的不同解决方案:

          public class Julia {
      
          public static void main(String[] args) {
      
              String s="10#21#12#91";
      
              List<String> numbers = splitToNumbers(s);
      
              Julia obj=new Julia();
              String result=obj.decrypt(numbers);
              System.out.println(result);
          }
      
          /**
           *@param s
           *@return
           */
          private static List<String> splitToNumbers(String s) {
      
              //add check s is not null
      
              char[] chars = s.toCharArray();
              char delimiter = '#';
              List<String> numberAsStrings = new ArrayList<String>();
      
              int charIndex = 0;
      
              while (charIndex < (chars.length -3)) {
      
                  char theirdChar = chars[charIndex+2];
                  if(theirdChar == delimiter) {
      
                      numberAsStrings.add(""+chars[charIndex]+chars[charIndex+1]);
                      charIndex +=3;
      
                  }else {
      
                      numberAsStrings.add(""+chars[charIndex]);
                      charIndex ++;
                  }
              }
      
              //add what's left
              while (charIndex < chars.length) {
      
                  numberAsStrings.add(""+chars[charIndex]);
                  charIndex++;
              }
      
              return numberAsStrings;
          }
      
          public String decrypt(List<String> numbersAsStings){
      
              StringBuilder sb=new StringBuilder();
      
              for (String number : numbersAsStings) {
      
                  int num = Integer.valueOf(number);
                  sb.append(intToChar(num-1));
              }
      
              return sb.toString();
          }
      
          private char intToChar(int num) {
      
              if((num<0) || (num>25) ) {
                  return '?' ;
              }
              return (char)('a' + num);
          }
      }
      

      【讨论】:

      • 谢谢 :) 你能推荐其他更好的解决方案吗?
      • 是的,我加了一个。
      猜你喜欢
      • 2018-02-11
      • 1970-01-01
      • 2013-06-23
      • 1970-01-01
      • 2018-10-12
      • 1970-01-01
      • 1970-01-01
      • 2016-01-12
      • 1970-01-01
      相关资源
      最近更新 更多