0

我编写了一个 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”的局部变量,然后如果遇到“#”,则将缓冲区的值分配给局部变量,将缓冲区重新初始化为'';然后移动到“Line”中的下一个值,重复下一个参数的过程,每次忽略“#”。

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

非常感谢

KD

4

4 回答 4

7

你需要第二个 TStringList:

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

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

于 2012-08-14T14:50:48.110 回答
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.
于 2012-08-14T16:45:36.983 回答
0

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

按照我个人喜好排序:

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

函数拆分(常量 AText,ASeparator:字符串;AClearBeforeAdd:布尔 = 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 年的帕斯卡规则...

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 上搜索“使用 TStringlist 拆分字符串”之类的内容并获取大量示例(例如 @Uwe 的示例)。

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

于 2012-08-14T14:52:08.893 回答
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;

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

于 2012-08-16T09:37:51.650 回答