Помощь - Поиск - Пользователи - Календарь
Полная версия: Кодирование длин серий . Текстовый файл.
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
lopata
Помогите пожалуйста разобраться как делать.

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

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

Пример:
Изображение


Файлы я пока не трогала...Попыталась просто кодировать. В переменную 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
А если вот так попробовать:
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
Спасибо) поняла
lopata
Не получается с декодированием. Не могу понять почему больше 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
Цитата
end; i:= j+1;
Эту строку исправляй немедленно! smile.gif Иначе она принесет тебе немало проблем в дальнейшем. Переменная цикла для тебя - табу. Ты имеешь к ней доступ для чтения, но для записи - ни в коем случае. Компилятор сам решает, когда и как изменять эту переменную. Тебе этого делать нельзя.
lopata
Ок)
Насчет последнего исправления тоже неверно. Я так обрадавалась, что количесиво d уменьшилось, что даже не заметила что их 5 вместо 4(
Client
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
Спасибо, Client.
Просто обидно, что у меня никогда ничего не работает(

Добавлено через 14 мин.
volvo, а что у меня неправильно?/
Client
Узнаешь код
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
Хм..но работает неверно.
Вадает результат abbccccccccccddend
пропустило последий символ.
А если задать abb3c4cEnd, то вообще не получается.
Client
вариант что в коде - 10 "с" и 4 "d"
Цитата
А если задать abb3c4cEnd, то вообще не получается.
То 7 "с" и получается
lopata
Сорри. Имела в виду abb3c4dEnd.
Походу я что-то недопонимаю...
volvo
Цитата
Сорри. Имела в виду abb3c4dEnd.
В чем проблема?
Нажмите для просмотра прикрепленного файла

Что ты ожидала получить?
lopata
Снова извините. Переклинило.
lopata
Не мог бы кто-нибудь объяснить про командную строку?
TarasBer
ParamCount - число параметров командной строки.
ParamStr(N) - N-ый параметр, строковый тип. ParamStr(0) - само имя программы, с полным путём к ней.
lopata
Честно говоря вообще не понимаю как это должно работать
Unconnected
Ну тебе надо получить 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 или даже обойтись без процедур.
Гость
Цитата(Unconnected @ 13.04.2010 22:06) *

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

Эммм...А что это значит?
Client
это значит что надо выполнить выбранное действие
TarasBer
Что такое командная строка - знаешь? Говоря на пальцах, это то, что есть в любом нормальном файловом менеджере, там можно написать 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
Спасибо. Стало немного понятней. А можешь привести какой-нибудь простой полный пример как это работает?
TarasBer
Ну например, программа возводит одно число в степень другого, числа задаются как параметры.


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
Spasibo ogromnoje.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.