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

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

Форум «Всё о Паскале» _ Задачи _ Задача на тему СПИСКи

Автор: punkska 6.09.2005 0:28

вот наступила оень пора закрывать сессию!=)



вот смотрю я на свою прогу и не могу понять зачем я в ней счётчик сделал?
без него вроде не работает .. а что он делает я не поёму (забыл за лето)
может опытный глаз профи увидит недочёты

program laba_4_a;
uses crt;
type
link=^komanda;
komanda=record
name:string[20];
shayb:integer;
peredach:integer;
stime:integer;
nkom:string[10];
score:integer;
next:link;
end;
fkom=file of komanda;

var
f:fkom;
xxx,k,z,n,i:integer;
s,newrec:link;
p:pointer;
beg:link;

min_score:integer;

begin
xxx:=0;
repeat;clrscr;
writeln(' ....laba....');
gotoxy (1,10);
writeln ('1. VvoD DaHHbIX..........');
writeln ('2. View DaHHbIX..........');
writeln ('3. SaVe DaHHbIE..........');
writeln ('4. Load DaHHbIE..........');
writeln ('5. Delete................');
writeln ('9. BEST PLAYERS..........');

writeln (' ');
writeln ('0. E-X-I-T');
writeln ('Press 1-4:');
readln (z);
case z of
1:
begin
xxx:=xxx+1;
clrscr;
writeln ('BBeDuTe Kol-vo igrokov:');
readln (n);
mark(p);
beg:=nil;
for i:=1 to n do begin
new(s);
write ('N',i);
write (' Name of player:'); readln (s^.name);
write (' Kol-vo shayb:'); readln (s^.shayb);
write (' Kol-vo peregach:'); readln (s^.peredach);
write (' Shtraf.time:'); readln (s^.stime);
s^.score:=s^.shayb+s^.peredach;
s^.next:=beg;
beg:=s;
end;
end;
2:
begin
clrscr;
s:=beg;
writeln('Name of player Kol-vo shayb Kol-vo peredach Shraf.Time');
repeat
writeln(s^.name,' ',s^.shayb,' ',s^.peredach,' ',s^.stime);
s:=s^.next;
until s=nil;
readln;
end;
3:
begin
assign (f,'file.dat');
rewrite(f);
s:=beg;
repeat
write (f,s^);
s:=s^.next
until s=nil;
release(p);
end;

4:
begin
if xxx>0 then release(p);
assign (f,'file.dat');
reset(f);
mark(p);
s:=beg;
for i:=1 to filesize (f) do
begin new (s);
read(f,s^);
s^.next:=beg;
beg:=s;
end;
close (f);
{s:=beg;}
end;


9:
begin
clrscr;
writeln ('Enter min. Score');
readln (min_score);
s:=beg;
writeln('Name of player Kol-vo shayb Kol-vo peredach Shraf.Time');
repeat
if (min_score<=s^.score) then
writeln(s^.name,' ',s^.shayb,' ',s^.peredach,' ',s^.stime);
s:=s^.next;
until s=nil;
readln;
end;

5:
begin
writeln ('Enter Number...');
readln (n);
if n=1 then
begin newrec:=beg;
beg:=beg^.next;
end
else begin
s:=beg;
for i:=1 to n-2 do s:=s^.next;
newrec:=s^.next;
s^.next:=newrec^.next;
end;
dispose(newrec);
end;

end;
until z=0;
end.

Автор: punkska 6.09.2005 0:36

ой блин осенило!!! он нужен чтоб нельзя была зайти в просмотр таблицы без еёё введения! сори за беспокойство!!
может есть недочёты в проге?

Автор: volvo 6.09.2005 1:41

Цитата(punkska @ 5.09.05 20:36)
может есть недочёты в проге?

У тебя очень нехорошо организавано выделение/освобождение памяти. С Mark/Release очень просто получить утечки памяти: представь себе, например, что пользователь вошел в программу, нажал "1", ввел данные, нажал "2", просмотрел их, и вышел (по нажатию на "0"). Результат? Утечка памяти.

Выходов может быть 2:
1) Mark - в самом начале программы, Release - в самом конце, так ты гарантированно вернешься к первоначальному состоянию кучи
2) Отказаться от Mark/Release, и пользоваться только New/Dispose, это более сложный (может потребоваться реорганизация структуры программы), но и более надежный путь.

Хотя по большому счету это вроде бы не имеет значения (все равно программа закрывается, и вся память освобождается), но лучше привыкать сразу писАть программы правильно, это сэкономит в дальнейшем очень много времени и нервов...

Автор: punkska 21.09.2005 23:25

Цитата
1) Mark - в самом начале программы, Release - в самом конце, так ты гарантированно вернешься к первоначальному состоянию кучи


не получаеться!!! =(((

Автор: volvo 22.09.2005 0:03

Что именно "не получается"?
Я имел в виду вот так:

Var
p_start: Pointer;
begin
WriteLn('Доступно памяти: ', MemAvail);
mark(p_start); { запомнил первоначальное состояние }
xxx:=0;
repeat; clrscr;
...
case z of
1 ...
end;
until z=0;
release(p_start); { вернулся к первоначальному состоянию }
WriteLn('Доступно памяти: ', MemAvail);
end.

Автор: punkska 23.09.2005 21:37

я правильно понял твою мысль?
так?

Код
program laba_4_a;
uses crt;
type
   link=^komanda;
   komanda=record
                 name:string[20];
                 shayb:integer;
                 peredach:integer;
                 stime:integer;
                 nkom:string[10];
                 score:integer;
                 next:link;
                 end;
   fkom=file of komanda;

   var
   f:fkom;
   xxx,k,z,n,i:integer;
   s,newrec:link;
 p_start,  p:pointer;
   beg:link;

   min_score:integer;

begin
mark(p_start);
xxx:=0;
repeat;clrscr;
writeln('                          vvv....');
gotoxy (1,10);
writeln ('1. VvoD DaHHbIX..........');
writeln ('2. View DaHHbIX..........');
writeln ('3. SaVe DaHHbIE..........');
writeln ('4. Load DaHHbIE..........');
writeln ('5. Delete................');
writeln ('9. BEST PLAYERS..........');

writeln (' ');
writeln ('0. E-X-I-T');
writeln ('Press 1-4:');
readln (z);
case z of
1:
begin
   xxx:=xxx+1;
   clrscr;
   writeln ('BBeDuTe Kol-vo igrokov:');
readln (n);
mark(p);
   beg:=nil;
  for i:=1 to n do begin
   new(s);
   write ('N',i);
   write (' Name of player:'); readln (s^.name);
   write (' Kol-vo shayb:'); readln (s^.shayb);
   write (' Kol-vo peregach:'); readln (s^.peredach);
   write (' Shtraf.time:'); readln (s^.stime);
   s^.score:=s^.shayb+s^.peredach;
   s^.next:=beg;
   beg:=s;
   end;
end;
2:
begin
clrscr;
s:=beg;
writeln('Name of player      Kol-vo shayb     Kol-vo peredach       Shraf.Time');
repeat
writeln(s^.name,'              ',s^.shayb,'                 ',s^.peredach,'                      ',s^.stime);
s:=s^.next;
until s=nil;
readln;
end;
3:
begin
assign (f,'file.dat');
rewrite(f);
s:=beg;
repeat
write (f,s^);
s:=s^.next
until s=nil;
release(p);
end;

4:
begin
if xxx>0 then release(p);
assign (f,'file.dat');
reset(f);
mark(p);
s:=beg;
for i:=1 to filesize (f) do
begin new (s);
read(f,s^);
   s^.next:=beg;
   beg:=s;
end;
close (f);
{s:=beg;}
end;


9:
begin
clrscr;
writeln ('Enter min. Score');
readln (min_score);
s:=beg;
writeln('Name of player      Kol-vo shayb     Kol-vo peredach       Shraf.Time');
repeat
if (min_score<=s^.score) then
writeln(s^.name,'              ',s^.shayb,'                 ',s^.peredach,'                      ',s^.stime);
s:=s^.next;
until s=nil;
readln;
end;

5:
begin
writeln ('Enter Number...');
readln (n);
if n=1 then
begin newrec:=beg;
beg:=beg^.next;
end
else begin
s:=beg;
for i:=1 to n-2 do s:=s^.next;
newrec:=s^.next;
s^.next:=newrec^.next;
end;
dispose(newrec);
end;

end;
until z=0; release(p_start);
end.


у меня он постоянно ругаеться ... если выполнять пункты в след порядке 1, 2 , 3 ,5
или 1,2,3,4,5,2
помогите

Автор: volvo 23.09.2005 21:44

Да объясни ты наконец, что значит "ругается"? Что, не работает, или сбоит, или вообще не запускается? Я ж не телепат...

Автор: punkska 23.09.2005 22:00

"ругается" - вылетает.
может что-то не так с выделением памити и её отчисткой?

Автор: volvo 23.09.2005 22:25

На самом деле это и должно происходить, потому что при выполнении "Сохранить" ты делаешь Release(P), а потом, например при "Удалить", хочешь освободить уже несуществующий указатель. Это - ошибка работы с памятью. Если тебе достаточно "залатать дыры", и заставить быстро программу работать - просто закомментируй описание

p: Pointer;
и все вызовы Mark(P)/Release(P) ... Все равно перед выходом Release(p_start) вернет всю память системе.

Если же ты хочешь написать программу, ПРАВИЛЬНО работающую с памятью, то придется ее переписывать (в частность - добавление/удаление элементов в список). Лучше всего - с нуля, и при этом делать это не одним куском программы, а используя процедуры и функции. Структура программы станет более ясной, и будет гораздо легче организовать правильную работу со списком, а значит и с памятью в целом.

P.S. Вообще Mark/Release - очень нехорошее решение. Вот, например в FPC эти процедуры вообще не включены... Делай выводы...

Автор: punkska 23.09.2005 22:46

Спасибо! попрбую перелопатить...
блин...
значит мне надо идти по этому пути 2) Отказаться от Mark/Release, и пользоваться только New/Dispose, это более сложный (может потребоваться реорганизация структуры программы), но и более надежный путь.

попрую с нуля написать...
а на форуме есть примеры прог похлжих на мою?
если есть подскажите где! спс!

Автор: punkska 24.09.2005 1:20

program list;
uses CRT;
Type
SS=^Obj;
Obj=recoed
name:string[20];
shayb:integer;
peredach:integer;
stime:integer;
nkom:string[10];
score:integer;
next:SS;
end;

Var

Procedure Create (var Beg: SS );
Var P:SS;
Begin
Beg:=Nil;
Repeat
New (P);
writeln ('BBeDuTe Kol-vo igrokov:');
readln (n);
for i:=1 to n do begin
new(s);
write ('N',i);
write (' Name of player:'); readln (p^.name);
write (' Kol-vo shayb:'); readln (p^.shayb);
write (' Kol-vo peregach:'); readln (p^.peredach);
write (' Shtraf.time:'); readln (p^.stime);
p^.score:=p^.shayb+p^.peredach;
p^.next:=beg;
beg:=p;
end;
end;



так правильно использовать new???
хелп !! пдскажите советом! горит!!! ща всю прогу долопачу !
хоть начало правильно! нпа правильном пути???

Автор: volvo 24.09.2005 1:45

:no: Попробуй разобраться:


Прикрепленные файлы
Прикрепленный файл  GOOD.PAS ( 4.02 килобайт ) Кол-во скачиваний: 263

Автор: punkska 24.09.2005 1:59

blink.gif blink.gif
спасибо :molitva: :flowers:

я конечно в шоке... вся ночь уйдёт на понимание ....


я наверно ещё свой набросок минут через 5ть покажу

Автор: punkska 24.09.2005 2:02

program list;
uses CRT;
Type
SS=^Obj;
Obj=record
name:string[20];
shayb:integer;
peredach:integer;
stime:integer;
nkom:string[10];
score:integer;
next:SS;
end;

Var
PBeg :pointer;
N,i :integer;



Procedure Create (var Beg: pointer );
Var P :SS;
tmp :SS;
Begin
if (beg=nil) then begin
new(P);
beg:=P;
end else begin
tmp:=beg;
while tmp^.next<>nil do tmp:=tmp^.next;
new(p);
tmp^.next:=p;
end;
write (' Name of player:'); readln (p^.name);
write (' Kol-vo shayb:'); readln (p^.shayb);
write (' Kol-vo peregach:'); readln (p^.peredach);
write (' Shtraf.time:'); readln (p^.stime);
p^.next:=nil;
p^.score:=p^.shayb+p^.peredach;
end;

Procedure View (beg:pointer);
Var P:SS;
Begin
P:=Beg;

writeln('Name of player Kol-vo shayb Kol-vo peredach Shraf.Time');
repeat
writeln(p^.name,' ',p^.shayb,' ',p^.peredach,' ',p^.stime);
p:=p^.next;
until p=nil;
readln;
end;

BEGIN
PBeg := nil;
clrscr;
write('Please enter the number players: ');
ReadLn(n);
for i:=1 to n do begin
Writeln;
WriteLn('Enter info about player n. ',i);
Create(PBeg);
end;
ReadLn;
clrscr;
View(PBeg);



END.





=))) что скажет суровый профи?

Автор: volvo 24.09.2005 3:34

Уже лучше, чем было, но все равно есть еще много над чем работать. Например, возьмем структуру Obj... Ты прямо в этой структуре хранишь указатель на следующий элемент (next), так? А зачем? Если ты запишешь эту структуру в файл, а потом прочитаешь, то прочитаешь ты элементы в другие адреса памяти, т.е. для сохранения работоспособности придется в поле next заново заносить правильную информацию, т.е. производятся лишние действия. Кроме того, размер файла тоже увеличивается (всего на 2 байта для каждого элемента списка, но все-таки, этого тоже можно избежать)...

Далее... При добавлении всех возможностей программы ты обязательно столкнешься с тем, что вот этот кусок будет дублироваться почти в каждой процедуре:

  P:=Beg;
...
repeat
{ Произвести какое-то действие с каждым элементом списка }
p:=p^.next;
until p = nil;
Этого можно избежать (посмотри, как я это сделал). Кстати, с таким кодом ты элементарно можешь получить Run-Time Error: например, если в момент вызова View список еще не сформирован, и следовательно Beg = nil, что приведет к попытке перехода по нулевому указателю, а это Ошибка !!! Вот так будет гораздо правильнее:
P:=Beg;
...
While p <> nil Do Begin
{ Произвести какое-то действие с каждым элементом списка }
p:=p^.next;
End;
Теперь если Beg = nil, то ты вообще не войдешь в цикл, как и должно быть...

rolleyes.gif

Автор: punkska 24.09.2005 11:56

репит на вайл поменял=) спасибо! :molitva: :molitva: :molitva:

а вот с нехт не догнал...