Delphi中Stringlist的自定義排序(將函數地址做為參數)


近日,在編制一個程序過程,因為數據量較小,就使用了stringlist來暫存數據。在使用過程中,遇到了一個問題。Stringlist字符串列表的默認排序方法是按ASCII碼的方式進行排序,如3,10,9排序時,結果為10,3,9.不符合程序的要求,於是嘗試着使用字符串列表的自主義排序方法,這時需要傳入一個function類的參數,因為習慣於使用PYTHON語言,所以直接編寫民了一個按數值降序排列的排序函數,並將函數名傳給了stringlistrr的CustomSort方法,結果提示:Incompatible types: 'regular procedure and method pointer'。大致意思是:不匹配的類型:需要一個方法、過程的指針類型。

為了解決這個問題,到網上查找資料,發現這個問題經常會遇到,但是各個解答要不就是看不懂,要不就是運行不成功,經過多次嘗試,最終解決了這個問題。

通過分析源代碼,結合網上程序,理清了網上的解決思路:1、在type處,定義一個function類型,.如:Tfunc=function(list: TStringList; index1,index2: Integer): Integer;  2、定義一個全局變量:如:myfunc:Tfunc;

3、編寫一個自定義的排序程序:如以下程序

function curmsort(list: TStringList; index1,
  index2: Integer): Integer;
var
  value1, value2: Integer;
begin
  value1 := StrToInt(list.Strings[index1]);
  value2 := StrToInt(list.Strings[index2]);
  if value1> value2 then
    Result :=  -1
  else if value1< value2 then
    Result := 1
  else
    Result := 0;
end;

4、在排序時,首先執行myfunc:=curmsort;(將自定義的函數名賦值給myfunc變量。)list.sorted:=False;,關閉排序,然后執行list.CustomSort(myfunc);

按照這個思路,最終也完成了自定義排序(將函數地址傳參)的功能。

完成后,回顧整個程序,通過對比、思考、實驗,發現第一、二步和最后一步的將函數名賦值給函數類型的變量都是可以省略的,關鍵的是自己定義的排序函數curmsort不能進行聲明,只要聲明了就不好使,個人感覺應該是因為在不聲明的情況下,函數名僅代表的是函數的內存地址,而不是執行函數的返回值。前邊的失敗是因為將函數進行了聲明,這時函數名代表了函數執行后的返回值,所以才導致類型不匹配。

例程如下:

unit Unit1;

interface

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

type
  
  TForm1 = class(TForm)
    lst1: TListBox;
    lst2: TListBox;
    btn1: TButton;
    procedure btn1Click(Sender: TObject);
  private
//注意,自定義的函數curmsort不能進行聲明。
    { Private declarations }
  public
    { Public declarations }
  end;

var
  
  Form1: TForm1;

implementation

{$R *.dfm}
function curmsort(list: TStringList; index1,   
  index2: Integer): Integer;   //寫函數時,函數名前不能加Tform1等限制。
var
  value1, value2: Integer;
begin
  value1 := StrToInt(list.Strings[index1]);
  value2 := StrToInt(list.Strings[index2]);
  if value1> value2 then
    Result :=  -1
  else if value1< value2 then
    Result := 1
  else
    Result := 0;
end;

procedure TForm1.btn1Click(Sender: TObject);
var list:TStringList;i:Integer;
begin
  list:=TStringList.Create;
  for i:=0 to 30 do
    begin
      list.Add(IntToStr(Random(3000)));
    end;
  lst1.Items.Assign(list);
  
  list.Sorted:=False;
  list.CustomSort(curmsort);
  lst2.Items.Assign(list);
end;

end.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM