Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Закрытая тема
Ваша тема закрыта, почему это могло произойти? Возможно,
Нет наработок или кода, если нужно готовое решение - создайте тему в разделе Фриланс и оплатите работу.
Название темы включает слова - "Помогите", "Нужна помощь", "Срочно", "Пожалуйста".
Название темы слишком короткое или не отражает сути вашего вопроса.
Тема исчерпала себя, помните, один вопрос - одна тема
Прочитайте правила и заново правильно создайте тему.
 
Опции темы Поиск в этой теме
Старый 16.04.2015, 20:33   #1
Риндера
Delphi, учу С
Форумчанин
 
Аватар для Риндера
 
Регистрация: 20.10.2010
Сообщений: 178
По умолчанию Шифровка по квадрату Виженера

Приветс. Пишу прогу, которая среди прочего шифрует текст по квадрату Виженера.

Проблема в том, что код работает вроде бы правильно, но результат получается кривой.

Код:
procedure TMain.Vijener(input,output:TMemo;key:string;encode:boolean);
  var
    i,lit,lenABC,lenkey: integer; 	// i - счетчик; lit - текущий обрабатываемый символ в input; 
					//Длина алфавита (стороны квадрата Виженера) и длина ключа, чтоб не вычислять их каждый раз 
    Ru,En,ABC: string;			// Строчки из которых собирается алфавит
    bukva:string;			// Итоговая буква, которая идет в output на каждой итерации
    p,k,c:integer;// Для облегчения читаемости формулы
                  // c = (p + k) mod 26
                  // p = (c - k + 26) mod 26
begin
  output.Clear;				// Очищаю выходной мемо
  ProgressBar1.Position:=0;		
  lit:=0;						
  Ru:='АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ';
  En:='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  ABC:='';
  // Убираю пробелы из ключа
  while Pos(' ',key)>0 do Delete(key,Pos(' ',key),1);
  // Привожу ключ к формату алфавита
  key:=AnsiUpperCase(key);		
  // Создаю алфавит для таблицы, значения берутся из настроек программы
  if OptionsForm.VijenerEn.Checked then ABC:=ABC+En;
  if OptionsForm.VijenerRu.Checked then ABC:=ABC+Ru;
  lenABC:=Length(ABC);
  lenkey:=Length(key);

  // Кодирую
  repeat
    if Cancel=true then break; 		// Если нажата кнопка отмены
    for i:=1 to lenkey do		// Для имитации "цикличной записи" ключа
      begin
        inc(lit);				
        if lit>Length(input.Text) then break; 			// Чтоб не было лишних букв в конце
        if Pos(AnsiUpperCase(input.Text[lit]),ABC)=0 then 	// Если символ не буква, пропускаем
          begin
            output.Text:=output.Text+input.Text[lit];
            continue;
          end;

        if encode then  	// Шифровать
          begin
            p:=Pos(AnsiUpperCase(input.Text[lit]),ABC);		
            k:=Pos(key[i],ABC);
            c:=(p+k) mod lenABC;
            bukva:=ABC[c];
          end
        else       		// Расшифровывать
          begin
            c:=Pos(AnsiUpperCase(input.Text[lit]),ABC);
            k:=Pos(key[i],ABC);
            p:=(c-k+lenABC) mod lenABC;
            bukva:=ABC[p];
          end;
        if not (AnsiUpperCase(input.Text[lit])=input.Text[lit]) then	// Чтоб все буквы не были капсом, привожу к регистру оригинала
          bukva:=AnsiLowerCase(bukva);
        output.Text:=output.Text+bukva;					// Записываю букву в output мемо
      end;

    // Косметика
    if (lit mod 10 = 0) or (lit>=Length(input.Text)) then		// Чтоб выходной мемо не мигал слишком сильно от постоянного обновления
      begin
        Application.ProcessMessages;
        ProgressBar1.Position:=Round(100*lit/(Length(input.Text)+0.001)); // +0.001 чтоб не крашилась при пустом входном поле
        SendMessage(output.Handle,EM_LINESCROLL,0,output.Lines.Count);	
      end;
  until lit>=Length(input.Text);

end;
Результат работы при ключе Unicorn и только английском алфавите вот: http://i.imgur.com/z0Thsgp.jpg

Как видно, после определенного момента всё просто крашится.

Объясните кто-нибудь, что я делаю не так =)

Последний раз редактировалось Риндера; 16.04.2015 в 20:43.
Риндера вне форума
Старый 16.04.2015, 21:05   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Не вникал, но визуально косяк вижу
Код:
            c:=(p+k) mod lenABC;
            bukva:=ABC[c];
Чего будет, когда с=0? Аналогично и ниже по коду
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума
Старый 16.04.2015, 21:18   #3
Вадим Мошев

Старожил
 
Аватар для Вадим Мошев
 
Регистрация: 12.11.2010
Сообщений: 8,568
По умолчанию

Кстати, онлайн (де)шифратор шифра вижнера http://planetcalc.ru/2468/?language_select=ru

Для проверки, если что.
Вадим Мошев вне форума
Старый 16.04.2015, 21:27   #4
Риндера
Delphi, учу С
Форумчанин
 
Аватар для Риндера
 
Регистрация: 20.10.2010
Сообщений: 178
По умолчанию

Да, при с=0 получается не хорошо.
Я думаю вообще вся проблема в том, что формулы для букв, пронумерованных от 0 до 25, а в делфи строка нумеруется с единицы.
Попробую завтра переписать так, чтоб ABC был массивом, а не строкой, сегодня устала уже от этого Виженера.
А еще надо наверное поубирать нафиг возможность выбирать язык и делать сразу на оба, действительно, зачем оно ваще нужно.

Последний раз редактировалось Риндера; 16.04.2015 в 21:34.
Риндера вне форума
Старый 17.04.2015, 08:23   #5
Риндера
Delphi, учу С
Форумчанин
 
Аватар для Риндера
 
Регистрация: 20.10.2010
Сообщений: 178
По умолчанию

Утро вечера мудренее, как говорится. Вот так работает на ура:
Код:
p:=Pos(AnsiUpperCase(input.Text[lit]),ABC)-1; 	// Добавила -1
k:=Pos(key[i],ABC)-1;				// Добавила -1
c:=(p+k) mod lenABC;
bukva:=ABC[c+1];				// Добавила +1
С калькулятором, кстати, не совпадает.
Хотя я знаю почему.

Последний раз редактировалось Риндера; 17.04.2015 в 08:31.
Риндера вне форума
Старый 17.04.2015, 14:00   #6
Вадим Мошев

Старожил
 
Аватар для Вадим Мошев
 
Регистрация: 12.11.2010
Сообщений: 8,568
По умолчанию

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

Я эту тему закрываю. Если появится вопрос, создайте новую.

Последний раз редактировалось Вадим Мошев; 17.04.2015 в 14:05.
Вадим Мошев вне форума
Закрытая тема


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
качение квадрата по квадрату NovichekVPascale Помощь студентам 0 12.10.2012 17:23
Таблица Виженера stas45rus Помощь студентам 0 23.10.2011 21:00
Шифр Виженера Radiy Паскаль, Turbo Pascal, PascalABC.NET 7 12.06.2010 10:05
расшифровать виженера!!! Anenya.K Помощь студентам 4 06.03.2010 13:09
Принадлежность точки квадрату Паскаль, либо Delphi Kati Помощь студентам 1 24.02.2010 22:10