Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Object Pascal: кроссплатформенные технологии > Pascal


Автор: Mager2005 9.5.2005, 22:30
Народ! Help, как говориться. Растолкуйте бестолковым начинающим, принцип работы динамической памяти и указателей. У меня тут задачка по базе данных. не могу разобраться что к чему.
Отрывок:

Код
type lib=record
     fio:string[50];
     marka:string[20];
     nomer :string[30];
     color :string;
         end;
type pitem=^item;
 item=record
 data:lib;
 next:pitem;
 end;
Var head,p,p1:pitem;
    w,n,k,q:integer;
    l:lib;
    h,c:char;
    f:file of lib;
    s:string[8];
  v, d:string;
   a:MasMenu;
   sim:Byte;
   j,i:Longint;
===========================
i:=0;
    while not(eof(f)) do begin
    inc(i);
    read(f,l);
    if q<>0 then begin for i:=1 to q do begin { and (i<=n) and (head<>nil) then }
        if i=1 then begin
        p:=head^.next;
        dispose(head);
        head:=p;    end
                    else begin
                         p:=head;
                         for k:=2 to i-1 do p:=p^.next;
                         p1:=p^.next;
                         p^.next:=p1^.next;
                         dispose(p1);
                         end;
     n:=n-1;            end;end;

    add(l,i);


PS пл по-подробнее растолкуйте smile


Автор: SPrograMMer 9.5.2005, 23:16
http://vingrad.ru/DELPHI-FAQ-002487чутка про очереди - структуры данных, которые тебе надо реализовать.
А вообще я понял у тебя есть типизирвоанный файл, и тебе его надо в динмаческую память отправить?
Добавлено @ 23:21
Цитата(Mager2005 @ 9.5.2005, 22:30)
Код

p:=head^.next;
        dispose(head);
        head:=p;

.....этот кусок деляет вроде первый элемент... ну все верно....




Цитата(Mager2005 @ 9.5.2005, 22:30)
Код

p:=head;
                         for k:=2 to i-1 do p:=p^.next;
                         p1:=p^.next;
                         p^.next:=p1^.next;
                         dispose(p1);

...а этот вроде деляет предпоследний (или последний) элемет....
smile smile smile не соображу тогда чего тебе надо.......

Автор: Mager2005 10.5.2005, 00:17
Все очень просто мне нужно объяснить что тут к чему вот и все. А какой кусок какой элемент делает - эт и так ясно. Ты б лучше пояснил, как он это делает smile

Автор: Mager2005 10.5.2005, 03:23
Цитата
Тут чутка про очереди - структуры данных, которые тебе надо реализовать.

Спасибо, надо было сразу в FAQ посмотреть smile

Автор: SPrograMMer 10.5.2005, 09:47
Цитата(Mager2005 @ 10.5.2005, 00:17)
как он это делает

Цитата(Mager2005 @ 10.5.2005, 03:23)
Спасибо, надо было сразу в FAQ посмотреть

значит разобрался?....

Автор: Mager2005 10.5.2005, 23:31
И да и нет. Вроде понятен принцип. Вот только такая фишка получается. Программа при запуске выдает на строчке dispose (head) - Invalid pointer operation, а на строчке new(p) - Heap overflow error. Что ей не нравится - не могу понять smile

Автор: Fedor 11.5.2005, 06:55
Mager2005 выложи полностью код

Автор: SPrograMMer 11.5.2005, 11:42
Цитата(Mager2005 @ 10.5.2005, 23:31)
dispose (head) - Invalid pointer operation

Это значит, что у тебя head содержит что-то, что не nil - "пусой" указатель, но однако это место памяти НЕ БЫЛО ранее выделено подпрограммой new => там находится или "мусор" или статические данные, в общем потому что эта память ранее не выделалась.
Что бы этого не происходило, ВЕЗДЕ, где есть указатели, после освободения памяти им нужно всегда присваивать nil ЯВНО. Дабы не наткнуться на него же во второй раз smile



Цитата(Mager2005 @ 10.5.2005, 23:31)
на строчке new(p) - Heap overflow error

так назваемое переполнениеи "кучи", т. е области динамической памяти.
Если там не хватает места для выделения, то вызывается подпрограма, которая находится по адресу, которая хранится в переменной HeapError, хоть ты эту переменную не объявлял, она у тебя есть smile . "Решается" эта проблема обычно следующим образом: пишется своя подпрограммка по обработки состояния "нет_памяти"- HeapError, и заменяется стандарт, ну примерно так:
Код

Var
  SaveHeapError:Pointer;//для сохранения адреса стандартной подпрограммы
{$F+}    // надо!
Function NewHeapError(Size:Word):Integer;
Begin
  NewHeapError:=1   // как тока не будет хватать памяти ошибок не возбуждать, но вернуть
                                 // nil при попытке получить часть памяти
End;
{$F-}
Procedure GetAnyDynamicMemory;
  Var
      X:PRecord;
Begin
    HeapError:=@NewHeapError;  // заменяем стандарт
   X:=New(PRecord);  // попытаться выделить память
   If X=Nil Then  // если не получилось
      // чего-нить делать, например сообщить пользователю, что нет памяти
   Else Begin
      // продолжаем работать с переменной Х
      X^........
   End;
   H eapError:=SaveHeapError // возвращаем стандарт
End;
....
Begin
   SaveHeapError:=HeapError;  // Сохраняем стандартную функцию
   // работаем с памятью:
  GetAnyDynamicMemory;
  ......
End.


Нехватка памяти, как ты наверное понимаешь происходит из-за того. что твоя запись СИЛЬНО большая, и может быть превашает 64 К , а структуры данных сразу непосредственно, превышающие 64 К разместить в памяти нельзя => частями надо....

Автор: Mager2005 11.5.2005, 20:54
SPrograMMer: и как можно решить проблему с head и new. И вообще как разместить запись в памяти частями???

Fedor: значит код моей базы данных такой:

Код

uses crt;
type  
     base=record
      name:string;
      processor:string;
      interf:string;
      system_bus_clockrate:string;
      max_processor:string;
      memory_type:string;
      ATA:string;
      USB:string;
      AGP:string;
      end;
type  point=^part;
      part=record
      data:base;
      next:point;
      end;
const 
      n=6;x=30;y=10;number=9;
      normal=$17;
      selected=$60;
var
     head,p,p1:point;
     menu:array [1..number] of string;
     a:array [1..n] of string;
     i,item,q,l:byte;
     ch:char;
     f:file of base;
     path:string;
     x1,y1:word;
================
procedure file_new(var path:string); (определяем имя загружаемого файла)
var j:byte;nam:string;
begin
clrscr;
path:='';
gotoxy(x,y);
write('Input the name of a new file: ');
read(nam);
readln;
path:=nam;
end;

procedure printing(l:byte); (печатаем данные из файла)
var i,j:byte; x2,y2:word;
begin
p1:=head; i:=0;
repeat
     x2:=34+i*l+1; y2:=2;
     gotoxy(x2,y2); for j:=1 to l do write(' ');
     gotoxy(x2,y2); write (p1^.data.name);
     gotoxy(x2,y2+2); for j:=1 to l do write(' ');
     gotoxy(x2,y2+2); write (p1^.data.processor);
     gotoxy(x2,y2+4); for j:=1 to l do write(' ');
     gotoxy(x2,y2+4); write (p1^.data.interf);
     gotoxy(x2,y2+6); for j:=1 to l do write(' ');
     gotoxy(x2,y2+6); write (p1^.data.system_bus_clockrate);
     gotoxy(x2,y2+8); for j:=1 to l do write(' ');
     gotoxy(x2,y2+8); write (p1^.data.max_processor);
     gotoxy(x2,y2+10); for j:=1 to l do write(' ');
     gotoxy(x2,y2+10); write (p1^.data.memory_type);
     gotoxy(x2,y2+12); for j:=1 to l do write(' ');
     gotoxy(x2,y2+12); write (p1^.data.ATA);
     gotoxy(x2,y2+14); for j:=1 to l do write(' ');
     gotoxy(x2,y2+14); write (p1^.data.USB);
     gotoxy(x2,y2+14); for j:=1 to l do write(' ');
     gotoxy(x2,y2+14); write (p1^.data.AGP);
     p1:=p1^.next;
     inc(i);
until p1=nil;
end;

procedure loading(i:byte; chipset:base); (загружаем данные в оперативную память)
var j:byte;
begin
while i<=q do
     if i=1 then
     begin
     new(p);
     p^.data:=chipset;
     if i=1 then
     begin
     p^.next:=head;head:=p;
     end
     else begin
          p1:=head;
          for j:=2 to i-1 do p1:=p1^.next;
          p^.next:=p1^.next;
          p1^.next:=p;
      end;
      {new(p);
      p^.data:=chipset; writeln(p^.data.name); readkey;
      p^.next:=head;
      head:=p;
      {writeln(head^.data.name);
     end
     else
     begin
      p1:=head;
      for j:=1 to i-1 do p1:=p1^.next;
      p1^.next:=p;
      p:=p1;}
     end;
     readkey;
end;

procedure reading (x,y:word);(читаем данные из файла)
var name:string; i,j,k:byte;
begin
file_new(path);
assign(f,path);
{$I-}
reset(f);
{$I+}
if IOResult<>0 then begin gotoxy(x,y+1); write('File is not found.'); end
   else
   begin
   i:=0;
   while not eof(f) do
   begin
       inc(i);
       read(f,chipset); 
       if q<>0 then begin for i:=1 to q do begin { and (i<=n) and (head<>nil) then }
       if i=1 then begin
       p:=head^.next;
       dispose(head);
       head:=p;    
       end
                    else begin
                         p:=head;
                         for k:=2 to i-1 do p:=p^.next;
                         p1:=p^.next;
                         p^.next:=p1^.next;
                         dispose(p1);
                         end;       end;end;


   loading(i,chipset);
   end;
   gotoxy(x,y+1);
   write('The loading has passed aptly.');
   end;
gotoxy(x,y+2);
write('Press <Enter>');
readkey;
end;
================================(запись данных в файл - первоначальное создание БД)
procedure inputchar(var mas:string);
var h:char;
begin
h:=readkey;
mas:='';
while (h<>#13) do
begin
mas:=mas+h;
write(h);
h:=readkey;
end;
end;

procedure kursor(item:byte);forward;

procedure create(x:byte);
var j,k:byte; mas:string; c:char;
begin
file_new(path);
assign (f,path);
rewrite (f);
q:=0;
repeat
inc(q);
table(number,31,x,true);
for i:=1 to number do
    begin
    gotoxy(x,y+i-1);
    write(menu[i]);
    end;
gotoxy (32,6);
write('Database creating');
for i:=1 to number do
    begin
    if i>1 then
           begin
          gotoxy(x+31,y+i-2);
          textbackground(blue);
          for j:=1 to 14 do write(' ');
          gotoxy(x+31,y+i-2);
          write (mas);
           end;
    gotoxy(x+31,y+i-1);
    textbackground(green);
    for j:=1 to 14 do write(' ');
    gotoxy(x+31,y+i-1);
    inputchar(mas);
    case i of
         1:chipset.name:=mas;
         2:chipset.processor:=mas;
         3:chipset.interf:=mas;
         4:chipset.system_bus_clockrate:=mas;
         5:chipset.max_processor:=mas;
         6:chipset.memory_type:=mas;
         7:chipset.ATA:=mas;
         8:chipset.USB:=mas;
         9:chipset.AGP:=mas;
              end;
    if i=number then begin
                gotoxy(x+31,y+i-1);
                textbackground(blue);
                for j:=1 to 14 do write(' ');
                gotoxy(x+31,y+i-1);
                write (mas);
             end;
     end;
gotoxy(30,20);
write('One more record (y/n)? ');
c:=readkey;
write(f,chipset);
until c=#110;
close(f);
end;


ну там еще несколько процедур: создание таблиц, управление курсором и т.д.


Автор: Fedor 11.5.2005, 21:37
Mager2005 Используйте пожалуйста теги CODE для обраления кода.

Автор: Mager2005 14.5.2005, 22:08
Народ! Нашлось решение. Ура !!!! Все намного проще, чем казалось. И кто бы мог подумать.
Значит, здесь вместо двух процедур reading и loading надо записать следующее:
Код

procedure read_in_memory (x,y:word;);
var name:string; i,j:byte;
begin
file_new(path);
assign(f,path);
{$I-}
reset(f);
{$I+}
if IOResult<>0 then begin gotoxy(x,y+1); writeln('File is not found'); end
else
begin
head:=nil;
while not eof(f) do
      begin
      read(f,chipset);
      if head=nil then
               begin
               new(p);
               head:=p;
               end
          else
               begin
               new(p^.next);
               p:=p^.next;
               end;
      p^.data:=chipset;
      p^.next:=nil;
      end;
gotoxy(x,y+1);
write('The loading has passed successfully....');
end; 
gotoxy(x,y+2);
write('Press <Enter>');
readkey;
end;

Что значит, если долго мучиться, что-нить да получится smile
Правда, решение не мое, и все же .....

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)