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

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

Форум «Всё о Паскале» _ Задачи _ Покритекуйте,укажите на ошибки..

Автор: Andrewshkovskii 16.03.2007 4:09

ЗА 1 день попытался освоить стек,и написать под него процедуры ,вот что получилось..
Единственное что не могу реализовать это :
Нормальное создание стека ,без "нулевого" элемента.(была проблема с ограничением стека,и последующией проверкой на переполнение,пришлось идти обходными путями)
Добавление сразу нескольких элементов.
Думаю завтра все осилить..или попытатся хотябы.
вот,осудите по все строгости,хочу нормально заботать стеки..

Program stekT;   {Created and Tested By Andrewshkovskii}
uses crt;
type
StekType=integer;
L1 = ^stack;
Stack = record
inf:StekType;
link:l1;
end;
var
top:L1;
m:StekType;
el:StekType;
maxE:integer;
procedure DelFStek(var top:l1); {Удаляет первый элемент стэка,использовать для ввода стека(ввод до элемента 0)}
var
k:l1;
m:StekType;
begin
if top=nil then
writeln('Stek is empty')
else
begin
m:=top^.inf;
k:=top;
Top:=top^.link;
dispose(k);
end;
end;

function EmptyStek(top:l1):boolean; (*проверка на пустоту стэка*)
begin
EmptyStek:=(top=nil);
end;
function StekOver(top:l1;maxe:integer):boolean; (*проверка на переполнение стэка *)
var
j:Integer;
k:l1;
begin
j:=0;
k:=top;
if NOT (EmptyStek (k)) then
while k<>Nil do
begin
j:=j+1;
k:=k^.link;
end;
StekOver:=(j>=maxe);
end;

procedure NewStek(top:l1); (**создание пустого стэка *)
begin
top:=nil;
end;
procedure InputStek(var top:l1;var El:StekType); (*добавление элемента в стек*)
var
k:l1;
i:integer;
begin
new(k);
k^.inf:=El;
if not (StekOver(top,maxe)) then
begin
k^.link:=Top;
Top:=k
end
else
begin
writeln;
writeln('Stek perepolnen!');
end;
end;

procedure BStek(var Top:l1); (*создание стэка с элементами с вводом элементов*)
var
k:l1;
i:integer;
el:StekType;
begin
top:=Nil;
repeat
clrscr;
writeln('Vvedite maks 4islo elementov steka(minimum 2)');
readln(MaxE);
if (MaxE<=0) then
begin
writeln('Vi vveli 0 ili otricatelnoe zna4enie kol-va elementov v steke!');
writeln('Eto ne dopystimo!Povtorite vvod!');
writeln('Press any key...');
readkey;
end;
until MaxE>0;
writeln('Vvedite elementi steka');
Writeln('Koncom vvoda yavlyaetsya element 0');
while el<>0 do
begin
readln(el);
inputstek(top,el);
end;
end;

procedure StekView(var top:l1); (*просмотр стэка*)
var
K:l1;
begin
if Top = nil then
writeln('Stek Pyst dlya prosmotra!')
else
begin
k:=top;
writeln('Elementi steka');
while k<>nil do
begin
writeln(k^.inf);
K:=k^.link;
end;
end;
end;

procedure StekDel(var top:L1); (*Удаление элемента стэка*)
var
k:L1;
i,DelVal,m:integer;
begin
If top = nil then
writeln('Stek Pyst Dlya ydaleniya')
else
begin
repeat
writeln('Skolko elementov ydalit iz STEKA(!!) ?');
readln(DelVal);
if DelVal > MaxE then
begin
writeln('Kol-vo elementov k ydaleniu bolshe kol-va elementov v steke!');
writeln('Povtorite Vvod!');
writeln('Press any key...');
readkey;
end;
until DelVal<MaxE;
for i:=1 to DelVal do
begin
m:=top^.inf;
k:=top;
Top:=Top^.Link;
Dispose(k);
end;
end;
end;


begin
clrscr;
NewStek(top);
BStek(top);
DelFStek(top);
StekView(top);
writeln('Vvedite element dlya dobavleniaya');
readln(el);
InputStek(top,el);
StekView(top);
StekDel(top);
StekView(top);
readkey;
end.


вот..первый опыт

Автор: volvo 16.03.2007 4:41

По всей строгости, говоришь? Ну, ты сам просил...

1. Функция StekOver ... Во-первых, я не совсем понимаю причин, по которым надо как-то ограничивать стек ... Тогда уже используй массив. Для стека как раз характерно, что он может динамически изменять размер, и не надо его ничем ограничивать... Единственный случай, который требует внимания (и это как раз и есть переполнение стека) - это когда у тебя не хватает памяти для того, чтобы занести следующих элемент в стек. Но это ловится не в этой функции, а при добавлении...

Но... Ладно. Хорошо. Ты решил стек ограничить. В конце концов почему бы и нет - ты автор программы, тебе лучше знать, что нужно... smile.gif Однако, все равно - ты при определении "переполненности" должен пройтись по всему списку, а он может быть немаленьким, что совсем не нужно делать... Достаточно разделить понятия Stack и Item (то, что у тебя описано как Stack - на самом деле - элемент стека), то есть, что-то типа:

type
StekType=integer;
PItem = ^TItem;
TItem = record
inf: StekType;
link: PItem;
end;

TStack = record
first: PItem; { <--- Указатель собственно на вершину стека }
count: integer; { <--- счетчик элементов в стеке }
end;

, и производить при добавлении в стек увеличение поля count, а при удалении элемента - его уменьшение, и тебе достаточно будет вместо прохода в чикле, и подсчета числа элементов просто сравнить Count с нужным значением...

2. Что еще очень сильно бросается в глаза... Дело, конечно опять же твое, но... Есть ДСД (динамическая структура данных) - Стек, над которой возможны следующие операции: Push (добавление элемента), Pop (извлечение элемента), Empty (проверка на пустоту стека)... То, что ты называешь эти операции другими именами - это не очень хорошо по крайней мере по 2-м причинам:
а) это сейчас тебе все понятно (я надеюсь), что делает та или иная процедура, а что будет через месяц? Сможешь с первого взгляда на ЭТУ ЖЕ программу рассказать, что какая процедура делает?
б) если ты попробуешь задать вопрос на форуме (ну, или, скажем по-другому, если в твоей программе должен будет разобраться другой человек) - я не думаю, что ты получишь ответ быстро... Потому что надо заставить себя понять, что означает каждая из этих вот процедур, и какую за какой следует вызывать, и что можно, а что нельзя делать со стеком...

Автор: мисс_граффити 16.03.2007 4:54

почти не оффтоп... раз попросил указать на ошибки.
покритИкуйте ;)

и еще. опять же, не по сути вопроса: форматирование программы. не очень удобно читать, когда такие большие отступы. Как-то привычнее около 2-х пробелов (для Паскаля), а у тебя их не просто много, а по-разному много.