2016-10-01 3 views
-1

Я делаю один вопрос с кодировкой, в котором я пытаюсь расшифровать входную строку. Процедура дешифрования: от 0 до 9 представляет собой алфавиты от a до i. , тогда 10 # представляют j, 11 # представляют k и так далее.Использование StringBuilder, получающего null как вывод

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. Может ли кто-нибудь помочь мне в этом и объяснить концепцию? Если у кого-то есть лучшее решение, пожалуйста, обратитесь к нему.

+0

Отформатируйте свой код и опубликовать [MCVE] – c0der

+0

Примечание: 'hs.put ("26", 'х');', вероятно, неправильно, должно be 'hs.put (" 26 ", 'z');'? – zaph

ответ

2

hs.get(s) всегда будет возвращать null, так как s не является String.

Try hs.get(s.toString())

hs.get(msg.charAt(i)) также всегда будет возвращать null, так как вы пропускании char к get вместо String.

В вашем коде могут быть проблемы с логикой, но это трудно сказать.

+0

Спасибо, что это работает :) может предложить любое другое хорошее решение, кроме этого? –

+0

@SahilArora использует целые ключи вместо строк или простую формулу. –

0

Это не так:

hs.get(s) 

s является StringBuilder. Он должен быть hs.get(Char)

Edit: необязательное другое решение:

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

Спасибо :) может предложить любое другое решение лучше, чем это? –

+0

Да, я добавил один. – c0der

1

Оптимизированная версия кода

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

} 
+0

Вы неверны. В силу 91 это означает 9 -> 'i' и 1 -> 'a'. Таким образом, используя этот% 26, он даст неверный ответ. –

+0

Я отредактировал код согласно вашей логике. Теперь он отлично работает. – asissuthar

+0

Алгоритм подходит только для конкретных входов. Когда я пытаюсь «ajulia» (110 # 21 # 12 # 91), он не работает. –

4

Вы не должны использовать данные (карты), когда вы могли бы использовать простая формула.

Мое предложение:

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

Пожалуйста, обратите внимание, что есть две ошибки в вопросе: буква а 1, не равна нулю, а значение 26 г, а не х. Последняя ошибка типична, когда вы используете данные, которые будет делать формула.

Поскольку вы изучаете, я бы отметил, что методы дешифрования - как мое предложение, так и ваше - должны быть статическими, поскольку они не используют никаких полей, поэтому создание экземпляра не требуется.

+0

Ваш выход является правильным. Используя выход решения, jul >>, но фактический результат - julia. Спасибо за руководство :) –

+0

No Johathan. Вопрос от 0 до 9 нет # не there.eg: а -> 1 б -> 2 я -> 9 J -> 10 # к -> 11 # z-- > 26 # –

+1

Я отредактировал код в соответствии с комментарием. –

3

Это Проблема совпадения с образцом, что может быть разрешено Regex.

У вашего кода есть некоторые ошибки, и те уже указываются другими. Я не вижу никакого решения, которое выглядит лучше простого решения регулярных выражений.

Ниже регулярное выражение кода будет выводить 'джулия' для ввода '10 # 21 # 12 # 91'.

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

Надеюсь, это поможет.

1

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