Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Задачи _ Кодирование длин серий . Текстовый файл.

Автор: lopata 11.04.2010 22:02

Помогите пожалуйста разобраться как делать.

Кодирование длин серий (Run-length encoding, RLE) - простая техника сжатия,при которой каждая последовательность знаков, которые состоят более чем из 2 одинаквых знаков, кодируется по первому знаку и длине последовательности.
Реализуйте простой вариант этого способа в форме программы фильта, которая кодирует и снова декодирует текстовые файлы,в которых содержатся только строчные и прописные буквы , знаки препинания и пробелы (но не цифры).Ваша программа должна предлогать следующие возможности вызова из камандной строки (метасимболы[...] и ...|... стоят для опций или альтернатив):
RLE [ -c | -d ] [inFile] [outFile]

Значение параметров:
-c входной файл нужно кодировать (значение по умолчанию),
-d входной файл нужно декодировать,
inFile имя входного файла, иначе стандартный ввод (input)
outFile имя выходного файла, иначе стандартный вывод (output).

Пример:
http://radikal.ru/F/s48.radikal.ru/i122/1004/7c/f44389e250f8.jpg.html


Файлы я пока не трогала...Попыталась просто кодировать. В переменную ch сохраняю символ, если он равен следующему - увеличиваю счетчик, если нет - скидываю в строку str2 и текущий символ сохраняю снова в ch и так далее. Не работает..:


var x, str1, str2, ch,countstr : string;
i, k, count : integer;
begin
countstr:= '';
ch := '';
str2 := '';
count := 0;
Readln(str1);
for i := 1 to Length(str1) do begin
if i=1 then begin
ch:=str1[1];
count:= 1;
end
else begin
if ch= str1[i] then
inc(count)
else begin
if count > 2 then begin
Str(count,countstr);
str2:= countstr+ch
end
else begin
for k := 1 to count do
str2 := str2+ch;
ch := str1[i];
count := 1;
end;
end;
end;
end;
end.



Автор: volvo 11.04.2010 22:20

А если вот так попробовать:

var
str1, str2, ch, countstr: string;
i, k, count: integer;
begin
str2 := '';
{ Readln(str1); }
str1 := 'AbbCCCddddEnd';


str1 := str1 + '_'; { <--- Последний символ не должен совпадать с добавляемым !!! }
ch := str1[1]; count := 1;
for i := 2 to Length(str1) do begin
if ch = str1[i] then inc(count)
else begin
if count > 2 then begin
Str(count,countstr);
str2 := str2 + countstr + ch { <--- Здесь надо увеличивать str2 !!! }
end
else begin
for k := 1 to count do
str2 := str2 + ch;
end;

ch := str1[i]; count := 1; { <--- Это делается в любом случае, а не только по Else !!! }
end;
end;
writeln(str2);
end.

?

Автор: lopata 11.04.2010 22:31

Спасибо) поняла

Автор: lopata 11.04.2010 23:55

Не получается с декодированием. Не могу понять почему больше d намного больше.




var str1 , str2, ch, substr,numberstr: string;
number,i,j,k : integer;
begin
numberstr := '';
str2:= '';
str := 'abb3c4dend';
substr := '1234567890';
for i := 1 to Length(str1) do begin
ch := str1[i];
if Pos(ch,substr)=0 then
str2 := str2 + ch
else begin
numberstr := numberstr+ch;
for j := i+1 to length(str1) do begin
ch:= str1[j];
if pos(ch,substr)>0 then
numberstr := numberstr + ch
else begin;
val(numberstr,number);
for k := 1 to number do
str2 := str2+ch;
break;
end; i:= j+1;
end;
end;
end;



Добавлено через 17 мин.
все) сама нашла. Нужно было numberstr обнулить. Там сохранялись предыдущие числа.

end; i:= j+1;
end;
numberstr := '';
end;


Автор: volvo 12.04.2010 0:16

Цитата
end; i:= j+1;
Эту строку исправляй немедленно! smile.gif Иначе она принесет тебе немало проблем в дальнейшем. Переменная цикла для тебя - табу. Ты имеешь к ней доступ для чтения, но для записи - ни в коем случае. Компилятор сам решает, когда и как изменять эту переменную. Тебе этого делать нельзя.

Автор: lopata 12.04.2010 0:21

Ок)
Насчет последнего исправления тоже неверно. Я так обрадавалась, что количесиво d уменьшилось, что даже не заметила что их 5 вместо 4(

Автор: Client 12.04.2010 0:56

uses crt;
var
str1, str2, ch, countstr: string;
i, k, count: integer;
errcode : integer;
begin
str2 := '';
ch:='';
{ Readln(str1); }
str1 := 'Abb10C4dEn2d';
i:=1;
while i <= length(str1) do begin
if str1[i] in ['0'..'9'] then begin
while (str1[i] in ['0'..'9']) do begin
ch:=ch + str1[i];
inc(i);
end;
val(ch, count, errcode);
if count > 2 then
for k:=1 to count-1 do
str2 := str2 + str1[i];
end
else begin
str2 := str2 + str1[i];
ch:='';
inc(i);
end;
end;

writeln(str2);
readkey
end.
Попробуй так, вроде пашет

Автор: lopata 12.04.2010 1:18

Спасибо, Client.
Просто обидно, что у меня никогда ничего не работает(

Добавлено через 14 мин.
volvo, а что у меня неправильно?/

Автор: Client 12.04.2010 1:53

Узнаешь код

var str1 , str2, ch, substr,numberstr: string;
number,i,j,k : integer;
errcode: integer;
begin
numberstr := '';
str2:= '';
str1:= 'abb10c4den2d';
substr := '1234567890';
i:=1;
while i <= Length(str1) do begin //замена на while
ch := str1[i];
if Pos(ch,substr)=0 then begin
str2 := str2 + ch;
numberstr:=''; //обнуление
end
else begin
numberstr := numberstr+ch;
for j := i+1 to length(str1) do begin
ch:= str1[j];
if pos(ch,substr)>0 then begin
numberstr := numberstr + ch;
inc(i); //подсчет цифр
end
else begin
val(numberstr,number, errcode);
if number > 2 then //проверка на 2
for k := 1 to number-1 do
str2 := str2+ch;
break;
inc(i);
end;
end;
end;
inc(i); //на основной while для перехода к след символу
end;
writeln(str2);
end.
?
Воть, вроде ничего не забыл.

Автор: lopata 12.04.2010 2:09

Хм..но работает неверно.
Вадает результат abbccccccccccddend
пропустило последий символ.
А если задать abb3c4cEnd, то вообще не получается.

Автор: Client 12.04.2010 2:15

вариант что в коде - 10 "с" и 4 "d"

Цитата
А если задать abb3c4cEnd, то вообще не получается.
То 7 "с" и получается


Эскизы прикрепленных изображений
Прикрепленное изображение

Автор: lopata 12.04.2010 2:21

Сорри. Имела в виду abb3c4dEnd.
Походу я что-то недопонимаю...

Автор: volvo 12.04.2010 2:46

Цитата
Сорри. Имела в виду abb3c4dEnd.
В чем проблема?
Прикрепленное изображение

Что ты ожидала получить?

Автор: lopata 12.04.2010 2:54

Снова извините. Переклинило.

Автор: lopata 12.04.2010 22:06

Не мог бы кто-нибудь объяснить про командную строку?

Автор: TarasBer 13.04.2010 13:07

ParamCount - число параметров командной строки.
ParamStr(N) - N-ый параметр, строковый тип. ParamStr(0) - само имя программы, с полным путём к ней.

Автор: lopata 14.04.2010 0:27

Честно говоря вообще не понимаю как это должно работать

Автор: Unconnected 14.04.2010 2:06

Ну тебе надо получить 3 параметра, делаешь что-то типа (пишу тут):

var c,infile,outfile:string;
begin
c:=paramstr[1];
infile:=paramstr[2];
outfile:=paramstr[3];
if uppercase©='-D' then unpcking else packing;
end.


Естественно, надо оформить коды сжатия и разжатия в процедуры packing и unpacking или даже обойтись без процедур.

Автор: Гость 14.04.2010 2:23

Цитата(Unconnected @ 13.04.2010 22:06) *

Естественно, надо оформить коды сжатия и разжатия в процедуры packed и unpacked или даже обойтись без процедур.

Эммм...А что это значит?

Автор: Client 14.04.2010 2:34

это значит что надо выполнить выбранное действие

Автор: TarasBer 14.04.2010 13:26

Что такое командная строка - знаешь? Говоря на пальцах, это то, что есть в любом нормальном файловом менеджере, там можно написать myProgram.exe, а можно написать myProgram.exe a b c d, через пробел (если же написать "myProgram.exe a" b c d, то часть, заключённая в кавычки, будет пониматься как один параметр, несмотря на то, что в ней содержится пробел). Это означает, что ты вызываешь программу myProgram.exe с параметрами a, b, c, d. То, что написано в свойствая ярлыка в строке "Объект" - это тоже команда, как правило, она там без параметров. Когда ты открываешь файл "a.txt", на самом деле вызывается команда notepad.exe a.txt, то есть в качестве параметра идёт имя открываемого файла. Поэтому все приличные программы знают, когда надо при запуске показать пустое окно, а когда - сразу открыть файл.

Программа получает информацию о них через функции ParamCount (в данном примере, с myProgram.exe a b c d - 4), и через ParamStr(N) (N от 0 до 4).
Твоя программа может принимать до 3 параметров, надо отдельно разобрать случаи разного их количества, чтобы сформировать, что программа должна делать. Типа так:


var
Decode: boolean;
InFile, OutFile: string;

...
Decode := False;
InFile := '';
OutFile := '';
if ParamCount >= 1 then begin
if ParamStr(1) = '-c' then Decode := False
else if ParamStr(1) = '-d' then Decode := True
else InFile := ParamStr(1);
end;
if ParamCout >= 2 then begin
if InFile = '' then InFile := ParamStr(2) else OutFile := ParamStr(2);
end;
if ParamCount >= 3 then begin
if OutFile = '' then OutFile := ParamStr(3);
end;


Автор: lopata 15.04.2010 3:25

Спасибо. Стало немного понятней. А можешь привести какой-нибудь простой полный пример как это работает?

Автор: TarasBer 15.04.2010 13:53

Ну например, программа возводит одно число в степень другого, числа задаются как параметры.


program Test;

var
a, b: extended;
Code: integer;

begin

if ParamCount < 2 then begin
WriteLn('Must be >= 2 parameters!');
Exit;
end;
Val(Paramstr(1), a, Code);
if Code <> 0 then begin
WriteLn(Paramstr(1) , ' is not a number!');
Exit;
end;
Val(Paramstr(2), b, Code);
if Code <> 0 then begin
WriteLn(Paramstr(2) , ' is not a number!');
Exit;
end;

if a > 0 then WriteLn(exp(ln(a) * b))
else if a = 0 then WriteLn(0)
else if (Frac(b) = 0) and (Frac(b/2) = 0) then WriteLn(exp(ln(-a) * b))
else if (Frac(b) = 0) then WriteLn(-exp(ln(-a) * b))
else WriteLn('Invalid argument');

end.




Пример: в командной строке переходите в директорию с этой программой (например, cd c:\progra~1\delphi\projects\test\), потом в командной строке пишете test 2 2, она выводит 4.000000E+0000

Автор: lopata 15.04.2010 16:29

Spasibo ogromnoje.