全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:3613
推到 Plurk!
推到 Facebook!

動能陣列在function內以傳址方式無法動態設定陣列大小

答題得分者是:syntax
pceyes
尊榮會員


發表:70
回覆:657
積分:1140
註冊:2003-03-13

發送簡訊給我
#1 引用回覆 回覆 發表時間:2007-12-14 14:28:59 IP:220.141.xxx.xxx 訂閱
在函數(A_array)內需要以傳址(refrence)方式變更陣列大小(setlength), 結果是無法進行動態設定陣列大小(錯誤訊息incompress type),
因為不知陣列大小為何(SetLength(A1,file_st.count);),事後要再進行清除空白行, 會很怪。
今天(20071214)再次努力, 加上另一個動態陣列(_tmparray), 想做完後把它加回去, 結果不行, 錯誤訊息它說不能將動態陣列傳給靜態陣列
程式碼如下:拜託大家幫忙, 謝謝!

[code delphi]
unit Unit1;

interface

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

type
TForm1 = class(TForm)
Button1: TButton;
ListBox1: TListBox;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
file_st : tstringlist;
tmpstr : string;
implementation

{$R *.dfm}

// 20071213 finish
// Call by Refrence
// function add "Var" Can Call by Refrence
function ParsingRef(var _s1:string;_s2:string):string;
var
_tempback: string;
_width : integer;
_lens : integer;
begin
_tempback := '';
_lens := length(_s2);
if _s2 = null then begin
_s2 := ';';
_lens := 0;
end;
_width := pos(_s2,_s1);
if _width <>0 then begin
_tempback := copy(_s1,1,_width-1);
delete(_s1, 1, _width _lens-1);
end
else begin
_tempback := _s1;
end;
result := _tempback;
end;

// _OMARK 含不含註解空白行 (FALSE : 不含 ; TRUE : 含)
// _oArray 欲更新之陣列
// _ofile 欲分割之檔案
// _oBegin 文字檔區段起始
// _oEnd 文字檔區段結束
function A_Arrays(_oMark:boolean;var _oArray:Array of String;_ofile:string;_obegin:string;_oend:string):boolean;
const k_CRLF = #13 #10;
var
_line : string;
_count,i : integer;
_tmpArray : Array of string;
begin
result := false;
_line := '';
_count := 0;
setlength(_tmpArray,1); <- 原程式碼是 setlength(_oArray,1) 錯誤訊息是 incompress type
// 清除 _oBegin 之前的資料
if '' <> _obegin then begin
delete(_ofile,1,pos(_obegin,_ofile) length(_obegin));
end;
while '' <> _ofile do begin
_line := parsingRef(_ofile,k_crlf);
if (copy(_line,1,1)= '*') and (not _omark) then begin
_line := '';
end
else if (trim(_line) = '') and (not _omark) then begin
_line := '';
end
// 如果到了 _oEnd 就結束
else if uppercase(trim(_line))=uppercase(_oend) then begin
break;
end
else begin
if '' <> _ofile then begin
setlength(_tmpArray,_count 1); // 動態變換陣列大小
_tmpArray[_count] := _line;
_count := _count 1;
end;
end; // if
end; // while
// assign dynaarray to static array <- 這段原來是 _oArray := tmpArray; 錯誤訊息是 can't assign dynmet array to static array ; ( why ?
for i := 0 to _count -1 do begin
_oArray[i]:=_tmpArray[i];
end;

end;


procedure TForm1.Button1Click(Sender: TObject);
var i : integer;
tmpstr : string;
A1 : Array of string;
begin
file_st := tstringlist.create;
file_st.loadfromfile('c:\test.txt');
tmpstr := file_st.text;
SetLength(A1,file_st.count);
A_Arrays(false, A1, tmpstr,'MAINBEGIN','MAINEND');
form1.listbox1.Clear;
for i := 0 to length(A1)-1 do begin
if trim(A1[i]) <> '' then
form1.listbox1.items.add(trim(A1[i]));
end;
end;

end.

[/code]
------
努力會更接近成功
pceyes
尊榮會員


發表:70
回覆:657
積分:1140
註冊:2003-03-13

發送簡訊給我
#2 引用回覆 回覆 發表時間:2007-12-14 15:00:41 IP:220.141.xxx.xxx 訂閱
同樣的要求及做法將陣列改成Tstringlist就可以用了, 真是奇怪

[code delphi]
unit Unit1;

interface

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

type
TForm1 = class(TForm)
Button1: TButton;
ListBox1: TListBox;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
file_st : tstringlist;
tmpstr : string;
implementation

{$R *.dfm}

// 20071213 finish
// Call by Refrence
// function add "Var" Can Call by Refrence
function ParsingRef(var _s1:string;_s2:string):string;
var
_tempback: string;
_width : integer;
_lens : integer;
begin
_tempback := '';
_lens := length(_s2);
if _s2 = null then begin
_s2 := ';';
_lens := 0;
end;
_width := pos(_s2,_s1);
if _width <>0 then begin
_tempback := copy(_s1,1,_width-1);
delete(_s1, 1, _width _lens-1);
end
else begin
_tempback := _s1;
end;
result := _tempback;
end;

// _OMARK 含不含註解空白行 (FALSE : 不含 ; TRUE : 含)
// _oArray 欲更新之陣列
// _ofile 欲分割之檔案 , 請以暫存字串代入
// _oBegin 文字檔區段起始
// _oEnd 文字檔區段結束
function A_Arrays(_oMark:boolean;var _oArray:TStringlist;_ofile:string;_obegin:string;_oend:string):boolean;
const k_CRLF = #13 #10;
var
_line : string;
_count: integer;
begin
result := false;
_count := 0;
_line := '';
if (pos(_obegin,_ofile) = 0)or(pos(_oEnd,_ofile) = 0) then exit;
// 清除 _oBegin 之前的資料
if '' <> _obegin then begin
delete(_ofile,1,pos(_obegin,_ofile) length(_obegin));
end;
while '' <> _ofile do begin
_line := parsingRef(_ofile,k_crlf);
if (copy(_line,1,1)= '*') and (not _omark) then begin
_line := '';
end
else if (trim(_line) = '') and (not _omark) then begin
_line := '';
end
// 如果到了 _oEnd 就結束
else if uppercase(trim(_line))=uppercase(_oend) then begin
break;
end
else begin
if '' <> _line then begin
_oArray.Add(trim(_line));
_count := _count 1;
end;
end; // if
end; // while
if _count > 0 then
result := true;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
tmpstr : string;
A1 : Tstringlist;
begin
file_st := tstringlist.create;
A1 := tstringlist.create;
file_st.loadfromfile('c:\test.txt');
tmpstr := file_st.text;
if A_Arrays(false, A1, tmpstr,'FIELDBEGIN','FIELDEND') then begin
form1.listbox1.Clear;
Listbox1.Items.Assign(A1);
end;
end;

end.

[/code]
------
努力會更接近成功
pceyes
尊榮會員


發表:70
回覆:657
積分:1140
註冊:2003-03-13

發送簡訊給我
#3 引用回覆 回覆 發表時間:2007-12-16 17:26:34 IP:122.127.xxx.xxx 訂閱
其實個人寫delphi很少用array 或許也不會用, 但搜文有看過, tlist因要產生物件, 速度會比 array慢,
但看到這篇, 可能要改變心意了, 因為這個案子array是變動的, 請參考如下一篇:
請問如何將動態筆數的 array (自訂型態) 當參數傳送

也許用tstringlist也是不錯的想法呢!
------
努力會更接近成功
syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#4 引用回覆 回覆 發表時間:2007-12-19 10:52:52 IP:61.64.xxx.xxx 訂閱
1. 這沒什麼好奇怪的,應該是你對 Delphi 的 array 認識不夠清楚,錯誤訊息已經很清楚告訴你你犯的錯誤,個人認為將動態陣列指定給靜態陣列,是屬於「新手才會犯的錯誤」,如果是老手,看到該錯誤訊息,應該很快就可以修正與解決

2. 你在迴圈中 使用 setLength ,這樣跟 List 的 add 效能上差異不大(雖然 add 還是比較慢),但你這樣用 setlength 也沒快到哪去,最好是計算完長度,再一次 setlength 完畢,不要一直做記憶體 realloc 的動作,而只是為了新增一個記憶單位(1-4 Byte)

3. 想要傳陣列,那你應該去看 Help 內 var 與 open array ,或書上,這類的資訊,因為是你自己知識上的有所短缺,快去充電吧,這不過是基本知識 (Help 查得到的,都應該自己來)

4. 如果 List 可以達到合理的速度,使用 List 是會方便許多,如要用 array ,那自己寫的部分會比較多,要考慮是否值得花時間在「重新設計已經有現成的東西可用」上面

===================引 用 pceyes 文 章===================
其實個人寫delphi很少用array 或許也不會用, 但搜文有看過, tlist因要產生物件, 速度會比 array慢,
但看到這篇, 可能要改變心意了, 因為這個案子array是變動的, 請參考如下一篇:
請問如何將動態筆數的 array (自訂型態) 當參數傳送

也許用tstringlist也是不錯的想法呢!
編輯記錄
syntax 重新編輯於 2007-12-19 11:44:46, 註解 無‧
系統時間:2017-10-18 19:12:04
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!