2016-08-10 2 views
1

Имейте код, который делает что-то вроде дешифрования, где вводится строка, а затем дешифруется в двойном числе, буквы могут быть от a до j и соответственно a = 0, b = 1 ... j = 9. Программа работает, все, что я хочу знать, может быть, это самый простой способ достичь этого? Я новичок в java и на данный момент не знаю всех функций. Код:Замена и преобразование строк

import java.util.Scanner; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 
import java.lang.Double; 
public class Decrypt 
{ 
    private static String conversionTable[][] = { 
     {"a", "0"}, 
     {"b", "1"}, 
     {"c", "2"}, 
     {"d", "3"}, 
     {"e", "4"}, 
     {"f", "5"}, 
     {"g", "6"}, 
     {"h", "7"}, 
     {"i", "8"}, 
     {"j", "9"}, 
    }; 
    private static Scanner scanner; 

    public static double decrypt(String encryptedNumber) 
    { 
     String c = ""; 
     int i = 0; 
     String[] s = encryptedNumber.split(""); 

     for(int j = 0; j < 2; j++) { 
      if(c.length() == s.length) 
       break; 

      for(int k = 0; k < 9; k++) { 
       if(c.length() == s.length) 
        break; 
       if(conversionTable[k][j].equalsIgnoreCase(s[i])){ 
        c += k; 
         i++; 
       }else if(s[i].equalsIgnoreCase(".")){ 
        c += "."; 
        i++; 
       } 
      } 
      j--; 
     } 

     double d = Double.parseDouble(c); 
     return d; 
    } 

    public static void main(String arg[]) 
    { 
     scanner = new Scanner(System.in); 
     System.out.println("Enter the string to decrypt:"); 
     String input=scanner.next(); 
     System.out.println("Number after decryption is:"+decrypt(input)); 
    } 
} 
+1

Ну, char - это всего лишь тип данных; и значения char ... могут быть выражены как числа, например здесь: https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html ... поэтому, предполагая, что вы только для символов ascii ... вам не нужна карта, вы можете делать простые вычисления. Оставленный как упражнение для читателя. – GhostCat

ответ

0

С точки зрения криптографической то, что вы описываете это substitution cipher. Я бы даже не рассматривал это шифрование больше, больше похоже на кодирование (см. here).

У вас есть строки, добавляющие строки. Когда вы делаете что-то вроде

c += k; 

, что Java на самом деле делает там создает новый объект String, и изменение указателя в с к этому новому объекту. За годы существования JVM стало намного лучше создавать и отбрасывать недолговечные объекты, но это все еще очень неэффективно. Попробуйте вместо этого использовать StringBuilder.

Вы также выполняет sequential search через вашу conversionTable что означает весь ваш алгоритм является O (N^2) операции (см here) (для nitpickers, это на самом деле O (м * п), но это достаточно близко, меня). Совершенно не имеет значения для такого небольшого стола, но избегайте делать такие вещи, если это возможно. Кроме того, нет смысла писать это самостоятельно, когда что-то на этом языке хочет сделать это за вас (это будет повторяющаяся тема). Ваши элементы в порядке, поэтому мы можем использовать одну из реализаций binarySearch() в Arrays. Я немного придумаю использование, но это для иллюстрации.

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

Избегайте использования инструкции break в чем-либо, кроме переключателя. Большинство людей считают, что они находятся в одной лодке goto.

И дайте вашим переменным более описательные имена. Ваше будущее будет благодарно вам.

Так с изменениями я изложил, мы в конечном итоге с помощью метода следующий расшифровывать():

public static double decrypt(String encryptedNumber) { 
    StringBuilder builder = new StringBuilder(); 
    int i = 0; 
    String[] encNumElements = encryptedNumber.toLowerCase().split(""); 
    for (String element : encNumElements) { 
     int foundAt = Arrays.binarySearch(conversionTable, new String[]{element, ""}, new Comparator<String[]>() { 
      @Override 
      public int compare(String[] arg0, String[] arg1) { 
       return arg0[0].compareTo(arg1[0]); 
      }    
     }); 
     if (foundAt >= 0) { 
     builder.append(conversionTable[foundAt][1]); 
     } else { 
     // assuming a decimal point here since it's not on the list 
     builder.append('.'); 
     } 
    } 

    double d = Double.parseDouble(builder.toString()); 
    return d; 
} 

Это лишь немного лучше. Если бы я действительно хотел сделать что-то подобное, то Компаратор был бы отдельным классом, но это работает для иллюстрации.

С точки зрения кодирования, то, что вы здесь, представляет собой таблицу поиска. Легкая реализация - это карта. Традиционно инициализация статической карты поиска является довольно уродливой, но проверьте ответ i_am_zero here на более простой способ сделать это с помощью Java 8. Карта является естественной структурой поиска, поэтому порядок не важен. Он также имеет приятный побочный эффект от сдачи десятичной точки в карту и, таким образом, исключить оператор if.

private static final Map<String, String> conversionMap = Stream.of(
     new SimpleEntry<>("a", "0"), 
     new SimpleEntry<>("b", "1"), 
     new SimpleEntry<>("c", "2"), 
     new SimpleEntry<>("d", "3"), 
     new SimpleEntry<>("e", "4"), 
     new SimpleEntry<>("f", "5"), 
     new SimpleEntry<>("g", "6"), 
     new SimpleEntry<>("h", "7"), 
     new SimpleEntry<>("i", "8"), 
     new SimpleEntry<>("j", "9"), 
     new SimpleEntry<>(".", ".")) 
     .collect(Collectors.toMap((se) -> se.getKey(), (se) -> se.getValue())); 

    public static double decrypt(String encryptedNumber) { 
     StringBuilder builder = new StringBuilder(); 
     String[] encNumElements = encryptedNumber.toLowerCase().split(""); 
     for (String element : encNumElements) {   
      builder.append(conversionMap.get(element)); 
     } 

     double d = Double.parseDouble(builder.toString()); 
     return d; 
    } 

Что-то вроде этого, где я остановился бы в общем случае. Но ваш список поиска представляет собой последовательность символов в последовательность целых чисел. Java фактически обрабатывает примитивные символы как целые числа, поэтому вы можете делать математику на них. String даже дает нам метод для получения символов из String, поэтому мы можем напрямую их перебирать.Мы должны иметь дело с десятичной точкой в ​​if, если снова, но это позволяет полностью избавиться от таблицы поиска.

public static double decrypt(String encryptedNumber) { 
     StringBuilder builder = new StringBuilder(); 
     for (char ch : encryptedNumber.toLowerCase().toCharArray()) { 
     if (ch == '.') { 
      builder.append('.'); 
     } else { 
      builder.append(ch - 'a'); 
     } 
     } 
     return Double.parseDouble(builder.toString()); 
    }