Поиск:

Ответ в темуСоздание новой темы Создание опроса
> простенький алгоритм для шифрования, результат непонятен 
:(
    Опции темы
Qawra
Дата 23.12.2009, 00:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 188
Регистрация: 6.3.2007

Репутация: нет
Всего: 4



Написала " своими словами " простенький алгоритм для шифрования .
Правда он на любом input даёт один и тот же output .
Посмотрите пожайлуста "свежим взглядом " в чём проблема :
Код

public class CeasarCipher {

    public static final int numberOfUsedLetters = 26; //use only English alphabet in uppercase
    public static final char[] alphabet = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
        'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
    // uses  rotation around array to enciphing and oposite rotation to deciphing
    protected static char[] encryptArray = new char[numberOfUsedLetters];
    protected static char[] decryptArray = new char[numberOfUsedLetters];
    public static String result;

    public static String enciphing(String input, int shift) {

        input.toUpperCase(); //convert all letters to UpperCase for comparison

        char[] plaintext = new char[input.length()];
        char[] ciphertext = new char[input.length()]; // assume that there will be no punctuation or empty spaces to remove
        result = ""; //because ciphers can run simultaneosly - "result" could change value

        // rotate alphabet by number of places entered by user
        for (int i = 0; i < numberOfUsedLetters ; i++) {
            encryptArray[i] = alphabet[(i + shift) % numberOfUsedLetters];
        }
        //  remove any punctuation and empty spaces from String entered by user
        int c = 0;//will be used as index
        for (int i = 0; i < input.length(); i++) // we check all elements of entered String
        {
            if (input.charAt(i) >= 'A' && input.charAt(i) <= 'Z') { // only letters we copy to plaintext array for enciphing
                plaintext[c] = input.charAt(i);
                c++;
            }
        }
        // actually enciphing starts

        for (int x = 0; x < plaintext.length; x++) {
            for (int y = 0; y < alphabet.length; y++) {
                if (plaintext[x] == alphabet[y]) {
                    ciphertext[c] = encryptArray[y];
                }
            }
        }
        // form String from array of char
        StringBuilder ciphertextBuilder = new StringBuilder();

        for (int j = 0; j < ciphertext.length; j++) {
            ciphertextBuilder = ciphertextBuilder.append(ciphertext[j]);
        }
        return result = ciphertext.toString();
    }

    public static void main(String[] args)
    {
        System.out.println(enciphing("b",6)); // здесь я тестирую  input
    }
}



PM MAIL   Вверх
Reaver
Дата 24.12.2009, 09:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 28.12.2006

Репутация: нет
Всего: нет



Первое что бросается в глаза, эта строка:
Код

input.toUpperCase(); 


Правильно написать 
Код

input = input.toUpperCase(); 

Метод String.toUpperCase() возвращает новую строку с преобразованным регистром, а не изменяет исходную.

Только после этого изменения программа начинает вылетать с ошибкой.
Да и решение слишком усложнено, вот так гораздо лучше, правда не учтена обработка пробелов:

Код

public class CeasarCipher {

    private static final String alphabetStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final int alphabetLen = alphabetStr.length();

    public static String enciphing(String input, int shift) throws IllegalArgumentException{
        input = input.toUpperCase();
        char[] result = new char[input.length()];

        for (int i = 0; i < input.length(); i++) {
            int idx = alphabetStr.indexOf(input.charAt(i));
            if (idx == -1) {
                throw new IllegalArgumentException("Недопустимые символы в строке");
            }
            idx = (idx + shift) % alphabetLen;
            while (idx < 0) {
                idx += alphabetLen;
            }
            result[i] = alphabetStr.charAt(idx);
        }

        return new String(result);
    }
}


Это сообщение отредактировал(а) Reaver - 24.12.2009, 09:18
PM MAIL   Вверх
Qawra
Дата 24.12.2009, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 188
Регистрация: 6.3.2007

Репутация: нет
Всего: 4



Спасибо !
Я попыталась пристроить удаление пробелов вместо Exception используя continue label .
Но пока ничего не удаляется 
Код

 
       public static String enciphing(String input, int shift)  {
        int index;
        input = input.toUpperCase();
        char[] result = new char[input.length()];

      nextLabel:
        for (int i = 0; i < input.length(); i++) {    
            if (input.charAt(i) < 'A' || input.charAt(i) > 'Z')
            {
                continue nextLabel;
            } else 
                index = alphabetStr.indexOf(input.charAt(i));
           
                index = (index + shift) % alphabetLen;
            
            while (index < 0) {
                index += alphabetLen;
            }
            result[i] = alphabetStr.charAt(index);
        }

        return new String(result);
    }


Это сообщение отредактировал(а) Qawra - 24.12.2009, 12:58
PM MAIL   Вверх
Reaver
Дата 24.12.2009, 14:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 28.12.2006

Репутация: нет
Всего: нет



В данном случае можно добавить пробел в алфавит, либо просто пропускать символы, не входящие в алфавит:
 
Код

    public static String enciphing(String input, int shift){
        input = input.toUpperCase();
        char[] result = new char[input.length()];

        for (int i = 0; i < input.length(); i++) {
            int index = alphabetStr.indexOf(input.charAt(i));
            if (index != -1) {
                index = (index + shift) % alphabetLen;
                while (index < 0) {
                    index += alphabetLen;
                }
                result[i] = alphabetStr.charAt(index);
            }
        }

        return new String(result);
    }

PM MAIL   Вверх
Qawra
Дата 24.12.2009, 15:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 188
Регистрация: 6.3.2007

Репутация: нет
Всего: 4



Я вынесла эту операцию в отдельный метод что бы не мучиться ,
буду вызывать её из enciphing и deciphing методов.

Я думаю что для того что-бы расшифровать то что мы зашифровали нам надо просто поменять + на - 
в строчке
Код

index = (index + shift) % alphabetLen;

Или этого недостаточно ?

Что-то я упустила в шифровании ..Компелируется , но результат выдаёт не тот который должен быть 
Код

 public static String enciphing(String input, int shift)  {
        int index;
        trimString(input);
        char[] result = new char[input.length()];
       for (int i = 0; i < input.length(); i++) {
        index = alphabetStr.indexOf(input.charAt(i));

                index = (index + shift) % alphabetLen;

            while (index < 0) {
                index += alphabetLen;
            }
            result[i] = alphabetStr.charAt(index);
        }
        return new String(result);
    }

на строчку 
Код

System.out.println(CeasarCipher2.enciphing("Piramida  heopsa", 4));

выдаёт "TDDDDDDDDDDDDDDD"
это он даже не заикается ... это он только первую букву правильно шифрует smile
trimString работает правильно , все пробелы удаляет


Я попробовала написать simple substitution алгоритм 
Код

public class SimpleSubstitutionCipher {
  
    public static final char[] alphabet = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
        'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};

   public static String trimString(String input) {
        input = input.toUpperCase();
        input.trim();// removes empty spaces from start and end of the string

        int c = 0;
        char[] inputArray = new char[input.length()];
        nextLabel:
        for (int i = 0; i < input.length(); i++) {
            // пробелы почему-то не удаляются
            if (input.charAt(i) < 'A' || input.charAt(i) > 'Z') {
                continue nextLabel;
            } else {
                inputArray[c] = input.charAt(i);
            }
            c++;
        }
            String inputTemp = new String(inputArray);
            return input=inputTemp;
    }
    
    public static String encipingSubstitution(String input ,String key)
    {      
        int index;
        trimString(input);
        char [] keyArray= new char[26];
        char [] result=new char [input.length()];
        
        keyArray=key.toCharArray();//convert to char array
        
        for(int i=0; i<input.length(); i++)
        {
            index = alphabet.indexOf(input.charAt(i));
            
            result[i] = keyArray[index];
            
        }
                
      return new String(result);
    }
}

Он у меня получился каким-то подозрительно простым ,
И строчка 
Код

index = alphabet.indexOf(input.charAt(i));

 компайлеру не понравилась.
Говорит что не может найти метод indexOf 

 key для этого алгоритма я запрашиваю у пользователя как string , затем буквы из него (без повторов) переписываю в keyArray и добиваю его до размера английского алфавита с помощью этого самого алфавита 
Смотрится правда  достаточно запутано :
Код

public static char[] setKey(String key) {

        char[] keyTemp = key.toCharArray();//convert to char array

        Set notRepeatedSet = new TreeSet();
        for (char element : keyTemp) {
            notRepeatedSet.add(element);
        }

        Character [] uniq = (Character[]) notRepeatedSet.toArray(new
Character[notRepeatedSet.size()]);
        int c=0;
        for (int i=0; i<uniq.length; i++)
        {
            keyArray[i]=uniq[i]; // puts unigue letters from key to front of the keyArray
            c++;
        }

        for ( int j=c+1; j<26; j++) // we need to fill empty positions of keyArray with letters
        {
       alreadyThere:
            for(int x=0; x<26; x++) // goes through alphabet array
            {

                for (int y=0; y<c ;y++)//goes through array with unigue letters from key
                {
                   if(uniq[y]==alphabet[x]) //if letter already in the keyArray
                   {
                     continue alreadyThere; //goes for next letter of alphabete
                   }else keyArray[j]=alphabet[x]; // store letter into key array
                }
            }
        }
        return keyArray;
    }

не знаю будет ли работать потому что строчка 
Код

index = alphabet.indexOf(input.charAt(i));
 
в самом алгоритме пока не скомпелировалась по непонятной причине

Это сообщение отредактировал(а) Qawra - 24.12.2009, 18:53
PM MAIL   Вверх
Reaver
Дата 24.12.2009, 19:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 28.12.2006

Репутация: нет
Всего: нет



Цитата(Qawra @  24.12.2009,  13:43 Найти цитируемый пост)
Я думаю что для того что-бы расшифровать то что мы зашифровали нам надо просто поменять + на - в строчке
index = (index + shift) % alphabetLen;
Или этого недостаточно ?


В принципе, все правильно, но функцию дешифрования переписывать не надо. Можно просто написать таким образом:
Код

public static String deciphing(String input, int shift){
  return enciphing(input, -shift);
}


Во вторых, Вы повторяете те же самые ошибки, что и в начале. Метод trim() возвращает новую строку, а не изменяет старую, то же самое и с вашим методом trimString(String input). Так же, метод trim() удаляет пробелы только из начала и конца строки.
Для удаления всех пробелов не обязательно писать свою функцию, можно воспользоваться функцией String.replaceAll(" ", "");

Цитата(Qawra @  24.12.2009,  13:43 Найти цитируемый пост)
И строчка
index = alphabet.indexOf(input.charAt(i));
компайлеру не понравилась.Говорит что не может найти метод indexOf 


Первый мой пример компилировался без проблем? Если нет, то какую версию jdk Вы используете?

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

public static String enciphing(String input, int shift)
            throws IllegalArgumentException {
        input = input.toUpperCase();
        
        char[] result = new char[input.length()];
        for (int i = 0; i < input.length(); i++) {
            int index = alphabetStr.indexOf(input.charAt(i));
            if (index != -1) {
                index = (index + shift) % alphabetLen;
                while (index < 0) {
                    index += alphabetLen;
                }
                result[i] = alphabetStr.charAt(index);
            } else {
                result[i] = ' ';
                System.out.println(input.charAt(i));
            }
        }
        return new String(result).replaceAll(" ", "");
    }


PM MAIL   Вверх
Qawra
Дата 24.12.2009, 19:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 188
Регистрация: 6.3.2007

Репутация: нет
Всего: 4



Ошибку с trim() и trimString(String input) я исправила .

NetBeans 6.7.1 у меня установлен , но я в нём только начинающий пока программист smile
Могу что-нибудь перепутать .
Здесь выделена эта строчка, в первом классе она скомпелировалась без проблем 
Код

public class SimpleSubstitutionCipher {

    public static char[] keyArray = new char[26];
    public static final char[] alphabet = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
        'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};

    public static String trimString(String input) {
        input = input.toUpperCase();
        input=input.trim();// removes empty spaces from start and end of the string

        int c = 0;
        char[] inputArray = new char[input.length()];
        nextLabel:
        for (int i = 0; i < input.length(); i++) {
            // пробелы почему-то не удаляются
            if (input.charAt(i) < 'A' || input.charAt(i) > 'Z') {
                continue nextLabel;
            } else {
                inputArray[c] = input.charAt(i);
            }
            c++;
        }
        String inputTemp = new String(inputArray);
        return input = inputTemp;
    }

    public static char[] setKey(String key) {

        char[] keyTemp = key.toCharArray();//convert to char array

        Set notRepeatedSet = new TreeSet();
        for (char element : keyTemp) {
            notRepeatedSet.add(element);
        }

        Character [] uniq = (Character[]) notRepeatedSet.toArray(new
Character[notRepeatedSet.size()]);
        int c=0;
        for (int i=0; i<uniq.length; i++)
        {
            keyArray[i]=uniq[i]; // puts unigue letters from key to front of the keyArray
            c++;
        }

        for ( int j=c+1; j<26; j++) // we need to fill empty positions of keyArray with letters
        {
       alreadyThere:
            for(int x=0; x<26; x++) // goes through alphabet array
            {

                for (int y=0; y<c ;y++)//goes through array with unigue letters from key
                {
                   if(uniq[y]==alphabet[x])//if letter already in the keyArray
                   {
                     continue alreadyThere; //goes for next letter of alphabete
                   }else keyArray[j]=alphabet[x]; // store letter into key array
                }
            }
        }
        return keyArray;
    }

    public static String encipingSubstitution(String input, String key) {
        int index;
        trimString(input);
        keyArray = setKey(key);

        char[] result = new char[input.length()];

        for (int i = 0; i < input.length(); i++) {
            index = alphabet.indexOf(input.charAt(i));

            result[i] = keyArray[index];
        }
        return new String(result);
    }
// uses the same key as encipingSubstitution method - keyArray which was already created
    public static String decipingSubstitution(String input) {

        return result;
    }

    public static void main(String[] args)
    {

    }
}

PM MAIL   Вверх
Reaver
Дата 24.12.2009, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 28.12.2006

Репутация: нет
Всего: нет



У вас переменная alphabet имеет тип char[], а обращаетесь к ней как к типу String.
PM MAIL   Вверх
Qawra
Дата 24.12.2009, 23:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 188
Регистрация: 6.3.2007

Репутация: нет
Всего: 4



Да , так оно и оказалось .Я уже переделала её в String  smile

Делаю сейчас  setKey для шифрования с субституцией .
Удаляются из  String   пробелы и дубликаты букв . То что остаётся становиться началом нового алфавита размером в 26 букв. Пустые места заполняются английским алфавитом начиная с буквы A.

Код

 public static char[] setKey(String key) {
        key=trimString(key);
        char[] keyTemp = key.toCharArray();//convert String to char array

        Set notRepeatedSet = new TreeSet();
        for (char element : keyTemp) {
            notRepeatedSet.add(element);
        }

        Character [] uniq = (Character[]) notRepeatedSet.toArray(new
Character[notRepeatedSet.size()]);
        int c=0;
        for (int i=0; i<uniq.length; i++)
        {
            keyArray[i]=uniq[i]; // puts unigue letters from key to front of the keyArray
            c++;
        }

        for ( int j=c; j<26; j++) // we need to fill empty positions of keyArray with letters
        {
       alreadyThere:
            for(int x=0; x<26; x++) // goes through alphabet array
            {
                for (int y=0; y<c ;y++)//goes through array with unigue letters from key
                {
                   if(uniq[y]==alphabet[x])//if letter already in the keyArray
                   {
                     continue alreadyThere; //goes for next letter of alphabete
                   }else keyArray[c]=alphabet[x]; // store letter into key array
                }
            }
        }
        return keyArray;
    }


Непонятно почему после удаления пробелов и дубликатов буквы оказываются в алфавитном порядке . А вместо английского алфавита  впечатывается буква Z .
Например :
Код

System.out.println(SimpleSubstitutionCipher.setKey(" ttuutoonneerrmmv "));


печатает EMNORTUVZ

Мне кажется что inner loops надо переставить местами чтобы английский алфавит допечатывать в key.
Ну а  порядок букв видимо результат использования TreeSet ...?






Это сообщение отредактировал(а) Qawra - 24.12.2009, 23:14
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Алгоритмы"

maxim1000

Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, maxim1000.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Алгоритмы | Следующая тема »


 




[ Время генерации скрипта: 0.1180 ]   [ Использовано запросов: 20 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.