Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 08.09.2011, 11:59   #1
pobedin
Форумчанин
 
Регистрация: 30.07.2009
Сообщений: 105
По умолчанию Список. Ошибка удаления

Здравствуйте. Разбираюсь впервые с линейным списком. Не выходит сделать никак удаление и изменение определенной записи. Ошибка в последней процедуре.
Код:
unit dlist1_;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Grids, ExtCtrls, Menus;

type
  TfrmMain = class(TForm)
    mm1: TMainMenu;
    mniN1: TMenuItem;
    grp1: TGroupBox;
    strngrd1: TStringGrid;
    grp2: TGroupBox;
    lbl4: TLabel;
    lbl5: TLabel;
    edtName: TEdit;
    edtNumber: TEdit;
    edtType: TEdit;
    edtColor: TEdit;
    edtValue: TEdit;
    lbl1: TLabel;
    lbl2: TLabel;
    lbl3: TLabel;
    pnl1: TPanel;
    btn1: TButton;
    btn2: TButton;
    btn3: TButton;
    mniN2: TMenuItem;
    pnl2: TPanel;
    grp3: TGroupBox;
    btn4: TButton;
    edtSearch: TEdit; 
    procedure btn1Click(Sender: TObject);
    procedure btn2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btn3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }

  end;

var
  frmMain: TfrmMain;

implementation

{$R *.DFM}

type
  TPList = ^TList; //указатель на тип

  TList = record
    name: string[20];
    number: string[20];
    value: string[10];
    typeProd: string[10];
    color: string[10];
    next: TPList; // следующий элемент списка
  end;

var
  head: TPList; // начало (голова) списка
  curr: TPList; // текущий элемент списка

  // добавить элемент в начало списка

procedure TfrmMain.btn1Click(Sender: TObject);
var
  curr: TPList; // новый элемент списка
begin
  new(curr); // выделить память для элемента списка
  curr^.number := edtName.Text;
  curr^.name := edtName.Text;
  curr^.value := edtValue.Text;
  curr^.typeProd := edtType.Text;
  curr^.color := edtColor.Text;

  // добавление в начало списка
  curr^.next := head;
  head := curr;

  // очистить поля ввода
  edtType.text := '';
  edtColor.text := '';
  edtName.text := '';
  edtNumber.text := '';
  edtValue.text := '';
end;

// вывести список

procedure TfrmMain.btn2Click(Sender: TObject);
var
  i, j: integer;
begin
  j := 1;
  curr := head; // указатель на первый элемент списка
  while curr <> nil do
  begin
    i := 1;
    strngrd1.Cells[i, j] := curr^.number;
    Inc(i);
    strngrd1.Cells[i, j] := curr^.name;
    Inc(i);
    strngrd1.Cells[i, j] := curr^.value;
    Inc(i);
    strngrd1.Cells[i, j] := curr^.typeProd;
    Inc(i);
    strngrd1.Cells[i, j] := curr^.color;
    Inc(j);
    curr := curr^.next; // указатель на следующий элемент
  end;
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  Caption := 'БД мебельной фабрики';
  strngrd1.ColCount := 6;
  strngrd1.Cells[1, 0] := '№ изделия';
  strngrd1.Cells[2, 0] := 'Название';
  strngrd1.Cells[3, 0] := 'Цена';
  strngrd1.Cells[4, 0] := 'Тип';
  strngrd1.Cells[5, 0] := 'Цвет';
  edtType.Clear;
  edtColor.Clear;
  edtName.Clear;
  edtNumber.Clear;
  edtValue.Clear;
  edtSearch.Clear;
end;

procedure TfrmMain.btn3Click(Sender: TObject); //удаление записи
var
  n: word; //счетчик
  PListCur: TPList; //дополнительный указатель
  m: integer;
begin
  m := 0;
  if strngrd1.Row <> 2 then
    m := strngrd1.Row - 1
  else
    m := strngrd1.Row;
  n := 1;
  curr := head; //переводим основной указатель в начало списка
  while n < m do
  begin
    curr := curr^.Next; //устанавливаем указатель перед удаляемым элементом
    inc(n);
  end;
  PListCur := curr; //ставим дополнительный указатель перед удаляемым элементом
  curr := curr^.Next; //переводим основной указатель на удаляемый элемент
  PListCur^.Next := curr^.Next; //соединяем список
  Dispose(curr); //удаляем нужный элемент.
end;

end.
pobedin вне форума Ответить с цитированием
Старый 08.09.2011, 12:17   #2
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Код:
Dispose(curr); //удаляем нужный элемент.
ага, а Dispose наследуется от формы? Оригинально.
Человек_Борща вне форума Ответить с цитированием
Старый 08.09.2011, 12:18   #3
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

1) нет начальной иницилизации head := nil;

2) нет проверки при удалении, что список не пуст.

3) нет проверки на то, что перебор записей успешно завершён.
ну, если m введёте БОЛЬШЕ, чем записей в списке.

4) поясните, не смог вникнуть в суть кода:
Код:
  if strngrd1.Row <> 2 then
    m := strngrd1.Row - 1
  else
    m := strngrd1.Row;
почему, если текущая строчка грида не третья, тогда берём номер строчки - 1, а иначе m := 2 ?!! В чём смысл данных манипуляций?

p.s. программку не запускал. все выводы чисто умозрительные. если что-то проглядел - сорри...

p.p.s. Отладка в любом случае спасёт отца русской демократии - ставьте точки останова и проходите в пошаговом режиме, следя за указателями и за тем, куда они показывают...

Цитата:
Сообщение от Человек_Борща
ага, а Dispose наследуется от формы? Оригинально.
замечание вообще не в тему.
При чём здесь наследование? При чём здесь форма?!
Dispose(Указатель) - освободить память, выделенную под структуру...

Последний раз редактировалось Serge_Bliznykov; 08.09.2011 в 12:23.
Serge_Bliznykov вне форума Ответить с цитированием
Старый 08.09.2011, 12:20   #4
pobedin
Форумчанин
 
Регистрация: 30.07.2009
Сообщений: 105
По умолчанию

Нда, здесь немного намудрил.
з.ы. Иногда удаляет, но очень странно. удаляет не всю строку, а какой-то элемент в строке. Так вообще возможно?

Последний раз редактировалось pobedin; 08.09.2011 в 12:26.
pobedin вне форума Ответить с цитированием
Старый 08.09.2011, 12:40   #5
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Цитата:
з.ы. Иногда удаляет, но очень странно. удаляет не всю строку, а какой-то элемент в строке. Так вообще возможно?
нет.
начните с иницилизации head.

и учтите, что когда Вы освобождаете память, занятую под запись, эта память только помечается в куче как свободная, но содержимое остаётся доступным (некоторое время, конечно).
Но это говорит прежде всего о том, что Вы (как программист) неправильно работаете с указателями и памятью!
Serge_Bliznykov вне форума Ответить с цитированием
Старый 08.09.2011, 13:01   #6
pobedin
Форумчанин
 
Регистрация: 30.07.2009
Сообщений: 105
По умолчанию

сделал по-другому, с проверкой. как задать del какое-нибудь значение чтобы запись сравнивалась и удалялась? у меня всегда не находит удаляемую запись.
Код:
procedure TfrmMain.btn3Click(Sender: TObject);
var
  del: TPList;
  prev: TPList;
begin
  if head = nil then
  begin
      ShowMessage('ERROR');
      Exit;
  end;
  if del = head then
    head := del^.next
  else
  begin
    prev := head^.next;
    while (prev^.next <> del) and (prev^.next <> nil) do
      prev := prev^.next;
    if prev^.next = nil then
    begin
      ShowMessage('ERROR not found');
      Exit;
    end;
    prev^.next:=del^.next;
    end;
    Dispose(del);
  end;
pobedin вне форума Ответить с цитированием
Старый 08.09.2011, 13:17   #7
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Вы, надеюсь, шутите?

ну если Вы описали del : TPList;
то откуда там возьмётся значение
(да ещё не просто значение, а значение равное указателю на какую-то запись из списка!)?!!!
ответ - ниоткуда!

Я бы предложил Вам всё-таки вернуться к начальному варианту:
удалять запись по её порядковому номеру.
Тогда перебираете записи до нужного номера. Нашли нужную запись - удалили. Если указали номер больше, чем есть записей в списке - сообщение о невозможности удаления и выход.
Serge_Bliznykov вне форума Ответить с цитированием
Старый 08.09.2011, 13:19   #8
pobedin
Форумчанин
 
Регистрация: 30.07.2009
Сообщений: 105
По умолчанию

понятно. спасибо.
pobedin вне форума Ответить с цитированием
Старый 08.09.2011, 13:28   #9
pobedin
Форумчанин
 
Регистрация: 30.07.2009
Сообщений: 105
По умолчанию

Рабочий вариант.
Код:
procedure TfrmMain.btn3Click(Sender: TObject);
var
  n: word; 
  PListCur: TPList;
begin
n := 1;
curr := head; 
while n < strngrd1.row - 1 do
begin
  curr := curr^.Next; элементом
  inc(n);
end;
PListCur := curr; 
curr := curr^.Next;
PListCur^.Next := curr^.Next; 
Dispose(curr); 
end;
pobedin вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
C++(удаления узла) Xaceo Помощь студентам 1 28.03.2011 18:05
список (в чем ошибка ?) rowlin Паскаль, Turbo Pascal, PascalABC.NET 5 17.12.2010 21:21
Ошибка в ленточной форме зависемый список vlad-minsk Microsoft Office Access 3 18.10.2010 12:18
Список с заглавным звеном, из текстового файла получить список из записей и по нему уже сделать задание Zigfried Помощь студентам 2 04.10.2010 20:29
Защита от удаления Михаил Юрьевич Общие вопросы Delphi 2 22.01.2010 22:48