Q&A

  • TList 질문입니다.
TList떄문에 하루종일 머리 싸매고 뒹굴고 있슴돠.. 고수님덜

좀 도와 주세염~ ㅜ_ㅡ

다름이 아니라.. 제가 일단 listview에 있는 내용을 메모리에 TList에 저장을

시킨후에 그 저장되 있는것중 특정값을 가진 소스에선 id이 'dfdf'인

값을 지닌 레코드(?)의 name과 pass 값을 가져오고 싶습니다.

그래서 이 값들을 두번째 리스트뷰에 출력을 하고자 합니다.

그래서 버튼을 만들어서 해보았지만.. 계속 에러만 발생합니다.

도저히 뭔지 모르겠네염.. 좀 알려주세요..

procedure TForm1.Button2Click(Sender: TObject); 에 검색 해서 출력하는

부분을 같이 넣으면 되는데 왜 프로시저가 달라지면 안되는걸까욤?

좀 알려주세요~~~ ㅜ_ㅡ




unit TListfrm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type
  PMyList = ^AList;
  AList = record
    id : string;
    pass : string;
    name : string;
  end;

  TForm1 = class(TForm)
    ListView1: TListView;
    ListView2: TListView;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }

  public
    { Public declarations }
    MyList : TList;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);
var
  ARecord : PMyList;
  i,j : integer;
  listitem : Tlistitem;
begin

  for i := 0 to listview1.Items.Count-1 do
  begin
    New(ARecord);
    ARecord^.id := listview1.Items.Item[i].Caption;
    ARecord^.pass := listview1.Items.Item[i].SubItems.Strings[0];
    ARecord^.name := listview1.Items.Item[i].SubItems.Strings[1];
    MyList.Add(ARecord);
  end;



end;

procedure TForm1.Button1Click(Sender: TObject);
var
  j : integer;
  ARecord : PMyList;
  listitem : Tlistitem;
begin
  for j := 0 to MyList.Count-1 do
  begin
    ARecord := MyList.Items[j];
    listitem := listview2.Items.Add;
    listitem.Caption := ARecord.id;
    listitem.SubItems.Add(ARecord.pass);
    listitem.SubItems.Add(ARecord.name);
  end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
  j : integer;
  ARecord : PMyList;
begin
{ Cleanup: must free the list items as well as the list }
  for j := 0 to MyList.Count-1 do
  begin
    ARecord := MyList.Items[j];
    Dispose(ARecord);
  end;
  MyList.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  MyList := TList.Create;
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  ARecord : PMyList;
  listitem : TListitem;
begin

  showmessage(inttostr(mylist.indexof(ARecord)));

  ARecord^.id := 'dfdf';
  MyList.IndexOf(ARecord); // 여기가 문제인듯.. 함돠.. ㅜ_ㅡ

  listitem := listview2.Items.Add;
  listitem.Caption := ARecord.id;
  listitem.SubItems.Add(ARecord.pass);
  listitem.SubItems.Add(ARecord.name);
end;

end.
2  COMMENTS
  • Profile
    강두헌 2002.02.19 19:03
    먼저 전 고수가 아니고요 초보의 허접한 답변입니다. 참고만 하세요.



    이 부분은 말씀하신 뜻을 정확히 모르겠습니다. 아래처럼해서 되는 경우가 있다는 뜻인가요? 그럼 이상한건데..


    문제의 시작은 여기죠.. 여기서 ARecord는 Pointer이고 아무곳이나 가르키고 있는 상태인데 여기에다 값을 넣었으니... 잘못하면.. 뭔일이 나도 나지요..



    TList.IndexOf는 TList로 연결된 Pointer들중에 어떤 주소를 알 경우에 사용하는 겁니다. 그런에 여기서 ARecord는 이상한 주소를 가르키고 있지요..



    제가 이래서 안돼고 저래서 안돼고.. 말을 했으니 그럼 이렇게 하면 될거 같다는 말을 해야 할 차례네요.. 간단히 말하면.. 검색을 해야지요.
    TList에 연결된 item을 대상으로 검색을 해야 하지요.

    당연히 검색 방법은 여러가지가 있구요.

    (이 이하는 다 아시는 내용이 될거 같지만, 이왕 쓰기 시작한거 씁니다.)

    Data가 적거나 혹 Data가 많더라도 검색횟수가 적다면 가장 쉽고 무식한 순차검색을 하시는게 좋을거구요..

    그렇지 않다면 검색 함수를 만들어야 합니다. 아래는 제가 즐겨 사용하는 이진검색입니다.
    제가 사용하는 code를 web상에서 고친것이기 때문에 오타가 있을 수 있습니다.


    먼저 Sort함수를 만들고요.
    function SortById(Item1, Item2 : Pointer) : Integer;
    var
      tmpId1 : string;
      tmpId2 : string;
    begin
      tmpId1 := PMyList(Item1)^.Word;
      tmpId2 := PMyList(Item2)^.Word;
      Result := CompareStr(tmpId1,tmpId2);
    end;

    TList에 data를 다 넣은 다음에 한번 Sort해 주고
    MyList.Sort(SortById);


    검색함수를 부르면 있는 위치가 나오지요.. (이진 검색입니다.)
    function TForm1.GetIndexNoById(AId : string) : integer;
    var
      pML : PMyList;
      i, Right, Left : integer;
    begin
      Result := -1;
      if MyList.Count <= 0 then Exit;
      Left := 0; Right := MyList.Count-1;
      while True do
      begin
        i := Round((Left + Right) / 2);
        pML := MyList.Items[i];
        if CompareStr(pML^.Id,AId) = 0 then
        begin
          Result := i;
          Exit;
        end
        else if CompareStr(pML^.Id,AId) > 0 then
          Right := i-1
        else
          Left := i+1;
        if (Left > Right) then Exit;
      end;
    end;

    헉헉.. 무지 길어졌네요.. 끝을 보고 싶어서...
    이제 그만 뒹구시고.. 즐코..^^
  • Profile
    이강민 2002.02.19 23:44
    답변 감사 드립니다.

    잘 되네염~~ ^^ 감솨함돠~~~ ㅜ_ㅡ