简体   繁体   English

如何遍历定界字符串并将字符串内容分配给本地delphi变量?

[英]How can I loop through a delimited string and assign the contents of the string to local delphi variables?

I have written a Delphi function that loads data from a .dat file into a string list. 我已经编写了一个Delphi函数,该函数将.dat文件中的数据加载到字符串列表中。 It then decodes the string list and assigns to a string variable. 然后,它解码字符串列表并分配给字符串变量。 The contents of the string use the '#' symbol as a separator. 字符串的内容使用“#”符号作为分隔符。

How can I then take the contents of this string and then assign its contents to local variables? 然后,如何获取该字符串的内容,然后将其内容分配给局部变量?

// 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;

After its been decoded the var "Line" contains something that looks like this: 解码后,变量“ Line”包含如下内容:

example: 例:

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

Not all of the values between the separators are the same length and the value of "Line" will vary each time the function LoadFromFile is called (eg sometimes a value may have only one number the next two or three etc so I cannot rely on the Copy function for strings or arrays). 并非所有分隔符之间的值都具有相同的长度,并且每次调用LoadFromFile函数时,“ Line”的值都会变化(例如,有时一个值在接下来的两个或三个中可能只有一个数字,所以我不能依靠字符串或数组的复制功能)。

I'm trying to figure out a way of looping through the contents of "Line", assigning it to a local variable called "buffer" and then if it encounters a '#' it then assigns the value of buffer to a local variable, re-initialises buffer to ''; 我试图找出一种循环遍历“行”内容,将其分配给名为“缓冲区”的局部变量的方法,然后如果遇到“#”,则会将缓冲区的值分配给局部变量,将缓冲区重新初始化为“”; and then moves onto the next value in "Line" repeating the process for the next parameter ignoring the '#' each time. 然后移到“行”中的下一个值,每次对下一个参数重复该过程,而忽略“#”。

I think I have been scratching around with this problem for too long now and I cannot seem to make any progress and need a break from it. 我认为我已经很久没有解决这个问题了,我似乎无法取得任何进展,需要有所突破。 If anyone would care to have a look, I would welcome any suggestions on how this might be achieved. 如果有人愿意看一看,我欢迎任何有关如何实现的建议。

Many Thanks 非常感谢

KD KD

You need a second TStringList: 您需要第二个TStringList:

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

Depending on your Delphi version you can set lineLst.StrictDelimiter := true in case the line contains spaces. 如果行包含空格,则可以根据您的Delphi版本设置lineLst.StrictDelimiter := true

You can do something like this: 您可以执行以下操作:

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.

You did not tag your Delphi version, so i don't know if it applies or not. 您没有标记您的Delphi版本,所以我不知道它是否适用。 That IS version-specific. 这是特定于版本的。 Please do! 请做!

In order of my personal preference: 为了我个人的喜好:

1: Download Jedi CodeLib - http://jcl.sf.net . 1:下载Jedi CodeLib- http ://jcl.sf.net。 Then use TJclStringList. 然后使用TJclStringList。 It has very nice split method. 它有很好的拆分方法。 After that you would only have to iterate through. 之后,您只需要遍历即可。

function Split(const AText, ASeparator: string; AClearBeforeAdd: Boolean = True): IJclStringList; 函数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 now has somewhat less featured StringSplit routine. 2:Delphi现在具有功能较弱的StringSplit例程。 http://docwiki.embarcadero.com/Libraries/en/System.StrUtils.SplitString It has a misfeature that array of string type may be not assignment-compatible to itself. http://docwiki.embarcadero.com/Libraries/zh-CN/System.StrUtils.SplitString它具有一个缺点,即字符串类型的数组可能与其自身不兼容。 Hello, 1949 Pascal rules... 您好,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: Use TStringList. 3:使用TStringList。 The main problem with it is that it was designed that spaces or new lines are built-in separators. 它的主要问题是,其设计是空格或换行符是内置的分隔符。 In newer Delphi that can be suppressed. 在较新的Delphi中可以将其抑制。 Overall the code should be tailored to your exact Delphi version. 总体而言,代码应适合您的确切Delphi版本。 You can easily Google for something like "Using TStringlist for splitting string" and get a load of examples (like @Uwe's one). 您可以轻松地在Google上查找诸如“使用TStringlist拆分字符串”之类的内容,并获取大量示例(例如@Uwe的示例)。

But you may forget to suppress here or there. 但是您可能会忘记在这里或那里进行抑制。 And you may be on old Delphi,, where that can not be done. 您可能在旧的Delphi上,而那是无法做到的。 And you may mis-apply example for different Delphi version. 您可能会误将示例用于其他Delphi版本。 And... it is just boring :-) Though you can make your own function to generate such pre-tuned stringlists for you and carefully check Delphi version in it :-) But then You would have to carefully free that object after use. 而且...这很无聊:-)尽管您可以创建自己的函数来为您生成这种预先调整的字符串列表,并仔细检查其中的Delphi版本:-)但是,在使用后,您必须仔细释放该对象。

I use a function I've written called Fetch . 我使用我编写的名为Fetch的函数。 I think I stole the idea from the Indy library some time ago: 我想我前一段时间从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;

Then I'd call it like this: 然后我会这样称呼它:

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;

Note: this was typed into the browser, so I haven't checked it works. 注意:这是在浏览器中输入的,因此我没有检查它是否有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM