Помощь - Поиск - Пользователи - Календарь
Полная версия: Задача на тему СПИСКи
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
punkska
вот наступила оень пора закрывать сессию!=)



вот смотрю я на свою прогу и не могу понять зачем я в ней счётчик сделал?
без него вроде не работает .. а что он делает я не поёму (забыл за лето)
может опытный глаз профи увидит недочёты
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
ой блин осенило!!! он нужен чтоб нельзя была зайти в просмотр таблицы без еёё введения! сори за беспокойство!!
может есть недочёты в проге?
volvo
Цитата(punkska @ 5.09.05 20:36)
может есть недочёты в проге?

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

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

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


не получаеться!!! =(((
volvo
Что именно "не получается"?
Я имел в виду вот так:
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
я правильно понял твою мысль?
так?
Код
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
Да объясни ты наконец, что значит "ругается"? Что, не работает, или сбоит, или вообще не запускается? Я ж не телепат...
punkska
"ругается" - вылетает.
может что-то не так с выделением памити и её отчисткой?
volvo
На самом деле это и должно происходить, потому что при выполнении "Сохранить" ты делаешь Release(P), а потом, например при "Удалить", хочешь освободить уже несуществующий указатель. Это - ошибка работы с памятью. Если тебе достаточно "залатать дыры", и заставить быстро программу работать - просто закомментируй описание
p: Pointer;
и все вызовы Mark(P)/Release(P) ... Все равно перед выходом Release(p_start) вернет всю память системе.

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

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

попрую с нуля написать...
а на форуме есть примеры прог похлжих на мою?
если есть подскажите где! спс!
punkska
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
:no: Попробуй разобраться:
punkska
blink.gif blink.gif
спасибо :molitva: :flowers:

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


я наверно ещё свой набросок минут через 5ть покажу
punkska
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
Уже лучше, чем было, но все равно есть еще много над чем работать. Например, возьмем структуру 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
репит на вайл поменял=) спасибо! :molitva: :molitva: :molitva:

а вот с нехт не догнал...
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.