Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > [Delphi] Удалить элемент из типизированного файла


Автор: BlackDan 7.6.2009, 21:09
Решите пожалуйста проблему - В общем есть типизированный файл с записями вида 
Код

events = record
  name:string[80];
  head:string[80];
  content:string[255];
  dates:tdate;
  times:ttime;
  types:string[80];
  Aligns:TAlignment;
  fstyle:TFontStyles;
  fonts:Tfont;
  pointer:integer;

 Нужно удалить одну из записей из файла по ее "номеру" там (pointer).
Пытался так
 
Код

procedure TForm3.BitBtn2Click(Sender: TObject);
begin
rewrite(base);
while not(eof(base)) do begin
   write(base,c_t_b[e]);
   c_t_b[e]:=c_t_b[e+1];
  end;
  closefile(base);
  close;
  end;
 где 'e'- номер удаляемого элемента. Он мне все записи из файла выносит =) 

Запись в файл
Код

if FileExists('base.dat') then begin
 reset(base);
  seek(base,filesize(base));
   i:=filesize(base)+1;
    c_t.pointer:=i;
   write(base,c_t);
 //showmessage(inttostr(filepos(base)));
  closefile(base);
 end
  else begin
   rewrite(Base);
  write(base,c_t);
 closeFile(Base);
  end;
  close;
end;


Чтение
Код

procedure TForm1.FormActivate(Sender: TObject);
var i:integer;
begin
 i:=1;
  assignfile(base,'base.dat');
   if FileExists('base.dat') then begin
    reset(base);
     while not (eof(base)) do
      begin
       read(base,c_t_b[i]);
       i:=i+1;
      end;
      closefile(base);
      end
   else begin
  rewrite(Base);
   closeFile(Base); end;
   t:=i;
end;

Автор: kami 7.6.2009, 22:24
не разбирался, что такое c_t и c_b_t, посему - как-то так:

Код

procedure DeleteRecordInFile(index:integer);
var
  i:integer;
begin
  rewrite(base);
  for i:=0 to length(my_array)-1 do // это если динамический массив. 
    if i<>index then  // если номер записи - не тот, который нужно удалить, то
      write(base, my_array[i]);  // записываем.
  // иначе - просто пропускаем.
  closeFile(base);
end;

procedure DeleteRecordInMemory(index:integer);
var
  i:integer;
begin
  for i:=index+1 to Length(my_base)-1 do
    my_base[i-1]:=my_base[i]; // перемещаем все записи начиная с удаляемой на 1 вперед.
  SetLength(my_base, Length(my_base)-1); // устанавливаем новую длину для массива.
end;


Добавлено через 4 минуты и 59 секунд
Позволю себе немного прокомментировать ваш код:
Цитата(BlackDan @  7.6.2009,  21:09 Найти цитируемый пост)

Код

rewrite(base); // обнуляем файл, делая ему размер=0
while not(eof(base)) do // пока не достигнут конец файла... гхм... вообще-то он достигнут на предыдущей строке, когда стал размером=0.
  begin   
    write(base,c_t_b[e]); // соответственно - сюда уже никогда не зайдем :)




P.S. Отладчик (т.е. breakpoint`s и клавиши F7 и F8) придумали не трусы smile 
Всего-то нужно было поставить breakpoint на начало этой процедуры и пройтись по ней по F8 - все стало бы прозрачно.

Автор: BlackDan 8.6.2009, 13:26
Цитата

это если динамический массив. 


У меня статический одномерный массив 

Автор: BlackDan 8.6.2009, 14:25
Сделал примерно так как вы сказали
Код

procedure TForm3.BitBtn2Click(Sender: TObject);
var i,i1,j:integer;
begin
j:=length(c_t_b);
rewrite(base);
for i := 1 to j do
  if i<>e then write(base,c_t_b[i])
   else begin
  closefile(base);
  close;
  end;
    for i1:=e+1 to j-1 do
    c_t_b[i1-1]:=c_t_b[i1];
   end;

Удаление заработало, но после удаления запись в файл на ту-же дату (уже с другим поинтером) вызавало Range Error теперь-же (хотя кажется я ничего существенно не менял) вообще не запускается а выдает переполнение на этой строчке  
Код
c_t_b[i1-1]:=c_t_b[i1];
 

Автор: kami 8.6.2009, 17:51
BlackDan, давай на "ты", проще будет.

Во первых (вернее, уже в который раз, afair):
используй форматирование кода.

Твой код с моими комментариями:

Код

  j := length(c_t_b);
  rewrite(base);
  for i := 1 to j do
    if i <> e then // в твоем коде непонятно, откуда это e берется и что это такое. Примем, что это глобальная переменная,
                         // обозначающая номер исключаемой записи.
      write(base, c_t_b[i])  // если номер не совпал - записываем
    else
      begin
        closefile(base); // а если совпал - закрываем файл базы. А теперь внимание:
                                 // допустим, в базе 10 записей. Удаляем вторую.
                                 // и что теперь? Цикл-то пойдет дальше, но base уже закрыт. И на следующем "витке" 
                                 //Write(base...) вызовет ошибку. Бо base теперь нету.
        close; // это что - не понимаю.
      end; // вывод - убрать куда подальше все, что после else. И сам else. Базу закрывать на выходе из процедуры.
  for i1 := e + 1 to j - 1 do
    c_t_b[i1 - 1] := c_t_b[i1]; // если элементы этого статического массива начинаются с нуля, то все нормально.


Добавлено через 1 минуту и 53 секунды
Цитата(BlackDan @  8.6.2009,  14:25 Найти цитируемый пост)
после удаления запись в файл на ту-же дату (уже с другим поинтером) вызавало Range Error теперь-же (хотя кажется я ничего существенно не менял) вообще не запускается а выдает переполнение на этой строчке  

На какой на этой?
Поставь breakpoint на "эту" строчку и посмотри, чему равны переменные перед ее выполнением.

Добавлено через 3 минуты и 28 секунд
Цитата(kami @  8.6.2009,  17:51 Найти цитируемый пост)
На какой на этой?

Упс... недосмотрел.
Но это не отменяет нижесказанного:
Цитата(kami @  8.6.2009,  17:51 Найти цитируемый пост)
Поставь breakpoint на "эту" строчку и посмотри, чему равны переменные перед ее выполнением.


Автор: BlackDan 8.6.2009, 19:27
Цитата

BlackDan, давай на "ты", проще будет.

+1
Цитата

Поставь breakpoint на "эту" строчку и посмотри, чему равны переменные перед ее выполнением.

Строчку подсвечивает зеленым, брэкпоинт перечеркивается и открывается вкладка CPU в которой я ни чего не понимаю =)) Точнее я понимаю что это ячейки памяти, и то что я вижу как и что куда пишется...

Спасибо тебе, конечно, но у мне завтра надо сдать отчет о проге так что к теме вернусь когда сдам защиту =)  

Автор: kami 8.6.2009, 19:57
Цитата(BlackDan @  8.6.2009,  19:27 Найти цитируемый пост)
 брэкпоинт перечеркивается и открывается вкладка CPU в которой я ни чего не понимаю =))

Меню Project>Options>Compiler>включить Debug information

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