Помощь - Поиск - Пользователи - Календарь
Полная версия: Многосвязные списки
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
D1ma
Всем привет.Требуется помощь в написании программы с использованием многосвязных список. Тему плохо понял, поэтому требуется помощь.
Задание: Найти короткую строку.
Сам код программы есть, требуется лишь поспотроить МС -)
 VAR
F:TEXT;
I:WORD;
C:CHAR;
N:WORD;
BEGIN
CLRSCR;
ASSIGN(F,'C:\F1.TXT');
RESET(F);
I:=0;
N:=60000;
WHILE NOT EOF(F) DO
BEGIN
IF EOLN(F) THEN
BEGIN
IF I<N THEN N:=I;
I:=0;
READ(F,C);
READ(F,C);
END;
READ(F,C);
I:=I+1;
END;
IF I<N THEN N:=I;
IF N=60000 THEN I:=0 ELSE I:=N;
WRITE('MIN = ');
WRITELN(I);

END.
volvo
Что в твоем понимании МС? Двухсвязный список? Мульти-список? Насколько МНОГОсвязным должен быть список?
D1ma
Цитата(volvo @ 13.04.2009 21:18) *

Что в твоем понимании МС? Двухсвязный список? Мульти-список? Насколько МНОГОсвязным должен быть список?

я как понял мульти-список
volvo
Что ты хочешь делать с мультисписком? Читать в него весь файл что-ли?
(Кстати, я помню, когда-то выкладывал программу, строящую мультисписок, посмотри в поиске.)
D1ma
Вот что получилось smile.gif :
Код
USES CRT;
CONST
PATH='C:\F1.TXT';
TYPE
DATA=STRING;
LINK=^RS;
RS=RECORD VAL:DATA;
          LNK:LINK;
          END;
TF=TEXT;
VAR
F:TF;
A:LINK;
B:WORD;

PROCEDURE ADD(VAR A:LINK;B:DATA);
BEGIN
     IF A<>NIL THEN ADD(A^.LNK,B) ELSE
     BEGIN
          NEW(A);
          A^.VAL:=B;
          A^.LNK:=NIL;
     END;
END;

PROCEDURE LOAD(VAR F:TF;VAR A:LINK);
VAR
I:DATA;
BEGIN
     ASSIGN(F,PATH);
     RESET(F);
     A:=NIL;
     WHILE NOT EOF(F) DO
     BEGIN
          READLN(F,I);
          ADD(A,I);
     END;
END;

PROCEDURE OUTPUT(A:LINK);
BEGIN
     WHILE A<>NIL DO
     BEGIN
          WRITELN(A^.VAL);
          A:=A^.LNK;
     END;
END;

PROCEDURE MIN(A:LINK;VAR B:WORD);
VAR
I:WORD;
BEGIN
     B:=256;
     WHILE A<>NIL DO
     BEGIN
          IF LENGTH(A^.VAL)<B THEN B:=LENGTH(A^.VAL);
          A:=A^.LNK;
     END;
     IF B=256 THEN B:=0;
END;

BEGIN
     CLRSCR;
     LOAD(F,A);
     OUTPUT(A);
     MIN(A,B);
     WRITELN;
     WRITELN('MIN=',B);
     READLN;
END.

Токо вот нужно без использования STRING, подравьте чуток - smile.gif
D1ma
Помогите исправить процедуру MIN. Список сформирован, необходимо найти длину короткой строки, используя CHAR.
SES CRT;
CONST
PATH='C:\F1.TXT';
TYPE
DATA=CHAR;
LINK=^RS;
RS=RECORD VAL:DATA;
LNK:LINK;
END;
TF=TEXT;
VAR
F:TF;
A:LINK;
B:WORD;

PROCEDURE ADD(VAR A:LINK;B:DATA);
BEGIN
IF A<>NIL THEN ADD(A^.LNK,B) ELSE
BEGIN
NEW(A);
A^.VAL:=B;
A^.LNK:=NIL;
END;
END;

PROCEDURE LOAD(VAR F:TF;VAR A:LINK);
VAR
I:DATA;
BEGIN
ASSIGN(F,PATH);
RESET(F);
A:=NIL;
WHILE NOT EOF(F) DO
BEGIN
READ(F,I);
ADD(A,I);
END;
END;

PROCEDURE OUTPUT(A:LINK);
BEGIN
WHILE A<>NIL DO
BEGIN
WRITE(A^.VAL);
A:=A^.LNK;
END;
END;

PROCEDURE MIN(A:LINK;VAR B:WORD);
VAR
I:WORD;
BEGIN
B:=256;
WHILE A<>NIL DO
BEGIN
IF LENGTH(A^.VAL)<B THEN B:=LENGTH(A^.VAL);
A:=A^.LNK;
END;
IF B=256 THEN B:=0;
END;

BEGIN
CLRSCR;
LOAD(F,A);
OUTPUT(A);
MIN(A,B);
WRITELN;
WRITELN('MIN=',B);
READLN;
END.
Krjuger

PROCEDURE MIN(A:LINK;VAR B:WORD);
VAR
I:WORD;
ch:integer;
BEGIN
B:=256;
WHILE A<>NIL DO
BEGIN
WHILE not eol(A^.Val) DO{либо eol либо eoln}
ch:=ch+1;

IF ch<B THEN B:=ch;
A:=A^.LNK
END;
IF B=256 THEN B:=0;
END;


Понимаеш char это одна буква,по сути ты находиш длинну, считывая строку побуквенно,зачем это делать я хз,но суть того, что я написал, мы берем строку и до тех пор пока не конец накручиваем счетчик ch, потом берем следующую опять накручиваем и сравниваем,меньшее записывает.
D1ma
Цитата(Krjuger @ 27.05.2009 18:28) *


PROCEDURE MIN(A:LINK;VAR B:WORD);
VAR
I:WORD;
ch:integer;
BEGIN
B:=256;
WHILE A<>NIL DO
BEGIN
WHILE not eol(A^.Val) DO{либо eol либо eoln}
ch:=ch+1;

IF ch<B THEN B:=ch;
A:=A^.LNK
END;
IF B=256 THEN B:=0;
END;


Понимаеш char это одна буква,по сути ты находиш длинну, считывая строку побуквенно,зачем это делать я хз,но суть того, что я написал, мы берем строку и до тех пор пока не конец накручиваем счетчик ch, потом берем следующую опять накручиваем и сравниваем,меньшее записывает.

то что char это 1 символ прекрасно понимаю smile.gif
Ну вот задали так...
Но ведь Eoln это ведь только для файловой переменной. а тут список...
Как быть?
Krjuger
Ну у меня то eoln не для списка,а только для A^.Val,а это string часть,для нее должно работать.а вообще подожди щас проверю.
мда действительно нельзя,извиняюсь.Тогда сделай так.

cch:char;
...........
WHILE A<>NIL DO
BEGIN
read(A^.Val,cch);
WHILE cch<>#13 DO{13-это enter}
begin
read(A^.Val,cch);
.................


так должно работать.
D1ma
Немного не понял, а почему именно 'enter'?
Krjuger
Ну а что ты нажимаеш,когда хочеш перейти на новую строку?Я вроде нажимаю enter.Поэтому логично,что если элемент char равен enter,то ты автоматически попадаеш на новую строку.
D1ma
эх, что-то не работает...
пробывал по всякому, но что-то не получается (
Кто сможет сделать за небольшое вознаграждение?
Krjuger
За вознаграждение,это уже немного в другую тему.
Lapp
Krjuger, я понимаю, что
Цитата
Не ругайте сильно,я только учусь.
- но почему ты заставляешь других учиться на твоих ошибках? Еще раз: проверяй свои творения перед публикацией! И учи матчасть.. smile.gif

D1ma, мне как-то странно, что у тебя данные имеют тип char, а не string (как в начале). Можешь пояснить? Ты понимаешь, что LENGTH(A^.VAL) всегда будет давать 1 в этом случае?

Ты не паникуй, сделаем. Только ты говори яснее, что ты хочешь получить и как.

Krjuger
Действительно,зачем ты тип данных в списке сменил???ведь у тебя теперь в дате всего 1 элемент,мой кусочек тоже рабоать так не станет..Кстати скинь заново весь код с исправления внесенными тобой...а то
"пробывал по всякому, но что-то не получается (" очень мало о чем гворит,ты же не сказал,что изменил
D1ma
Цитата(Lapp @ 1.06.2009 9:10) *

Krjuger, я понимаю, что - но почему ты заставляешь других учиться на твоих ошибках? Еще раз: проверяй свои творения перед публикацией! И учи матчасть.. smile.gif

D1ma, мне как-то странно, что у тебя данные имеют тип char, а не string (как в начале). Можешь пояснить? Ты понимаешь, что LENGTH(A^.VAL) всегда будет давать 1 в этом случае?

Ты не паникуй, сделаем. Только ты говори яснее, что ты хочешь получить и как.

Первый вариант рабочий, но как оказалось нельзя использовать STRING, а только CHAR.( до сих пор не пойму почему)
Далее string поменял на char,чуток подправил,посимвольный ввод работает.
Но вот как изменить процедуру min, я так и не додумался...

p.s. Вариант, предложенный Krjuger не работает.
read(A^.Val,cch); это допустимо только же для файлов? а тут список.
Lapp
Цитата(D1ma @ 1.06.2009 15:19) *
read(A^.Val,cch); это допустимо только же для файлов? а тут список.
Да, конечно.
То есть, ты имеешь в виду, что в каждом элементе списка только один символ?
Будь добр, подтверди (а лучше опровергни)), ибо мне все равно не верится в такое диво.
Может, переспросишь препа? или кого-нить еще..

В принципе, ничего особо трудного, ибо концы строк ты тоже заносишь в список.. но странно)).
D1ma
Цитата(Lapp @ 1.06.2009 15:30) *

Да, конечно.
То есть, ты имеешь в виду, что в каждом элементе списка только один символ?
Будь добр, подтверди (а лучше опровергни)), ибо мне все равно не верится в такое диво.
Может, переспросишь препа? или кого-нить еще..

В принципе, ничего особо трудного, ибо концы строк ты тоже заносишь в список.. но странно)).


Ну получается что только один символ, т.к. char, получается что подтверждаю smile.gif)

Krjuger
В общем я сделал для типа строка,но сразу говорю сделано довольнотаки кустарно,но работает,если надо то могу скинуть,но там я создаю буферный файл в который каждый раз перезаписываю строку,чтоб через чар посчитать его длинну...
Lapp
Цитата(D1ma @ 1.06.2009 17:04) *
Ну получается что только один символ, т.к. char, получается что подтверждаю smile.gif)
Сдается мне, что ты и не пытался уточнить.. Ладно, твое дело, в конце концов.
Лови.
PROCEDURE MIN(A:LINK;VAR B:WORD);
VAR
I:WORD;
BEGIN
B:=256;
i:=0;
WHILE A<>NIL DO begin
case A^.VAL of
#13: ;
#10: begin
if i<b then b:=i;
i:=0
end
else Inc(i)
end;
A:=A^.LNK;
END
END;

D1ma
Цитата(Lapp @ 1.06.2009 19:29) *

Сдается мне, что ты и не пытался уточнить.. Ладно, твое дело, в конце концов.
Лови.
PROCEDURE MIN(A:LINK;VAR B:WORD);
VAR
I:WORD;
BEGIN
B:=256;
i:=0;
WHILE A<>NIL DO begin
case A^.VAL of
#13: ;
#10: begin
if i<b then b:=i;
i:=0
end
else Inc(i)
end;
A:=A^.LNK;
END
END;


Спасибо smile.gif
только помойму последняя строка символов не проверяется на длину, т.к. если его длина меньше остальных
то не выдается его длина
Krjuger
вот тебе немног другая реализация,но как я и говрил вполне кустарно....Кстати вопрос больше в Лапу,когда я в дату списка записываю стринг,а потом скидываю строку во временный txt файл,то у меня окончание ознаменуется #26 это конец файла чтоли или как?


USES CRT;
CONST
PATH='C:\TPascal\F1.TXT';
TYPE
DATA=string;
LINK=^RS;
RS=RECORD VAL:DATA;
LNK:LINK;
END;
TF=TEXT;
VAR
F:TF;
A:LINK;
B,ch:WORD;
cch:char;
str:text;

PROCEDURE ADD(VAR A:LINK;B:DATA);
BEGIN
IF A<>NIL THEN ADD(A^.LNK,B) ELSE
BEGIN
NEW(A);
A^.VAL:=B;
A^.LNK:=NIL;
END;
END;

PROCEDURE LOAD(VAR F:TF;VAR A:LINK);
VAR
I:DATA;
BEGIN
ASSIGN(F,PATH);
RESET(F);
A:=NIL;
WHILE NOT EOF(F) DO
BEGIN
READ(F,I);
ADD(A,I);
readln(f);
END;
END;

PROCEDURE OUTPUT(A:LINK);
BEGIN
WHILE A<>NIL DO
BEGIN
WRITE(A^.VAL);
A:=A^.LNK;
writeln;
END;
END;

PROCEDURE MIN(A:LINK;VAR B:WORD);
VAR
I:WORD;
BEGIN
B:=256;
WHILE A<>NIL DO
BEGIN
ch:=0;
rewrite(str);
write(str,a^.val);
reset(str);
read(str,cch);
while cch<>#26 do begin
read(str,cch);
ch:=ch+1;
end;
IF ch<B THEN B:=ch;
A:=A^.LNK;
END;
IF B=256 THEN B:=0;
END;

BEGIN
CLRSCR;
assign(str,'C:\TPascal\f2.txt');
LOAD(F,A);
OUTPUT(A);
MIN(A,B);
WRITELN;
WRITELN('MIN=',B);
READLN;
END.


Еще так как это не рабочий вариант,то я файлы не закрыл,думаю сам справишся.
Lapp
Цитата(D1ma @ 1.06.2009 20:15) *
последняя строка символов не проверяется на длину,
Да, ошибся я. Секундочку..
Ну, вот так можно, наверное..
PROCEDURE MIN(A:LINK;VAR B:WORD);
VAR
I:WORD;
BEGIN
B:=256;
i:=0;
WHILE A<>NIL DO begin
case A^.VAL of
#13: ;
#10: begin
if i<b then b:=i;
i:=0
end
else Inc(i)
end;
A:=A^.LNK;
END;
if i<b then b:=i;
END;

Только ты спрячь и не показывай volvo. А то тут одна строка кода сдублирована...
smile.gif


Добавлено через 1 мин.
Пожалуйста, не надо всякий раз цитировать ВЕСЬ предыдущий мессадж при ответе.
Krjuger
Цитата

Только ты спрячь и не показывай volvo. А то тут одна строка кода сдублирована...

УУУУууу.....молись,в прошлый раз volvo конкурс устроил,как избавиться от условия))))Растерзает ведь...
Lapp
Нет, погоди, так снова неправильно. Дай минутку.

Добавлено через 12 мин.
Вот так будет правильно:
PROCEDURE MIN(A:LINK;VAR B:WORD);
VAR
I:WORD;
BEGIN
B:=256;
i:=0;
WHILE A<>NIL DO begin
case A^.VAL of
#13: ;
#10: begin
if i<b then b:=i;
i:=0
end
else Inc(i)
end;
A:=A^.LNK;
END;
if (0<i)and(i<b) then b:=i else if b=256 then b:=0
END;

D1ma
в общем, оказалось что это вовсе не многосвязный список... nea.gif

Как же надоела эта задача... mad.gif

Код

uses crt;
type slov=^slovo;
     slovo=record
     sim:char;
     ss:slov;
     end;
     spisok=^zveno;
     zveno=record
     sl:slov;
     cc:spisok;
     end;
var s,s1,s2:spisok;
    t:text;
    b,i:word;
begin
clrscr;
assign(t,'C:/f1.txt');
reset(t);
s1:=nil;
while not eof(t) do begin
new(s);
s2^.sl:=nil;
  while not eoln(t) do begin
   new(s^.sl);
   read(t,s^.sl^.sim);
   s^.sl^.ss:=s2^.sl;
   s2^.sl:=s^.sl;
  end;
readln(t);
s^.cc:=s1;
s1:=s;
end;
close(t);

while s<>nil do begin
while s^.sl<>nil do begin
  write(s^.sl^.sim);
  s^.sl:=s^.sl^.ss;
end;
writeln;
s:=s^.cc;
end;

b:=256;
i:=0;
While S<>nil do begin
Case S^.sl^.sim of
      #13:;
      #10: begin
if i<b then b:=i;
        i:=0
      end
      else Inc(i)
    end;
     s:=s^.cc;
end;
if (0<i)and(i<b) then b:=i else if b=256 then b:=0;
write('MIN=',b);
end.

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

D1ma
Блин...
В чем ошибка?
D1ma
Решил сначала попробывать с использованием типа STRING, c ним все просто

Код

b:=256;
while s<>nil do begin
while s^.sl<>nil do begin
write(s^.sl^.sim);
if length(S^.sl^.sim)<b then b:=length(S^.sl^.sim);
s^.sl:=s^.sl^.ss;
end;
writeln;
s:=s^.cc;
end;write(b);


Но нужно с использованием Char.
В общем считает, но не отдельную строку, а всю длину.
Код

hile s<>nil do begin
while s^.sl<>nil do begin
  write(s^.sl^.sim);

Case S^.sl^.sim of
      #13:;
      #10: begin
if i<b then b:=i;
        i:=0
      end
      else Inc(i)
    end;
    
end;

s^.sl:=s^.sl^.ss;
end;
writeln;
s:=s^.cc;
end;
if (0<i)and(i<b) then b:=i else if b=256 then b:=0;
write('MIN=',b);

Как сделать чтобы считал не всю длину, а токо длину строки?
D1ma
Решил попробывать вот так:

while s<>nil do begin
Case S^.sl^.sim of
#13:;
#10: begin
if i<b then b:=i;
i:=0
end
else Inc(i)
end;

while s^.sl<>nil do begin
write(s^.sl^.sim);

s^.sl:=s^.sl^.ss;
end;
writeln;
s:=s^.cc;
end;
if (0<i)and(i<b) then b:=i else if b=256 then b:=0;
write('MIN=',b);


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

М
Пожалуйста, пользуй тэги code=pas /code

Lapp
Я довольно много поменял тут..
Разберешься?
type
pSlovo= ^Slovo;
Slovo= record
c: char;
Next: pSlovo;
end;
pSpisok=^Spisok;
Spisok=record
s,s1: pSlovo;
Next: pSpisok;
end;

var
L,L1: pSpisok;
t: text;
b,i: word;

begin
assign(t,'f1.txt');
reset(t);
L:=nil;
while not eof(t) do begin
if L=nil then begin
New(L);
L1:=L
end
else begin
New(L^.Next);
L:=L^.Next
end;
with L^ do begin
next:=nil;
s:=nil;
while not eoln(t) do with s^ do begin
if s=nil then begin
New(s);
s1:=s
end
else begin
New(s^.next);
s:=s^.next
end;
with s^ do begin
read(t,c);
next:=nil
end
end;
readln(t);
end
end;
close(t);

L:=L1;
while L<>nil do with L^ do begin
s:=s1;
while s<>nil do with s^ do begin
write©;
s:=Next
end;
writeln;
L:=Next
end;

b:=256;
L:=L1;
while L<>nil do with L^ do begin
i:=0;
s:=s1;
while s<>nil do with s^ do begin
case c of
#13:;
#10: begin
if i<b then b:=i;
i:=0
end
else Inc(i)
end;
s:=Next
end;
L:=Next
end;
if (0<i)and(i<b) then b:=i else if b=256 then b:=0;
write('MIN=',b)
end.
D1ma
Спасибо!!! smile.gif
Плохо разобрался токо, немогли бы написать действие след. операторов? -)


L1:=L;

s1:=s;

L:=Next;

s:=Next;

L:=Next;

Lapp
Цитата(D1ma @ 8.06.2009 17:01) *
немогли бы написать действие след. операторов?
Ты лучше в программе комментами пиши, какое именно место непонятно и почему.

L1:=L;
s1:=s;
- запомнить начало списка

L:=Next;
s:=Next;
- продвижение вперед по списку
D1ma
Исправьте что не так smile.gif


while not eof(t) do begin
if L=nil then begin
New(L);
L1:=L {Запоминаем начало списка}
end
else begin
New(L^.Next);
L:=L^.Next {переход на след. элемент}
end;
with L^ do begin
next:=nil;{обнуляем ссылку}
s:=nil;
while not eoln(t) do with s^ do begin
if s=nil then begin
New(s);
s1:=s {Запоминаем начало подсписка}
end
else begin
New(s^.next);
s:=s^.next {переход на след. элемент}
end;
with s^ do begin
read(t,c);
next:=nil {обнуляем ссылку}
end
end;
readln(t) ; {?}
end
end;
close(t);

L:=L1;
while L<>nil do with L^ do begin
s:=s1; {Запоминаем начало подсписка}
while s<>nil do with s^ do begin
write©;
s:=Next {продвижение вперед по списку}
end;
writeln;
L:=Next {продвижение вперед по списку}
end;

b:=256;
L:=L1;
while L<>nil do with L^ do begin
i:=0;
s:=s1;
while s<>nil do with s^ do begin
case c of
#13:;
#10: begin
if i<b then b:=i;
i:=0
end
else Inc(i)
end;
s:=Next {продвижение вперед по списку}
end;
L:=Next {продвижение вперед по списку}
end;

Krjuger
Ну а ты скажи,что не так и тебе исправят..Где ошибка,то? что тебя не устраивает?Уу тебя в руках всегда есть встроеный в паскаль дебагер,где ты можеш проверить все изменения переменных при каждом шаге,только для этого надо самому понимать,что должно происходить и что произошло и смотреть где именно ошибка,и тогда уже думать,как это исправить.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.