Модераторы: Poseidon
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [Delphi] Работа со сложными структурами данных 
:(
    Опции темы
SniyLSD
Дата 28.5.2008, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 32
Регистрация: 28.5.2008

Репутация: нет
Всего: нет



Всем привет! У меня есть небольшая просьба о помощи по теме динамические структуры данных, 
Есть задача :
    Элементы двунаправленного списка имеют следующую структуру:
- Шифр детали
- Наименование
- Цена
- Вес
- Указатель предыдущего
- Указатель последующего
Удалить элемент с заданным номером  от конца списка.

Проблема вот в чем, я написал программу, Работает, но частично, она может добавлять данные в дин.список, может выводить их в таблицу, но не работает удаление нужного элемента списка, мало того, программа просто виснет во время нажатия на кнопку удаления эл. пожалуйста, помогите, посмотрите скрипт расскажите в чем проблема, и, если не трудно, поправьте скрипт чтоб он работал, плиз
Скрипт прилагается(Делфи 7): 

Присоединённый файл ( Кол-во скачиваний: 8 )
Присоединённый файл  _______11_4.rar 196,71 Kb
PM MAIL   Вверх
anwe
Дата 28.5.2008, 22:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 748
Регистрация: 2.9.2006

Репутация: 9
Всего: 23



Тебе надо все последующие номера сместить на 1 влево: на место 2-го пойдет 3, на место 3-го пойдет 4 и т. д. А потом у смещенных уменьшить номера на единицу.
А в коде, не разбираясь с записями, видна сразу явная ошибка:
Код

   while p<>nil do
   i:=i+1;
Где смена условия? Где изменение р? Это бесконечный цикл!

Это сообщение отредактировал(а) anwe - 28.5.2008, 22:46
PM MAIL   Вверх
SniyLSD
Дата 29.5.2008, 05:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 32
Регистрация: 28.5.2008

Репутация: нет
Всего: нет



Понятно вроде, но слишком замудрился я с ней smile  - тему "Дин. списки " я плохо понял smile
Цитата

 А в коде, не разбираясь с записями, видна сразу явная ошибка:

  while p<>nil do
   i:=i+1;


Так, вроде чуть поправил:
Код

begin
  k:=strtoint(edit1.text);
  i:=0;
  g:=(t-k)+1;
   while p<>nil do
   i:=i+1;
   p:=p^.next;{вставил изменение p, но начинает выдавать ошибку на обращение к памяти. похоже надо поставить в конец кода этот оператор}
    if (i=g) then
      Begin
        P:=Head;//
        B:=False; //перенесен из начала процедуры
          If P=Head Then
            Begin
              Head:=P^.Next;
              p1:=p^.next;
            End
            Else
              Begin
                If P^.Next=Nil Then
                b:=true
                  Else
                    Begin
                      Last^.Next:=P^.Next;
                      P1:=P^.next;
                      P1^.prev:=last;
                    End;
              End;
              If  B Then
              Last^.Next:=Nil;
            End;
            Last:=P;
            P:=P^.Next;
          end;


Теперь не виснет, но выдает ошибку типа 
"Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 0045F58E in module 'Project1.exe'. Read of address 00000054'. Process stopped. Use step or Run to continue." Ошибку обращения к памяти.

[quote]Тебе надо все последующие номера сместить на 1 влево: на место 2-го пойдет 3, на место 3-го пойдет 4 и т. д. А потом у смещенных уменьшить номера на единицу.[quote]
эммм... не понял, эти номера на счет чего?
 если честно, я этот код списал из программы аналогичной задачи, но там было другое условие - Удалить повторяющиеся элементы списка, если в них совпадает шифр и наименование. Сам в нем плохо разобрался.

Можете мне помочь написать этот кусок кода правильно? Чтоб работал))
PM MAIL   Вверх
SniyLSD
Дата 29.5.2008, 08:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 32
Регистрация: 28.5.2008

Репутация: нет
Всего: нет



Понятно вроде, но слишком замудрился я с ней :crazy  - тему "Дин. списки " я плохо понял :dash1
Цитата

 А в коде, не разбираясь с записями, видна сразу явная ошибка:

  while p<>nil do
   i:=i+1;


Так, вроде чуть поп
PM MAIL   Вверх
anwe
Дата 29.5.2008, 13:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 748
Регистрация: 2.9.2006

Репутация: 9
Всего: 23



Цитата(SniyLSD @  29.5.2008,  07:06 Найти цитируемый пост)
тему "Дин. списки " я плохо понял 

Это одно а незнание элементарных операторв - это другое. Почитай про while..do. Для выхода условие должно менятся внутри цикла. То что добавлено, ничего не дает. Для этого оператора при его работе с циклом из нескольких строк нужны операторные скобки. Да и добавил строку p:=p^.next, независящую от i. А проскакивает у тебя этот цикл, вероятно, потому что делаешь это в первый же раз. Другими словами и p и head=nil
Цитата
эммм... не понял, эти номера на счет чего?

Это индексы элементов в массиве.

Это сообщение отредактировал(а) anwe - 29.5.2008, 13:39
PM MAIL   Вверх
SniyLSD
Дата 29.5.2008, 15:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 32
Регистрация: 28.5.2008

Репутация: нет
Всего: нет



Походу я намудрил с алгоритмом подсчитывания номера удаляемого элемента от головы. это все и усложнило процедуру удаления, а может этот способ даже неприемлен для данной ситуации, что вызывает различного рода ошибки.
Можете мне помочь написать код который выбирает элемент с заданным номером от конца списка? то есть в списке 10 элементов, выбрали второй элемент от конца, а от головы он будет 9. а дальше мне будет понятнее, так как траблы у меня именно с этим((
Код


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, ExtCtrls, Grids;
    {    Элементы двунаправленного списка имеют следующую структуру:
- Шифр детали
- Наименование
- Цена
- Вес
- Указатель предыдущего
- Указатель последующего
Удалить элемент с заданным номером  от конца списка.}
type
  TForm1 = class(TForm)
    Button1: TButton;
    Button4: TButton;
    sed1: TLabeledEdit;
    sed2: TLabeledEdit;
    sed3: TLabeledEdit;
    sed4: TLabeledEdit;
    Button6: TButton;
    Edit1: TEdit;
    StringGrid1: TStringGrid;
    Button2: TButton;
    procedure Button4Click(Sender: TObject);



    procedure Button1Click(Sender: TObject);

    procedure Edit1KeyPress(Sender: TObject; var Key: Char);

    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

Type
   TPPrice=^Tprice;

   TPrice=record
   index:string[20];
   name:string[20];
   price:string[20];
   mass:string[20];
   next:TPPrice;
   prev:TPPrice;
   end;
var
  Form1: TForm1;
   n,t:integer;        //t - количество элементов в списке
   p,p1,p2,head,last: TPPrice;
   B,B1:boolean;

implementation

{$R *.dfm}

procedure TForm1.Button4Click(Sender: TObject);
begin
 Application.Terminate;
end;

procedure TForm1.Button1Click(Sender: TObject);

begin
 new(p);
 p^.index:=sed1.Text;
 p^.name:=sed2.Text;
 p^.price:=sed3.text;
 p^.mass:=sed4.text;
  if head=nil then
  begin
    p^.next:=nil;
    p^.prev:=nil;
    head:=p;
    last:=p;
  end
  else
    begin
      last^.next:=p;
      p^.prev:=last;
      p^.next:=nil;
    end;
  last:=p;
   sed1.clear;
   sed2.clear;
   sed3.clear;
   sed4.clear;
   sed1.SetFocus;
   END;
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);  {процедура фильтрации ввода}
begin
 case key of
  '0'..'9':;
  else key:=chr(0);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   head:=nil;
  last:=nil;
  n:=0;
  StringGrid1.Cells[0,0]:='№';
  StringGrid1.Cells[1,0]:='Шифр';
  StringGrid1.Cells[2,0]:='Наименование';
  StringGrid1.Cells[3,0]:='Цена';
  StringGrid1.Cells[4,0]:='Вес';
end;

procedure TForm1.Button2Click(Sender: TObject); {процедура вывода списка в таблицу}
var i:integer;
begin
  i:=0;
  p:=head;
  StringGrid1.RowCount:=2;
  StringGrid1.Cells[0,1]:='';
  StringGrid1.Cells[1,1]:='';
  StringGrid1.Cells[2,1]:='';
  StringGrid1.Cells[3,1]:='';
  StringGrid1.Cells[4,1]:='';
  t:=0;
  while p<>nil do
    begin
      t:=t+1; // здесь мы считаем количество элементов в списке
      i:=i+1;
      StringGrid1.RowCount:=StringGrid1.RowCount+1;
      StringGrid1.Cells[0,i]:=IntToStr(i);
      StringGrid1.Cells[1,i]:=p^.index;
      StringGrid1.Cells[2,i]:=p^.name;
      StringGrid1.Cells[3,i]:=p^.price;
      StringGrid1.Cells[4,i]:=p^.mass;
      p:=p^.next;
    end;
  StringGrid1.Cells[0,i+1]:='';
  StringGrid1.Cells[1,i+1]:='';
  StringGrid1.Cells[2,i+1]:='';
  StringGrid1.Cells[3,i+1]:='';
  StringGrid1.Cells[4,i+1]:='';

  END;

procedure TForm1.Button6Click(Sender: TObject);
var
 k,g,i:integer;
begin
  k:=strtoint(edit1.text);
  i:=0;
  g:=(t-k)+1; 

{ g - нужный нам элемент, получаемый в результате вычитания числа введенного пользователем из числа t и суммой полученного числа с 1. в результате мы начинаем считать цикл идущий следом, если i (количество проведенных циклов - совпадает с номером элемента от головы) , будет равно числу g то инициируется удаление данного элемента.}


   while p<>nil do
   i:=i+1;
    if (i=g) then
      Begin
        P:=Head;
        B:=False;
          If P=Head Then
            Begin
              Head:=P^.Next;
              p1:=p^.next;
            End
            Else
              Begin
                If P^.Next=Nil Then
                b:=true
                  Else
                    Begin
                      Last^.Next:=P^.Next;
                      P1:=P^.next;
                      P1^.prev:=last;
                    End;
              End;
              If  B Then
              Last^.Next:=Nil;
            End;
            Last:=P;
            P:=P^.Next;
          end;

    
end.





Вот вроде с этим понятнее , можно ли как нибудь по другому реализовать выбор нужного нам элемента списка?
PM MAIL   Вверх
anwe
Дата 29.5.2008, 19:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 748
Регистрация: 2.9.2006

Репутация: 9
Всего: 23



Отвечая на первый вопрос
Цитата(SniyLSD @  28.5.2008,  16:54 Найти цитируемый пост)
но не работает удаление нужного элемента списка

привожу работоспособный код:
Код

Type
   TPPrice=^Tprice;
   TPrice=record
   index:string[20];
   name:string[20];
   price:string[20];
   mass:string[20];
   nomer:byte;         //это добавлено: номер элемента в списке
   next:TPPrice;
   prev:TPPrice;
   end;
Код

procedure TForm1.Button1Click(Sender: TObject);
begin
n:=n+1;          //это добавлено
...
p^.nomer:=n;   //это добавлено
...

Добавлена кнопка Button3 (чтобы твой код не трогать)
Код

procedure TForm1.Button3Click(Sender: TObject);
var
 k,i:integer;
 q:TPPrice;
begin
k:=strtoint(edit1.text);
P:=Head;
try
    if k<>1 then
        while k-1<>p^.nomer do
        p:=p^.next;
    q:=p^.next;
    p^.next:=q^.next;
    p:=q;
    if k=n then
    p:=p^.prev;
    for i:=k+1 to n-1 do
        begin
        p:=p^.next;
        p^.nomer:=p^.nomer-1;
        end;
    n:=n-1;
    Button2.Click;
except
ShowMessage('Такого номера нет);
end;
end;

Ниже сам проект.

Присоединённый файл ( Кол-во скачиваний: 27 )
Присоединённый файл  _______11_4.rar 199,94 Kb
PM MAIL   Вверх
SniyLSD
Дата 30.5.2008, 00:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 32
Регистрация: 28.5.2008

Репутация: нет
Всего: нет



Ого! Спасибо дружище! Блин, не додумался до такого простого варианта (, видно сказывается небольшой опыт практического программирования, да и с сессией замотался - мозги кипят smile , сейчас курсовой проект как раз только закончил, на часах у меня 6 утра.
Еще раз спасибо)  smile 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Центр помощи"

ВНИМАНИЕ! Прежде чем создавать темы, или писать сообщения в данный раздел, ознакомьтесь, пожалуйста, с Правилами форума и конкретно этого раздела.
Несоблюдение правил может повлечь за собой самые строгие меры от закрытия/удаления темы до бана пользователя!


  • Название темы должно отражать её суть! (Не следует добавлять туда слова "помогите", "срочно" и т.п.)
  • При создании темы, первым делом в квадратных скобках укажите область, из которой исходит вопрос (язык, дисциплина, диплом). Пример: [C++].
  • В названии темы не нужно указывать происхождение задачи (например "школьная задача", "задача из учебника" и т.п.), не нужно указывать ее сложность ("простая задача", "легкий вопрос" и т.п.). Все это можно писать в тексте самой задачи.
  • Если Вы ошиблись при вводе названия темы, отправьте письмо любому из модераторов раздела (через личные сообщения или report).
  • Для подсветки кода пользуйтесь тегами [code][/code] (выделяйте код и нажимаете на кнопку "Код"). Не забывайте выбирать при этом соответствующий язык.
  • Помните: один топик - один вопрос!
  • В данном разделе запрещено поднимать темы, т.е. при отсутствии ответов на Ваш вопрос добавлять новые ответы к теме, тем самым поднимая тему на верх списка.
  • Если вы хотите, чтобы вашу проблему решили при помощи определенного алгоритма, то не забудьте описать его!
  • Если вопрос решён, то воспользуйтесь ссылкой "Пометить как решённый", которая находится под кнопками создания темы или специальным флажком при ответе.

Более подробно с правилами данного раздела Вы можете ознакомится в этой теме.

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Poseidon, Rodman

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Центр помощи | Следующая тема »


 




[ Время генерации скрипта: 0.0526 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.