变量的问题,德尔福范围

我填一个tdictionary,从文件中读取,遍历键 - 值对。 在迭代德尔福字典迭代得到解决。

问题是,在字典中的值不被保存,可能是一个范围,问题的变量。 其分配给程序parsetextfile字典后,我比较习惯到Java ...值确实存在直接,然后迷路:

program parsefile; {$APPTYPE CONSOLE} uses SysUtils, Classes, StrUtils, Dialogs, Generics.collections; var key : string; dict: TDictionary<String, TStringlist>; KeysList, Valuename: TStringList; KeyName: string; i: integer; function DeleteSpaces(str: string): string; var i: Integer; begin i:=0; while i<=Length(str) do if str[i]=' ' then Delete(str, i, 1) else Inc(i); Result:=str; end; procedure HandleOneKey(KeyIndex:Integer; PrevKeys:string); var L:TStringList; i:Integer; Part: string; KeyName: string; begin KeyName := KeysList[KeyIndex]; L := dict[KeyName]; for i:=0 to L.Count-1 do begin writeln(L[i]); Part := KeyName + '=' + L[i]; if KeyIndex = (KeysList.Count-1) then WriteLn(PrevKeys + ' ' + Part) else HandleOneKey(KeyIndex+1, PrevKeys + ' ' + Part); end; end; procedure Split(const Delimiter: Char;Input: string;const Strings: TStrings); begin Strings.Clear; Strings.Delimiter := Delimiter; Strings.DelimitedText := Input; end; procedure parsetestfile; var testfile: Textfile; text: string; splitarray: TStringList; subsplit1, subsplit2: TStringList; begin splitarray := TStringList.Create; subsplit1:= TStringList.Create; subsplit2:= TStringList.Create; AssignFile(testfile, 'g:\testfile.txt') ; Reset(testfile); while not Eof(testfile) do begin ReadLn(testfile, text); if AnsiContainsStr(text, '=') then begin Split('=', text, splitarray); splitarray[0] := trim(splitarray[0]); splitarray[1] := DeleteSpaces(splitarray[1]); if AnsiStartsStr('data', splitarray[0]) then begin split(' ', splitarray[0], subsplit1); splitarray[0]:=subsplit1[1]; split(',', splitarray[1], subsplit2); dict.Add(splitarray[0], subsplit2); for ValueName in dict.Values do begin for i := 0 to Valuename.Count - 1 do write('Values are : '+ Valuename[i]); writeln; end;//for end;//end-data-check end;//end-=-check end;//while CloseFile(testfile); splitarray.Free; subsplit1.Free; subsplit2.Free; end; begin dict := TDictionary<String, TStringlist>.Create; parsetestfile; KeysList := TStringList.Create; for KeyName in dict.Keys do KeysList.Add(KeyName); for i := 0 to Keyslist.Count - 1 do begin writeln('Keylist Items: ' + Keyslist[i]); end; if KeysList.Count > 0 then begin HandleOneKey(0, ''); end; dict.Destroy; Keyslist.Free; WriteLn('Press ENTER to make the window go away'); ReadLn; end.

--------------解决方案-------------

顶端编辑

我现在看到你更习惯于去渣,那种解释你的问题。 Java使用的垃圾收集器:如果你有东西的参考,这一点有效的。 德尔福不使用GC,你是负责释放你分配内存。 这就引出了第二个问题:你可以释放你拿一个参考记忆,并没有什么东西这样做,阻止你。 在你parsetestfile过程中,您要添加subsplit2到字典中,所以你保持该引用的副本。 后来在你释放相同的步骤subsplit2 ,所以你的字典现在持有什么德尔福认为是“空闲内存”的参考!

随着德尔福,你需要非常仔细而审慎生命周期管理。 在这种情况下,你显然不能释放subsplit2parsetestfile过程本身,但你需要在后面释放它。 你需要,当你释放释放它Dict ,看我怎么做,最初的代码。

*推荐要求



这里是有很多东西固定代码。 请阅读评论,我插入注释的地方我改变了一些东西。

它编译和价值观生存的解析过程,但我不知道你想达到什么,你忘了提供一个示例文本文件:我不得不“做一补”。

program Project23;

{$APPTYPE CONSOLE}

uses
SysUtils, Classes, StrUtils, Dialogs, Generics.collections;

var deviceid, key, topmodule : string;
dict: TDictionary<String, TStringlist>;
KeysList: TStringList;
KeyName: string;
i: integer;

function DeleteSpaces(str: string): string;
var
i: Integer;
begin
i:=0;
while i<=Length(str) do
if str[i]=' ' then Delete(str, i, 1)
else Inc(i);
Result:=str;
end;

procedure HandleOneKey(KeyIndex:Integer; PrevKeys:string);
var L:TStringList;
i:Integer;
Part: string;
KeyName: string;
begin
KeyName := KeysList[KeyIndex];
L := dict[KeyName];
for i:=0 to L.Count-1 do
begin
writeln(L[i]);
Part := KeyName + '=' + L[i];
if KeyIndex = (KeysList.Count-1) then
WriteLn(PrevKeys + ' ' + Part)
else
HandleOneKey(KeyIndex+1, PrevKeys + ' ' + Part);
end;
end;

procedure Split(const Delimiter: Char;Input: string;const Strings: TStrings);
begin
Strings.Clear;
Strings.Delimiter := Delimiter;
Strings.DelimitedText := Input;
end;

procedure parsetestfile;
var testfile: Textfile;
text: string;
splitarray: TStringList;
subsplit1, subsplit2: TStringList;
ValueName:TStringList; // Never Ever ignore compiler warnings!
i: Integer; // Never Ever ignore compiler warnings!
begin
splitarray := TStringList.Create;
subsplit1:= TStringList.Create;
AssignFile(testfile, 'c:\temp\testfile.txt') ;
Reset(testfile);

while not Eof(testfile) do
begin
ReadLn(testfile, text);
if AnsiContainsStr(text, '=') then
begin
Split('=', text, splitarray);
splitarray[0] := trim(splitarray[0]);
splitarray[1] := DeleteSpaces(splitarray[1]);
if AnsiStartsStr('data', splitarray[0]) then
begin

subsplit2:= TStringList.Create; // Moved the creation of subsplit2 over here, because you need one fresh list for every line of text you read.

split(' ', splitarray[0], subsplit1); // can't split on SPACE because the previous split allready broke the text at "=" and at SPACE. That's how DelimitedText works!
// splitarray[0]:=subsplit1[1]; // splitarray[0] already contains the stuff before "="; And you should check the nubmer of lines in subsplit1!
split(',', splitarray[1], subsplit2);
dict.Add(splitarray[0], subsplit2);
for ValueName in dict.Values do
begin
for i := 0 to Valuename.Count - 1 do
writeLN('Values are : '+ Valuename[i]); // Only use Write when you intend to write the line terminator later
writeln;
end;//for
end;//end-data-check
end;//end-=-check
end;//while
CloseFile(testfile);
splitarray.Free;
subsplit1.Free;
// subsplit2.Free; // Ooops! You're freeing Subsplit2, after you added it as a value in the dict.
end;

begin
dict := TDictionary<String, TStringlist>.Create;
parsetestfile;
KeysList := TStringList.Create;

for KeyName in dict.Keys do
KeysList.Add(KeyName);
for i := 0 to Keyslist.Count - 1 do
begin
writeln('Keylist Items: ' + Keyslist[i]);
end;
if KeysList.Count > 0 then
begin
HandleOneKey(0, '');
end;
dict.Free; // dict.Destroy; // never call "Destroy" directly, call .Free.
Keyslist.Free;
WriteLn('Press ENTER to make the window go away');
ReadLn;
end.

分类:德尔福 时间:2015-03-15 人气:4
分享到:

相关文章

Copyright (C) 55228885.com, All Rights Reserved.

55228885 版权所有 京ICP备15002868号

processed in 0.396 (s). 10 q(s)