Помощь - Поиск - Пользователи - Календарь
Полная версия: Очередь
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Jill
Есть программка - демонстрация работы очереди. Рабочая. Трабл в том, что менюха выбора действий Case of позволяет провести ОДНО действие. При перестановках всяких...очередь куда-то теряется sad.gif

Как сделать так, чтобы менюха висела постоянно (до команды "Выход"), и действий можно было МНОГО совершать над этой...очередью!!!

ПЛЗ!!!

Вот, собственно, программка:
Исходный код

Program SOD_3;
Uses Crt;
Type Pointer=^Line;
Line=Record
Inf:Integer;
Next:Pointer;
End;
Var Head, {голова очереди}
Tail, {хвост очереди}
First, {очередной элемент очереди}
PointerNew,P,NewP:Pointer;
f:boolean;
i:Integer;
a:Real;

{Вставка элемента в очередь}
Procedure Vstavka(Var Head,NewP,Tail:Pointer);
Var a:Real;
Begin
f:=True;
Repeat
Write('Введите целое число -> ');
{$I-} {временно отключаем контроль ошибок ввода-вывода}
Readln(a);
{$I+}
if IOResult<>0 then {ф-ция возвращает целое значение,
являющееся состоянием последней выполненной операции ввода-вывода}
begin
f:=False;
Exit;
end
Until (IOResult=0)and(a>=-32768)and(a<=32767);
New(NewP);
If Head=Nil then {очереди нет - создаем ее}
Head:=NewP
else
Tail^.Next:=NewP; {очередь есть - становимся в хвост}
Tail:=NewP; {новый хвост}
NewP^.Inf:=trunc(a);
NewP^.Next:=Nil;
End;

{Просмотр содержимого очереди}
Procedure Vyvod(Var Head,Tail:Pointer);
Begin
First:=Head;
if First<>Nil then
begin
Head:=First^.Next;
Write(First^.Inf,' ');
end;
End;

{удаление элемента}
Procedure Udalenie(var Head,Tail:Pointer);
var First:Pointer;
Begin
If Head<>Nil
then If Head=Tail {в очереди единственный элемент}
then begin Dispose(Head); Head:=Nil; Tail:=Nil end
else begin
First:=Head; Head:=Head^.Next; Dispose(First)
end
else Writeln('Удалять нельзя, т.к. очередь пуста!')
End;

{поиск максимального элемента}
Procedure Maximal(Head,Tail:Pointer);
Var K,First:Pointer;
max:Integer;
begin

if Head=Nil then Writeln('Очередь пуста!')
else begin
K:=Head;
First:=K^.Next;
max:=K^.Inf;
while First<>Nil do
begin
if max<First^.Inf then max:=First^.Inf;
First:=First^.Next;
end;
Writeln;
Writeln('Максимальный элемент: ',max);
Writeln;
end;
end;

{Основной модуль}
Begin
ClrScr;
Head:=Nil;
Mark(P);
Writeln;
Writeln('=================Создание очереди===================');
Writeln;
Writeln('Признак окончания ввода очереди - НЕ числовой символ');
Repeat Vstavka(Head,PointerNew,Tail) until not f;
if Head=Nil then
begin
Writeln('Очередь пуста!');
Readln;
Readln;
Exit;
end;
Writeln;
Writeln('Возможно произвести следующие действия:');
Writeln;
Readln;

Writeln('Показать очередь - 0');
Writeln('Добавить элемент - 1');
Writeln('Удалить элемент - 2');
Writeln('Найти максимальный - 3');
Writeln('Выход - 4');
Writeln;
Readln(i);

Case i of
0: begin First:=Head;
Writeln('Содержимое очереди:');
While First<>Nil do
Vyvod(Head,Tail); Readln; end;

1: begin First:=Head;
Vstavka(Head,NewP,Tail);
Writeln('Содержимое очереди:');
While First<>Nil do
Vyvod(Head,Tail); Readln; end;

2: begin First:=Head;
Udalenie(Head,Tail);
Writeln('Содержимое очереди:');
While First<>Nil do
Vyvod(Head,Tail); Readln; end;

3: begin First:=Head;
Maximal(Head,Tail);
Readln; end;

4: Exit end;

Readln;
Release(P); {освобождение кучи, начиная с адреса P}
End.


ЗЫ: препод злой - придираться будет к любым мелочам...
volvo
...
repeat
ClrScr;
Writeln;
Writeln('Возможно произвести следующие действия:');
Writeln;

Writeln('Показать очередь - 0');
Writeln('Добавить элемент - 1');
Writeln('Удалить элемент - 2');
Writeln('Найти максимальный - 3');
Writeln('Выход - 4');
Writeln;
Readln(i);

Case i of
0: begin First:=Head;
Writeln('Содержимое очереди:');
While First<>Nil do
Vyvod(Head,Tail); Readln; end;

1: begin First:=Head;
Vstavka(Head,NewP,Tail);
Writeln('Содержимое очереди:');
While First<>Nil do
Vyvod(Head,Tail); Readln; end;

2: begin First:=Head;
Udalenie(Head,Tail);
Writeln('Содержимое очереди:');
While First<>Nil do
Vyvod(Head,Tail); Readln; end;

3: begin First:=Head;
Maximal(Head,Tail);
Readln; end;
end;
until (i = 4);
...
Jill
по логике - так, но... ОНА ОПЯТЬ ПРОПАДАЕТ!!!
при выбора вротого по счету действия - один ответ - "Очередь пуста!" sad.gif
volvo
Ты просто при первой же распечатке очереди полностью "расстраиваешь" указатели, и они начинают указывать совсем не туда, куда ты думаешь... Попробуй так:
procedure PrintQueue(Head: Pointer);
begin
While Head <> nil Do Begin
Write(Head^.Inf:4);
Head := Head^.Next;
End;
end;
и вызывай
  PrintQueue(Head);
вместо
  While First<>Nil do
Vyvod(Head,Tail);



P.S. Это конечно не мое дело, но вот тип указателя на Line не стоит называть Pointer, т.к. тип Pointer в Паскале уже существует. Тем более, что
Цитата
препод злой - придираться будет к любым мелочам...
volvo
И еще... Вот альтернативный вариант реализации меню, все время "висящего" сверху:
...
clrscr;

{ Отрисовываем опции на экране }
Writeln('show - 0');
Writeln('add - 1');
Writeln('delete - 2');
Writeln('find max - 3');
Writeln('exit - 4');
Writeln;

{ Разрешаем программе работать только с нижней частью экрана }
window(1, 10, 80, 24);
repeat
repeat
i := Ord(ReadKey) - Ord('0'); { Берем выбор пользователя, без ReadLn }
until i in [0 .. 4];

Case i of
1: ...
2: ...
3: ...
end;
until (i = 4);
window(1, 1, 80, 25); { Восстанавливаем окно на весь экран }
Clrscr;
...
Jill
таки-да - куда попало указывают ;-)

вроде ОК!!! спасибо большое :-) хоть с одной задачей разобралась... еще четыре...ууууух


ЗЫ: насчет Pointer вообще спасибо (буду знать, что не стоит) / но мысля эта не сама ко мне пришла - из методички нашего универа (ХАИ), содранной с инета ;-)
Jill
ух ты!!! интересно оЧЧЧ

попробую обязательно

спасибо smile.gif

вообще из программки ляльку сделали ;)
Jill
уууупс!!! все процедурки работают КРОМЕ УДАЛЕНИЯ!!! вываливается нафиг паскаль

что там не так??? sad.gif
volvo
...
If Head<>Nil
then If Head=Tail { <--- Вот это ! }
...

В Паскале нельзя сравнивать указатели друг с другом - можно только с Nil... Чтобы проверить, единственный ли это элемент:
If Head <> Nil Then
If Head^.Next = Nil { <--- Так должно быть... }


P.S. Да и вообще, что мешает сделать так:
Procedure Udalenie(var Head, Tail: Pointer);
var First: Pointer;
Begin
If Head<>Nil Then Begin
First:=Head; Head:=Head^.Next; Dispose(First);
If Head = nil Then Tail := nil
End
Else Writeln('Удалять нельзя, т.к. очередь пуста!')
End;
?
Jill
ууууууууууу sad.gif

а так - черти что после удаления выдает..........

______________________________
я погибну под этой задачей.......
volvo
Пост №4 перечитай, и сравни со своим выводом...
PrintQueue(Head);
Так - не работает?
Jill
сейчас вообще что попало выводит sad.gif
c
PrintQueue(First);
только удаление не проходило...

забор полнейший...sad.gif
volvo
Не знаю, у меня все работает... Посмотри:
Jill
действительно работает...

пошла разбираться в чем дЫк

спасибо БОЛЬШОЕ!!! :-)
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.