IPB
ЛогинПароль:

> Прочтите прежде чем задавать вопрос!

1. Заголовок темы должен быть информативным. В противном случае тема удаляется ...
2. Все тексты программ должны помещаться в теги [code=pas] ... [/code].
3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора).
5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM!
6. Одна тема - один вопрос (задача)
7. Проверяйте программы перед тем, как разместить их на форуме!!!
8. Спрашивайте и отвечайте четко и по существу!!!

 
 Ответить  Открыть новую тему 
> Распаковка сжатого файла, Работа с очередью
FENIX
сообщение 9.04.2005 17:39
Сообщение #1


Новичок
*

Группа: Пользователи
Сообщений: 45
Пол: Мужской

Репутация: -  0  +


Задание такое:
Распаковка сжатого файла.
Файл представляет собой последовательность цепочек вида: <Число><Символ>. Переписать содержимое файла в очередь и преобразовать последовательность по правилу: каждую цепочку заменить на указанное число символов. Например: ‘7a12c4d’ заменяется на ‘aaaaaaaccccccccccccdddd’. Результат записать в выходной файл.

Сделал очередь, из файла читается все нормально. Но абсолютно не могу представить даже приблизительной реализации алгоритма задачи.
Help plz blink.gif

Код

Uses Crt;

Type
  Inf = String;
  Ptr = ^EL;
  EL = record
            Dn : Inf;
            Nx : Ptr;
           end;

  Queue = object
           p : ptr;
           Constructor Init;
           Function Empty : boolean;
           Procedure Push(D : Inf);
           Procedure Print;
           Function Pop : Inf;
           Destructor Done;
           end;


Constructor Queue.Init;
begin
  p := nil
end;

Destructor Queue.Done;
var q : Ptr;
begin
  while p <> nil do
  begin
     q := p;
     p := p^.Nx;
     dispose(q);
  end;
  p := nil;
end;

Function Queue.Empty : boolean;
begin
  If p = nil then
  Empty := false
  else Empty := true;
end;

Procedure Queue.Push(D : Inf);
var q : Ptr;
begin
  New(q);
  q^.Dn := D;
  q^.Nx := p;
  p := q;
end;

Function Queue.Pop : Inf;
var q : Ptr;
begin
  q := p;
  If q^.Nx = nil then
  begin
     Pop := q^.Dn;
     dispose(q);
     p := nil;
  end;

  While q^.Nx^.Nx <> nil do q := q^.Nx;
  Pop := q^.Dn;
  dispose (q^.Nx);
  q^.Nx := nil;
end;

Procedure Queue.Print;
var q : Ptr;
begin
  q := p;
  while q <> nil do
  begin
     write(q^.Dn : 4, ' ');
     q := q^.Nx;
  end;
  writeln;
end;

var   Q1 : Queue;
     input, output : text;
     s, sl : string;
     i, code : integer;

 BEGIN

   ClrScr;
   assign(input, 'input.txt');
   reset(input);
   assign(output, 'output.txt');
   rewrite(output);
   Q1.Init;
   writeln('DO= ',MemAvail);
   writeln;
   While not EOF(input) do
     begin
        sl := '';
        readln(input, s);
        If s[length(s)] <> ' '
        then s := s + ' ';
        For i := 1 to length(s) do
        If s[i] <> ' '
        then
           sl := sl + s[i]
        else
        If length(sl) <> 0 then
        begin
           Q1.Push(sl);
           sl := '';
        end;
     end;

   Q1.Print;
   Q1.Done;
   Close(input);
   writeln;
   writeln('POSLE= ',MemAvail);
   readkey;

END.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
volvo
сообщение 9.04.2005 17:54
Сообщение #2


Гость






Погоди, а что записывается в очередь? Зачем ты определил элемент очереди, как строку ? не хватило ли бы просто записи (Integer + char) ?
 К началу страницы 
+ Ответить 
volvo
сообщение 9.04.2005 18:00
Сообщение #3


Гость






Кстати, опять кое-что можно улучшить ;)
Код
Destructor Queue.Done;
begin
 while not Empty do Pop
end;

Function Queue.Empty : boolean;
begin
 Empty := (p = nil)
end;

А у тебя Empty будет возвращать неправильное значение...
 К началу страницы 
+ Ответить 
FENIX
сообщение 9.04.2005 19:00
Сообщение #4


Новичок
*

Группа: Пользователи
Сообщений: 45
Пол: Мужской

Репутация: -  0  +


Цитата(volvo @ 9.04.05 17:54)
Погоди, а что записывается в очередь? Зачем ты определил элемент очереди, как строку ? не хватило ли бы просто записи (Integer + char) ?

Не знаю :D Делал самым понятным мне способом.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
volvo
сообщение 9.04.2005 19:03
Сообщение #5


Гость






Я бы сделал так: читаешь из файла строку, разбиваешь ее на числа/символы и каждую такую пару ставишь в очередь... Когда считал весь файл - просто берешь очередное значение из очереди и записываешь <символ> столько раз в выходной файл, сколько нужно (согласно значению <числа>)...
 К началу страницы 
+ Ответить 
volvo
сообщение 9.04.2005 20:33
Сообщение #6


Гость






Приблизительно вот так (не обращай внимания на определение очереди, главное - КАК она используется):
Код
type
 trec = record
   count: integer;
   ch: char;
 end;
 ttype = trec;

{$i dds_lib\item.pas}
type
 pttype = ^ttype;
 tqueue = object
   head, tail: ptitem;

   constructor init;
   destructor done;

   procedure put(x: ttype);
   function get: pttype;

   function empty: boolean;
 private
   last_read: pttype;
 end;


constructor tqueue.init;
 begin
   head := nil; tail := nil;
   new(last_read)
 end;
destructor tqueue.done;
 begin
   dispose(last_read);
   while empty do get
 end;

procedure tqueue.put(x: ttype);
 var p: ptitem;
 begin
   new(p, init(x, nil));
   if empty then head := p
   else tail^.next := p;
   tail := p
 end;

function tqueue.get: pttype;
 var p: ptitem;
 begin
   get := nil;
   if not empty then
     begin
       p := head;
       head := head^.next;

       last_read^ := p^.info;
       dispose(p, done);
       get := last_read
     end
   else
     begin
       writeln('reading from empty queue');
       halt(102)
     end;
 end;

function tqueue.empty: boolean;
 begin
   empty := not assigned(head)
 end;

{ Все самое интересное - здесь... }
var
 q: tqueue;

procedure convert_str(s: string);
var
 i, err: integer;
 to_number: string;
 r: trec;
begin
 i := 1; to_number := '';
 while i <= length(s) do begin
   while s[i] in ['0' .. '9'] do
     begin
       to_number := to_number + s[i];
       inc(i);
     end;
   val(to_number, r.count, err);
   to_number := '';
   r.ch := s[i]; inc(i);

   q.put(r)
 end;

end;

var
 f: text;
 s: string;
 pr: pttype;
 i: integer;

begin
 assign(f, 'fenix.txt');
 {$i-} reset(f); {$i+}

 q.init;
 while not eof(f) do begin
   readln(f, s);
   convert_str(s)
 end;

 while not q.empty do
   begin
     pr := q.get;
     for i := 1 to pr^.count do
       write(pr^.ch);
   end;

 q.done;

 close(f)
end.

В качестве исходного файла тестировался файл с единственной строкой - которую ты привел в задании... Ну, естественно, что в файл моя программа не пишет, я ее делал для проверки алгоритма...


Прикрепленные файлы
Прикрепленный файл  FENIX.TXT ( 9 байт ) Кол-во скачиваний: 167
 К началу страницы 
+ Ответить 
FENIX
сообщение 10.04.2005 0:36
Сообщение #7


Новичок
*

Группа: Пользователи
Сообщений: 45
Пол: Мужской

Репутация: -  0  +


Спасибо большое! smile.gif

{Ушел разбирать код}

===============

Хммм... Что-то я запутался в обилии типов...
Как я понял, отдельный элемент, добавляемый и извлекаемый (функции Push и Pop у меня) - это запись из двух полей?
Т.е. мне свой Inf надо также поменять? Однако если я его меняю подобным образом, компилятор пишет, что возвращаемое ф-ей Pop значение неверно...
Что-то я совсем потерялся blink.gif

Сообщение отредактировано: FENIX - 10.04.2005 1:39
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
volvo
сообщение 10.04.2005 8:59
Сообщение #8


Гость






FENIX, я же написал:
Цитата(volvo @ 9.04.05 20:33)
(не обращай внимания на определение очереди, главное - КАК она используется)

Тем более, что откомпилировать мой код ты все равно не сможешь - не хватает файла ITEM.PAS...
Цитата
Т.е. мне свой Inf надо также поменять? Однако если я его меняю подобным образом, компилятор пишет, что возвращаемое ф-ей Pop значение неверно...
Это - потому, что ты пытаешься вернуть саму запись (что противоречит синтаксису языка), а я возвращаю указатель на нее (что, кстати, вполне законно ;) ).
 К началу страницы 
+ Ответить 
FENIX
сообщение 10.04.2005 21:49
Сообщение #9


Новичок
*

Группа: Пользователи
Сообщений: 45
Пол: Мужской

Репутация: -  0  +


Блин, полдня пытался сделать, ничего не получилось blink.gif
Никак не могу преобразовать код под мою прогу...
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
volvo
сообщение 10.04.2005 22:18
Сообщение #10


Гость






FENIX,
есть 2 пути:
1 - я могу конечно выслать тебе файл, которого не хватает, но это навряд ли тебе поможет, т. к. скорее всего, эту программу просто не примут...
2 - переделаем чуть-чуть твою программу так, чтобы она работала с моим типом TRec:
Код
type
 ttype = word;

 ptitem = ^titem;
 titem =
   record
     data: ttype;
     next: ptitem;
   end;

 tqueue = object
   head, tail: ptitem;
   constructor init;
   destructor done;

   procedure put(x: ttype);
   function get: ttype;

   function empty: boolean;
   procedure print;
 end;


constructor tqueue.init;
begin
 head := nil; tail := nil;
end;
destructor tqueue.done;
begin
 while not empty do get
end;

procedure tqueue.put(x: ttype);
var p: ptitem;
begin
 new(p);
 p^.data := x;
 p^.next := nil;
 if empty then head := p
 else tail^.next := p;
 tail := p
end;

function tqueue.get: ttype;
var p: ptitem;
begin
 if not empty then begin
   p := head;
   head := head^.next;

   get := p^.data;
   dispose(p);
 end
 else begin
   writeln('reading from empty queue');
   halt(102)
 end;
end;

function tqueue.empty: boolean;
begin
 empty := not assigned(head)
end;

procedure tqueue.print;
var p: ptitem;
begin
 p := head;
 write('(queue) <');
 while assigned(p) do begin
   write(p^.data, ' ');
   p := p^.next
 end;
 writeln('>')
end;

{
 Вот до этого места - все, как у тебя -
 очередь которая работает с Word-ами
}

{ А вот дальше... }
type
{
 определяем запись в которой поля count и ch
 хранятся там же, где и поле to_queue (они физически
 занимают одно место в памяти).
 Это называется запись с селектором
}
 trec = record
 case boolean of
   false: (count: byte; ch: char);
   true : (to_queue: word);
 end;

var
 q: tqueue;
 f: text;

procedure convert_str(s: string);
var
 i, err: integer;
 to_number: string;
 r: trec;
begin
 i := 1; to_number := '';
 while i <= length(s) do begin
   while s[i] in ['0' .. '9'] do
     begin
       to_number := to_number + s[i];
       inc(i);
     end;
   val(to_number, r.count, err);
   to_number := '';
   r.ch := s[i]; inc(i);

   q.put(r.to_queue)
{
 пишем то мы содержимое поля to_queue, но
 эффект такой, как будто мы записали другие 2 поля
}
 end;

end;

var
 s: string;
 i: integer;
 rec: trec;

begin
 assign(f, 'fenix.txt');
 {$i-} reset(f); {$i+}

 q.init;
 while not eof(f) do begin
   readln(f, s);
   convert_str(s)
 end;

 while not q.empty do
   begin
{
 то же самое и с чтением, читаем вроде бы Word,
 но на самом деле рассматриваем его как Byte + Char
}
     rec.to_queue := q.get;
     for i := 1 to rec.count do
       write(rec.ch);
   end;

 q.done;
 close(f)
end.

Что не понятно - спрашивай ;)
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



- Текстовая версия 19.07.2025 18:12
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"