Помощь - Поиск - Пользователи - Календарь
Полная версия: Проблема с прогой на линейные списки.
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
TheKnyazz
Здравствуйте!Я очень внимательно прочитал ваш достаточно качественный ЧаВо по файлам и динамическим спискам, но тут проблема, я не знаю куда прилепить процедуру закрытия файла, чтоб в моем ткст файле сохранялись мои записи в таблицу, и при следующем запуске программы, я мог загрузить из файла значения, и продолжить работу со старыми данными. Так же небольшая проблема с пониманием такой строки моего задания "создать процедуру, которая вставляет в список L новый элемет Е1, за каждым вхождением элемента Е"
Я просто не понимаю, что это значит. У нас была только 1 лекция по этой теме, но это нам не обьясняли, а на следующее практическое задание тянуть готовую лабу. Обьясните пожалуйста, что оно такое.

Вот мой исходник.

Program lab9;
Uses Crt;
Type
Data= Record
num:byte;
FIO:string[15];
year: integer;
sex: char;
stat: string[11];
child: byte;
salary: integer;
End;
Ukaz=^Query;
Query=Record
Inf:Data;
Next:Ukaz
End;
Var
NewE,Left,Right,Temp:Ukaz;
Z:Data;
Key:byte;
f:text;

Procedure Org;
var i: integer;
Begin
clrscr;
reset (f);
Writeln('vypolnyaetsya procedura organizacii ocheredi');
write ('zagruzka dannyh iz faila');
for i:= 1 to 7 do
begin
delay (300);
write ('.')
end;
writeln;
writeln ('zagruzka zavershena');
readln;
Writeln('======================================== ');
with z do
Readln(f,num,Fio,year,stat,sex,child,salary);
New(NewE);
NewE^.Inf.num:=Z.num;
NewE^.Inf.Fio:=Z.Fio;
NewE^.Inf.year:=Z.year;
NewE^.Inf.stat:=Z.stat;
NewE^.Inf.sex:=Z.sex;
NewE^.Inf.child:=Z.child;
NewE^.Inf.salary:=Z.salary;
NewE^.Next:=nil;
Right:=NewE;
Left:=NewE;
While not eof(f) Do
Begin
with z do
Readln(f,num,Fio,year,stat,sex,child,salary);
New(NewE);
NewE^.Inf.num:=Z.num;
NewE^.Inf.Fio:=Z.Fio;
NewE^.Inf.year:=Z.year;
NewE^.Inf.stat:=Z.stat;
NewE^.Inf.sex:=Z.sex;
NewE^.Inf.child:=Z.child;
NewE^.Inf.salary:=Z.salary;
NewE^.Next:=Nil;
Right^.Next:=NewE;
Right:=NewE
End
End;
Procedure Dob;
Begin
Writeln('vvedite №');
Readln(Z.num);
Writeln('vvedite familiyu');
Readln(Z.Fio);
If Z.Fio='*' Then Exit;
Writeln('vvedite god rojdeniya');
Readln(Z.year);
Writeln('vvedite pol');
Readln(Z.sex);
writeln ('vvedite status');
readln (z.stat);
Writeln('vvedite kolichestvo detei');
Readln(Z.child);
Writeln('vvedite zarplatu');
Readln(Z.salary);
New(NewE);
NewE^.Inf.num:=Z.num;
NewE^.Inf.Fio:=Z.Fio;
NewE^.Inf.year:=Z.year;
NewE^.Inf.stat:=Z.stat;
NewE^.Inf.sex:=Z.sex;
NewE^.Inf.child:=Z.child;
NewE^.Inf.salary:=Z.salary;
NewE^.Next:=nil;
If Right=Nil Then
Left:=NewE
Else
Right^.Next:=NewE;
Right:=NewE;
End;

Procedure Udal;
Begin
Writeln('isklyuchaetsya golovnoi element ocheredi');
Writeln('press Enter');
Readln;
If Left<>Nil Then
Begin
Temp:=Left;
Left:=Left^.Next;
Dispose(Temp);
If Left=Nil Then
Right:=Nil;
End
End;

Procedure Prosmotr;
Var i:integer;
Begin
if left=nil then
begin
writeln ('spisok pustoi');
readln;
clrscr;
exit
end
else
Writeln('ochered soderjit sleduyuschie elementy');
Temp:=Left;
While Temp<>nil Do
Begin
Writeln(Temp^.Inf.num,' ',Temp^.Inf.Fio,' ',Temp^.Inf.year,' ',Temp^.Inf.sex,' ',
Temp^.Inf.stat,' ',Temp^.Inf.child,' ',Temp^.Inf.salary);
Temp:=Temp^.Next;
End;
Writeln('press Enter');
Readln;
clrscr;
End;

procedure my_var;
Begin
End;

begin
assign (f,'d:\lab9.txt');
{$I-};
reset(f);
{$I+};
if IOResult=0 then
writeln ('file opened successfully')
else
begin
writeln ('no input file');
readln;
exit;
end;
Right:=Nil;
Left:=Nil;
ClrScr;
while true do
begin
Writeln('1-organizaciya spiska');
Writeln('2-dobavlenie elementa');
Writeln('3-udalenie elementa');
Writeln('4-prosmotr spiska');
writeln('5-moe zadanie');
Writeln('6-vyhod');
Writeln('-------------------------------');
readln(key);
Case Key Of
1 : Org;
2 : Dob;
3 : Udal;
4 : Prosmotr;
5 : my_var;
6 : EXIT;
End;
end;
End.




Основные ф-ции работают вроде, а вот чтоб сохранять данные, не получается.
volvo
Цитата
чтоб сохранять данные, не получается.
Перед тем, как выйти из программы (при выборе 6-го пункта), переоткрой файл F на запись, пробеги по списку, и сохрани его содержимое в файл.

Цитата
"создать процедуру, которая вставляет в список L новый элемет Е1, за каждым вхождением элемента Е"
Я просто не понимаю, что это значит.
Допустим, у тебя был список:
L = <1, 2, 3, 1, 5, 6, 7, 8, 1>
, и E = 1, E1 = 10... Твоя задача - пройти по списку, найти все элементы, равные значению E, то есть, единице, и после каждого такого элемента вставить значение E1. В результате, список должен выглядеть так:
L = <1, 10, 2, 3, 1, 10, 5, 6, 7, 8, 1, 10>
TheKnyazz
Что-то я зашел в тупик.
Из ваших слов
procedure Escape;
begin
reset(f);
while
Temp<>nil do
begin
Temp:=Temp^.next;
End;
writeln('press enter');
readln;
clrscr;
close(f);
exit;
end;

Эту штуку я должен использовать в 6 пункте. Но почему-то толку ни какого.
Или я что-то не правильно понял?
volvo
Цитата
Из ваших слов
Не-а... Я сказал:
Цитата(Self)
(при выборе 6-го пункта), переоткрой файл F на запись
, это делается Rewrite-ом... И записать содержимое списка в файл, а не просто пронестись по нему вхолостую:

procedure Escape;
begin
rewrite(f);
while Temp<>nil do begin
with Temp^.Inf do
writeln(f, num:4, Fio:16, year:6, stat:12, sex:2, child:4, salary:6);
Temp:=Temp^.next;
end;
writeln('press enter'); readln;
close(f);
clrscr;
end;
Я надеюсь, ты сохранил где-то указатель на начало списка, иначе ты потеряешь его, и будет у тебя утечка памяти, этого делать не стОит...
TheKnyazz
Цитата(volvo @ 1.02.2009 19:31) *

Я надеюсь, ты сохранил где-то указатель на начало списка, иначе ты потеряешь его, и будет у тебя утечка памяти, этого делать не стОит...

с этого места поподробнее пожалуйста, моск почему-то слабо осознает. Мне ввести еще одну ссылочную переменную специально для того, чтобы сохранить в ней первый элемент? теоретически грамотный пользователь будет заполнять мою таблицу начиная с 1 элемента.(я имею ввиду, то что спрашивается при добавлении элементов, какой номер.) Нельзя ли это как-то использовать? Или имеется ввиду указатель типа конец файла\конец строки?
А так же, каким образом еще и закрыть основную программу?
Когда я дописываю exit после clrscr В процедуре escape, почему-то меня не хочет выкидывать из программы.
volvo
Цитата
Мне ввести еще одну ссылочную переменную специально для того, чтобы сохранить в ней первый элемент?
Не вот у тебя когда происходит просмотр списка, ты делаешь так:
  Writeln('ochered soderjit sleduyuschie elementy');
Temp:=Left;
While Temp<>nil Do ...
, то есть, Temp у тебя - именно дополнительная переменная, которая используется только для того, чтобы пробежать по списку, основная же переменная (Left) не изменяется... Здесь (при сохранении списка) почему-то Left-а и в помине нет (а вдруг я выберу "выход" сразу же после просмотра списка, когда Temp = nil? Опять ничего не сохранится). Сделай и здесь то же самое: сначала Temp := Left, а потом - все остальное...

+ к этому, я ж сказал, что еще надо сделать: надо список не только сохранить, но и память, им занимаемую, освободить. Не привыкай делать "чтобы как-то отработало", если память выделялась (а она выделялась, в частности - в процедуре Org, при создании списка) - она должна быть удалена. На каждый New должен быть свой Dispose.

Цитата
Когда я дописываю exit после clrscr В процедуре escape, почему-то меня не хочет выкидывать из программы.
А что, должно? Exit завершает текущую процедуру, а не программу вообще-то... Добавь этот самый Exit не внутрь Escape, а
Case Key Of
1 : Org;
2 : Dob;
3 : Udal;
4 : Prosmotr;
5 : my_var;
6 :
begin
Escape;
Exit; { <--- Вот сюда }
end;
End;
, собственно, он там и был, чего ты убрал его оттуда - непонятно...
TheKnyazz
Вас понял, из-за таких "гениев" как я происходит переполнение памяти, и многочасовой труд например в ранних версиях ворда уходит на смарку).
Огромное вам спасибо за помощь! Все поправил, все работает.
Со своим заданием с элементом е1 постараюсь разобраться сам, надо же почувстовать себя программистом lol.gif lol.gif
Alma
Я конечно прошу прощения. Но у меня аналогичная проблема с программой. Список не сохраняется в файл и при повторном открытии таблица пустая. Я попыталась сделать так, как Вы советовали, но ничего не получается. Не могли бы вы мне подсказать в чем ошибка, а то было уже перепробовано много вариантов и все равно не сохраняется. Спасибо заранее

program lab9;
uses Crt;
type
data =record
nomer:integer;
F,I,O:string[15];
Ocenki:record
math,history,physyc:integer
end;end;
ukaz=^query;
query=record
inf:data;
next:ukaz
end;
spisok = file of data;

var

newE, Left, Right,Temp : ukaz;
Z:data;
key:integer;
tab: spisok;

procedure Escape;
begin
rewrite(tab);
Temp:=left;
while Temp<>nil do begin
with Temp^.Inf do
writeln ( F:10,' ', I:10,' ', O:10,' ',ocenki.math:4,' ',ocenki.history:4,' ',ocenki.physyc:4);
Temp:=Temp^.next;
end;
writeln('press enter'); readln;
close(tab);
clrscr;
end;

procedure Org;
begin
Writeln('procedura organizacii o4eredi');




writeln('dlay vihoda *');
writeln('=========================================');
writeln('vvedite Familiu');
readln(z.F);

if z.F='*' then exit;
writeln('imay');
readln(z.I);
writeln('ot4estvo');
readln(z.O);
writeln('vvedite ocenki');
with z.ocenki do
readln(math,history,physyc);

New(newE);
NewE^.inf.F:=z.F;
NewE^.inf.I:=z.I;
NewE^.inf.O:=z.O;
NewE^.inf.ocenki.math:=z.ocenki.math;
NewE^.inf.ocenki.history:=z.ocenki.history;
NewE^.inf.ocenki.physyc:=z.ocenki.physyc;

newE^.Next:=nil;
right:=newE;
left:=newE;
while true do
begin

writeln('dlay vihoda *');
writeln('=========================================');
writeln('vvedite Familiu');
readln(z.F);
if z.F='*' then exit;
writeln('imay');
readln(z.I);
writeln('ot4estvo');
readln(z.O);
writeln('vvedite ocenki');
with z.ocenki do
readln(math,history,physyc);

New(newE);
NewE^.inf.F:=z.F;
NewE^.inf.I:=z.I;
NewE^.inf.O:=z.O;
NewE^.inf.ocenki.math:=z.ocenki.math;
NewE^.inf.ocenki.history:=z.ocenki.history;
NewE^.inf.ocenki.physyc:=z.ocenki.physyc;

newE^.Next:=nil;
right^.next:=newE;
right:=newE;
end;
end;

procedure Dob;
begin
writeln('dlay vihoda *');
writeln('=========================================');
writeln('vvedite Familiu');
readln(z.F);
if z.F='*' then exit;
writeln('imay');
readln(z.I);
writeln('ot4estvo');
readln(z.O);
writeln('vvedite ocenki');
with z.ocenki do
readln(math,history,physyc);

New(newE);
NewE^.inf.F:=z.F;
NewE^.inf.I:=z.I;
NewE^.inf.O:=z.O;
NewE^.inf.ocenki.math:=z.ocenki.math;
NewE^.inf.ocenki.history:=z.ocenki.history;
NewE^.inf.ocenki.physyc:=z.ocenki.physyc;
newE^.Next:=nil;
if right=nil then
Left:=NewE
else right^.NExt:=newE;
right:=NewE;
end;

procedure Udal;
begin
writeln('udalenie 1 elementa');
writeln('najmite enter');
readln;
if left<>nil then
begin
Temp:=Left;
Left:=Left^.Next;
Dispose(Temp);
if Left=nil then
Right:=nil;
end;
end;


procedure prosmotr;
var i: integer;
begin

writeln ('elementi o4eredi');
writeln;

temp:=left;

writeln('last_name ', ' ', 'first_name ',' ', 'ot4estvo ', 'math ','history ','physyc');
writeln(' ____________________________________________________________________________ ');
while Temp<>nil do
begin

with Temp^.inf do
writeln ( F:10,' ', I:10,' ', O:10,' ',ocenki.math:4,' ',ocenki.history:4,' ',ocenki.physyc:4);
Temp:=Temp^.Next;

end;
writeln;
writeln(' najmite enter');
readln;
end;

{======================================================================}

begin
assign(tab,'D:\spisok.txt');{$I-}
reset(tab);{$I+}
if IOresult <> 0 then
rewrite(tab);
readln;
right:=nil;
left:=nil;
repeat
ClrScr;
writeln('1 - cozdanie');
writeln('2 - dobavlenie');
writeln('3 - udalenie');
writeln('4 - prosmotr');
writeln('5 - sohranenie');
writeln('6 - vihod');
writeln('______________________');
writeln( 'vvedite punkt menu');
readln(key);
case key of
1:org;
2:dob;
3:udal;
4:prosmotr;
5: escape;
end
until key=6;
end.
volvo
Цитата
Я попыталась сделать так, как Вы советовали, но ничего не получается.
Я советовал записывать в файл, а не выводить на экран:
procedure Escape;
begin
rewrite(tab);
Temp:=left;
while Temp<>nil do begin
with Temp^.Inf do
writeln (tab, F:10,' ', I:10,' ', O:10,' ',ocenki.math:4,' ',
ocenki.history:4,' ',ocenki.physyc:4);
Temp:=Temp^.next;
end;
writeln('press enter'); readln;
close(tab);
clrscr;
end;

Разница заметна?
Гость
Разница заметна, спасибо, сама не увидела:)
Единственное, на строке writeln() теперь выдает ошибку Invalid file type
volvo
Потому что в исходной программе работа была с текстовым файлом, а ты пытаешься работать с типизированным... Для типизированных все еще проще:
  while Temp<>nil do begin
write(tab, Temp^.Inf);
Temp:=Temp^.next;
end;
сохранит данные в файл, главное потом правильно их прочесть... Или поменяй тип файла на текстовый, и делай, как я написал в предыдущем посте...
Гость
Цитата(volvo @ 2.02.2009 22:30) *

сохранит данные в файл, главное потом правильно их прочесть...


Не получается правильно прочесть. Если пишу еще одну процедуру просто для чтения типизированного файла, паскаль завершает работу.
Если меняею процедуру prosmotr все рачно ничего не выводиться при повторном запуске
procedure prosmotr;
var i: integer;
begin
reset(tab);
seek(tab,0);

writeln ('elementi o4eredi');
writeln;
volvo
Цитата
Если пишу еще одну процедуру просто для чтения типизированного файла, паскаль завершает работу.
А если написать эту процедуру правильно? Вот так, например:

Procedure ReadFile;
var
p: ukaz;
R: data;
begin
left := nil; right := nil;
reset(tab);
while not eof(tab) do begin

read(tab, R);
new(p);
p^.data := R;

if left = nil then left := p
else right^.next := p;
right := p;

end;
close(tab);
end;
Гость
Спасибо огромное. Вы очень мне помогли
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.