Технический форум

Технический форум (http://www.tehnari.ru/)
-   Помощь студентам (http://www.tehnari.ru/f41/)
-   -   Помогите доработать программу (http://www.tehnari.ru/f41/t250020/)

Smile188 13.11.2016 00:22

Помогите доработать программу
 
Программа работает, но нужно немного ее улучшить . Но нужно чтобы у одинаковых слов были разные коды. (Напр. если в книге 3 союза " и" , а мы вводим 5 , то программа должна при шифровке вывести 1 2 3 1 2)



Код:

{ Нужно реализовать шифровку и расшифровку с помощью кодировочной книги. }
 
const
  MaxWord: integer = 200;
 
type
  TBook = array[1..MaxWord] of string; // тип для выходного массива слов
 
function GetWords(const line: string; var words: TBook; var count: integer): integer; // разбиение строки на слова по разделителю
const
  delimiter = [' ',',','.','(',')',':','?','!'];
var
  back,pos,n: integer;
begin
  pos:=1;
  while pos <= length(line) do
    begin
      while (pos <= length(line)) and (line[pos] in delimiter) do pos:=pos+1;
      if pos <= length(line) then
        begin
          back:=pos;
          while (pos <= length(line)) and not(line[pos] in delimiter) do pos:=pos+1;
          n:=n+1;
          words[n]:=copy(line,back,pos-back);
        end;
    end;
  GetWords:=n;
end;
 
var
  book,txt: TBook;
  shifr: array[1..MaxWord] of integer;
  i,j,k,n: integer;
  str: string;
  key: byte;
  f: text;
 
begin
  assign(f,'kkk.txt');
  reset(f);
  n:=0;
  while not eof(f) do
    begin
      readln(f,str);
      n:=GetWords(str,book,n);
    end;
  close(f);
  writeln('Кодировочная книга успешно прочитана...');
  repeat
    writeln;
    writeln('  < МЕНЮ >  ');
    writeln('  1 - зашифровать текст');
    writeln('  2 - дешифровать текст');
    writeln('  3 - выход');
    writeln;
    write('Введите номер пункта : ');
    readln(key);
    case key of
      1: begin
          write('Введите текст : ');
          readln(str);
          write('Зашифрованный текст : ');
          k:=0;
          k:=GetWords(str,txt,k);
          for i:=1 to k do
            begin
              j:=1;
              while j <= n do
                begin
                  if txt[i] = book[j] then
                    begin
                      write(j,' ');
                      j:=n;
                    end;
                  j:=j+1;
                end;
            end;
          writeln;
        end;
      2: begin
          write('Введите количество слов в тексте : ');
          readln(k);
          write('Введите шифр : ');
          for i:=1 to k do read(shifr[i]);
          writeln;
          write('Дешифрованный текст : ');
          for i:=1 to k do write(book[shifr[i]],' ');
          writeln;
        end;
      3: writeln('Нажмите любую клавишу для выхода...');
      end;
  until key = 3;
  readln;
end.


Vladimir_S 13.11.2016 08:38

И ведь каждый раз прошу: сформулируйте исходное задание, опишите (подробно!) применяемый алгоритм шифрования и т.п. Нет - всё мимо. Чирик-чирик, вот программа - исправьте.
Ну как знаете.
Ждите - может быть и найдётся энтузиаст, который по неотлаженной программе восстановит алгоритм, разберется "что имел в виду программист" и отладит код. Но я - не он.

Smile188 13.11.2016 10:52

{ Нужно реализовать шифровку и расшифровку с помощью кодировочной книги. }

Алгоритм , если что был указан. Но вот еще раз более подробно:
реализация шифрования и расшифровки методом «Кодировочная книга». При этом будем считать, что кодом служит позиция слова в кодировочной книге (специально подготовленном файле), причем, если слово встречается несколько раз и в открытом тексте, и в кодировочной книге, в закрытом тексте для одного и того же слова будут использованы разные коды.

Vladimir_S 13.11.2016 14:45

Уф, ну - получите.
1. Исправлено довольно много ошибок. Например, объявление в списке параметров функции строку константой - абсурд. Ну и еще по мелочи. Кстати, ну зачем тут функция? По всем статьям подходит процедура.
2. Английские надписи можете обратно заменить русскими: просто мне с кириллицей работать неудобно (у меня DOS-кодировка).
3. Путь к файлу-книге, естественно, исправьте по своему усмотрению.
Код:

const
  MaxWord = 200;
  delimiter = [' ',',','.','(',')',':','?','!'];

type
  TBook = array[1..MaxWord] of string; // type of word output array

Procedure GetWords(line: string; var words: TBook; var count: byte); // Fragmentation of string to words according to delimiter
var
  back,pos,m: integer;
begin
  pos:=1;
  m:=0;
  while pos <= length(line) do
    begin
      while (pos <= length(line)) and (line[pos] in delimiter) do pos:=pos+1;
      if pos <= length(line) then
        begin
          back:=pos;
          while (pos <= length(line)) and not(line[pos] in delimiter) do pos:=pos+1;
          m:=m+1;
          words[m]:=copy(line,back,pos-back);
        end;
    end;
  count:=m;
end;

var
  book,txt: TBook;
  shifr,posit: array[1..MaxWord] of byte;
  i,j,k,n,q: byte;
  st: string;
  key: byte;
  f: text;
  b: boolean;

begin
  assign(f,'D:\kkk.txt');
  reset(f);
  while not eof(f) do
    begin
      readln(f,st);
      GetWords(st,book,n);
    end;
  close(f);
  writeln;
  writeln('Code book read successfully...');
  for i:=1 to n do write(book[i]+' ');
  repeat
    writeln;
    writeln('  < MENU >');
    writeln('  1 - encode text');
    writeln('  2 - decode text');
    writeln('  3 - exit');
    writeln;
    write('Enter the item number: ');
    readln(key);
    case key of
      1: begin
          write('Enter the text: ');
          readln(st);
          writeln('Encoded text: ');
          GetWords(st,txt,k);
          for i:=1 to k do posit[i]:=0;
          b:=false;
          for i:=1 to k do
            begin
            b:=false;
            repeat
              j:=1;
              repeat
              if (txt[i]=book[j]) and (j>posit[i]) then
                begin
                b:=true;
                posit[i]:=j;
                shifr[i]:=j;
                for q:=i+1 to k do
                  if txt[q]=txt[i] then posit[q]:=j;
                end
              else
                j:=j+1;
              until b or (j=n+1);
              if not(b) and (j=n+1) then
              for q:=1 to k do
                if txt[q]=txt[i] then posit[q]:=0;
            until b;
            end;
          for i:=1 to k do write(shifr[i],' ');
          writeln;
        end;
      2: begin
          write('Enter the number of words in text: ');
          readln(k);
          write('Enter the code: ');
          for i:=1 to k do read(shifr[i]);
          writeln;
          write('Decoded text: ');
          for i:=1 to k do write(book[shifr[i]],' ');
          writeln;
        end;
      end;
  until key = 3;
end.


Smile188 13.11.2016 18:25

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

if (txt[i]=book[j]) and (j>posit[i]) then
Encoded text: Ошибка времени выполнения: System.IndexOutOfRangeException: Индекс находился вне границ массива

Vladimir_S 13.11.2016 18:42

Цитата:

Сообщение от Smile188 (Сообщение 2434019)
Спасибо большое, вы очень помогли. Книга работает, но она читает если только текст в книге записан в одну строку , не подскажите как сделать, чтобы программа читала из книги в которой больше чем 1 строка?

Сходу не подскажу. Как обрабатывать эти переводы строки - не знаю. Точнее, не помню. Вроде как-то решается. Можно, конечно, пойти по такому пути: работать с множеством букв, а не разделителей, и всё, что не буква, считать разделителем. Дальше считываем файл посимвольно.
Цитата:

Сообщение от Smile188 (Сообщение 2434019)
тут выдается ошибка:
Код:

if (txt[i]=book[j]) and (j>posit[i]) then
Encoded text: Ошибка времени выполнения: System.IndexOutOfRangeException: Индекс находился вне границ массива

Это ОЧЕНЬ странно. Естественно, я гонял программу, прежде чем выложить.
Если не секрет, покажите, пожалуйста, Вашу книгу и кодируемый текст. Просто в текстовом виде.

Smile188 13.11.2016 19:02

Вложений: 1
Вложение 315645
...........

Vladimir_S 13.11.2016 19:18

А, ну тогда понятно... В Вашем файле - 661 символ, а уж слов - даже и не знаю, может быть и больше 200. А Вы пытаетесь считывать строку...
Мне кажется, тут надо бы ограничиться строкой с количеством символов не более 255. Или кардинально переделать часть программы, где разделение книги на слова: считывать данные из файла посимвольно и "на лету" отделять буквы от разделителей и формировать массив слов.
Совсем другая задача.

Smile188 13.11.2016 19:29

Но так в моей изначальной программе все нормально шифровало и расшифровывалось из этой книги, кроме повторяющихся слов, вместо разных кодов выводило один и тот же столько раз, сколько я ввела слов

Vladimir_S 13.11.2016 19:48

Цитата:

Сообщение от Smile188 (Сообщение 2434040)
Но так в моей изначальной программе все нормально шифровало и расшифровывалось из этой книги, кроме повторяющихся слов, вместо разных кодов выводило один и тот же столько раз, сколько я ввела слов

Ох... ну тогда - не знаю. У меня - классический Free Pascal, в котором строка - это массив символов не длинее 255, и воспринять 660 символов по команде чтения строки он просто не умеет. И я вместе с ним. Извините.


Часовой пояс GMT +4, время: 12:59.

Powered by vBulletin® Version 4.5.3
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.