如何循环分隔字符串并将字符串的内容分配给本地delphi变量?

时间:2012-08-14 14:36:55

标签: delphi loops delphi-xe2 tstringlist

我编写了一个Delphi函数,它将.dat文件中的数据加载到字符串列表中。然后它解码字符串列表并分配给字符串变量。字符串的内容使用'#'符号作为分隔符。

如何获取此字符串的内容,然后将其内容分配给局部变量?

// Function loads data from a dat file and assigns to a String List.
function TfrmMain.LoadFromFile;
var 
  index, Count : integer;
  profileFile, DecodedString : string;
begin
  // Open a file and assign to a local variable.
  OpenDialog1.Execute;
  profileFile := OpenDialog1.FileName;
  if profileFile = '' then
    exit;
  profileList := TStringList.Create;
  profileList.LoadFromFile(profileFile);
  for index := 0 to profileList.Count - 1 do
  begin
    Line := '';
    Line := profileList[Index];
  end;
end;

在解码后,var“Line”包含如下内容:

示例:

Line '23#80#10#2#1#...255#'.

并非所有分隔符之间的值都是相同的长度,并且每次调用函数LoadFromFile时“Line”的值都会变化(例如,有时一个值可能只有一个数字,接下来的两个或三个等等所以我不能依赖于字符串或数组的复制功能。)

我试图想出一种循环“Line”内容的方法,将它分配给一个名为“buffer”的局部变量,然后如果遇到'#',则将缓冲区的值赋给a局部变量,将缓冲区重新初始化为'';然后移动到“Line”中的下一个值,重复下一个参数的过程,每次都忽略'#'。

我想我现在已经解决了这个问题太长时间了,我似乎无法取得任何进展,需要休息一下。如果有人愿意看一看,我会欢迎任何关于如何实现这一目标的建议。

非常感谢

KD

4 个答案:

答案 0 :(得分:7)

您需要第二个TStringList:

  lineLst := TStringList.Create;
  try
    lineLst.Delimiter := '#';
    lineLst.DelimitedText := Line;
    ...
  finally
    lineLst.Free;
  end;

根据您的Delphi版本,您可以设置lineLst.StrictDelimiter := true,以防该行包含空格。

答案 1 :(得分:1)

您可以这样做:

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, StrUtils;

var
  S : string;
  D : string;

begin
  S := '23#80#10#2#1#...255#';

  for D in SplitString(S,'#') do //SplitString is in the StrUtils unit
    writeln(D);

  readln;
end.

答案 2 :(得分:0)

您没有标记您的Delphi版本,所以我不知道它是否适用。 这是特定于版本的。请做!

根据个人喜好:

1:下载Jedi CodeLib - http://jcl.sf.net。然后使用TJclStringList。它有非常好的分割方法。之后你只需要迭代。

function Split(const AText,ASeparator:string; AClearBeforeAdd:Boolean = True):IJclStringList;

uses JclStringLists;
...
var s: string;  js: IJclStringList.
begin
...
   js := TJclStringList.Create().Split(input, '#', True);
   for s in js do begin
      .....
   end;
...
end;

2:Delphi现在具有较少的特色StringSplit例程。 http://docwiki.embarcadero.com/Libraries/en/System.StrUtils.SplitString     它有一个错误,字符串类型的数组可能不与自身分配兼容。您好,1949年Pascal规则......

uses StrUtils;
...
var s: string;  
    a_s: TStringDynArray; 
(* aka array-of-string aka TArray<string>. But you have to remember this term exactly*)
begin
...
   a_s := SplitString(input, '#');
   for s in a_s do begin
      .....
   end;
...
end;

3:使用TStringList。它的主要问题是它被设计为空格或新线是内置分隔符。在较新的Delphi中可以被抑制。总的来说,代码应该根据您的精确Delphi版本进行定制。您可以轻松地使用Google进行类似&#34;使用TStringlist分割字符串&#34;并获得大量示例(例如@Uwe&#39;)。

但是你可能会忘记在这里或那里压抑。你可能在旧的德尔福,在那里无法做到。你可能会错误地应用不同的Delphi版本的例子。并且...它很无聊:-)虽然您可以自己创建函数来为您生成这样的预先调整的字符串列表并仔细检查其中的Delphi版本:-)然后您必须在使用后小心地释放该对象。

答案 3 :(得分:0)

我使用了一个名为Fetch的函数。我想我不久前从Indy图书馆偷走了这个想法:

function Fetch(var VString: string; ASeperator: string = ','): string;
var   LPos: integer;
begin
  LPos := AnsiPos(ASeperator, VString);
  if LPos > 0 then
  begin
    result := Trim(Copy(VString, 1, LPos - 1));
    VString := Copy(VString, LPos + 1, MAXINT);
  end
  else
  begin
    result := VString;
    VString := '';
  end;
end;

然后我会这样称呼它:

var
  value: string;
  line: string;
  profileFile: string;
  profileList: TStringList;
  index: integer;
begin
  if OpenDialog1.Execute then
  begin 
    profileFile := OpenDialog1.FileName;
    if (profileFile = '') or not FileExists(profileFile) then
      exit;

    profileList := TStringList.Create;
    try
      profileList.LoadFromFile(profileFile);

      for index := 0 to profileList.Count - 1 do
      begin
        line := profileList[index];
        Fetch(line, ''''); //discard "Line '"
        value := Fetch(line, '#')
        while (value <> '') and (value[1] <> '''') do //bail when we get to the quote at the end
        begin
           ProcessTheNumber(value); //do whatever you need to do with the number
           value := Fetch(line, '#');
        end;
      end;
    finally
      profileList.Free;
    end;
  end;
end;

注意:这是在浏览器中输入的,所以我没有检查它是否有效。