【问题标题】:Stringlist with delimiter as a string?将分隔符作为字符串的字符串列表?
【发布时间】:2011-03-18 21:35:42
【问题描述】:

我在存储为字符串的对象中有一个名为 HistoryText 的属性。 我想在网格中显示所有行。我应该能够删除和编辑网格中的行。 格式为:

16.5.2003-$-12:09-$-anna-$-Organization created
2.6.2005-$-13:03-$-jimmy-$-Organization edited
19.12.2005-$-13:33-$-madeleine-$-Organization edited

所以每行有 4 个字段,日期、时间、用户和消息,分隔符字符串为“-$-”。 作为分隔符是字符串而不是字符,它不能分配给 stringlists delimiter 属性。

我有一个将字符串提取到 Stringlist 的例程:

procedure ParseDelimited(const aStringList: TStringList; const aOrgList, aDelimiter: string);
var
   vDelimiterPos : integer;
   vPartialStr : string;
   vRemaingTxt : string;
   vDelimiterLength : integer;
begin
   vDelimiterLength := Length(aDelimiter);

   if (AnsiRightStr(aOrgList, Length(aDelimiter)) = aDelimiter) then
     vRemaingTxt := aOrgList
   else
     vRemaingTxt := aOrgList + aDelimiter;

   aStringList.BeginUpdate;
   aStringList.Clear;
   try
     while Length(vRemaingTxt) > 0 do
     begin
       vDelimiterPos := Pos(aDelimiter, vRemaingTxt);
       vPartialStr := Copy(vRemaingTxt,0,vDelimiterPos-1);
       aStringList.Add(vPartialStr);
       vRemaingTxt := Copy(vRemaingTxt,vDelimiterPos+vDelimiterLength,MaxInt);
     end;
   finally
     aStringList.EndUpdate;
   end;
end;

它似乎工作正常。我的问题是将 StringList 中的更改同步回原始 String 属性?这个分隔符有很多历史数据,所以我认为将其更改为 TChar 不是一个现实的选择。

更新: 一个澄清。我想我可以设法使用上面的方法将 String 转换为 StringList 。然后在网格中显示它应该不会那么难。当我想将 TStringList 转换回原始的 String 属性时,问题就出现了,以 '-$-' 作为分隔符。例如,我不能做 HistoryText := myStringList.Delimitedtext。

第二次更新: 我已经解决了。你们都得到了 +1 的快速答案,并且真的很想提供帮助。总结一下我是怎么做到的。

从历史文本中读取:

MyStringList.Text := Historytext;

现在每行都有 3 个 '-$-' 分隔符,并且每行像往常一样由换行符分隔。

  • 在循环中解析字符串列表并将其显示在网格中。我不再为 MyStringList 烦恼了。
  • 让用户删除和编辑网格中的行。
  • 完成后在网格中逐行逐列循环并构建一个与原始格式相同的新字符串。
  • 将该字符串分配给 HistoryText。

所以将焦点从 StringList 转移到网格上会更容易:)

【问题讨论】:

  • 您的实际问题是什么?您提到想要在网格中显示,并且 stringlist 过程“似乎工作正常”。 “将更改同步回来”也有点宽泛。你需要什么?
  • 我的解决方案确实适用(在 D2007+ 中)双向 - 而且更短。
  • 请注意,更优雅的方式是使用 pos 和 strutils posex,并取消所有的 copy()ing

标签: delphi delphi-2007 tstringlist


【解决方案1】:

在黑暗中野刺(不是很清楚你在问什么):

遍历网格行:

  • 对于每一行:
    • 将空字符串分配给临时字符串 var
    • 为每一列添加行/列值加上您的分隔符到临时字符串 var
    • 从临时字符串 var 中删除最后一个分隔符(如果它非空)
    • 将临时字符串变量添加到字符串列表
  • 将字符串列表的文本属性写回您的 HistoryText

const
  Delimiter = '-$-';
var
  row: Integer;
  col: Integer;
  SL: TStringList;
  rowString: string;
begin
  SL := TStringList.Create;
  try
    for row := 0 to StringGrid1.RowCount - 1 do begin
      rowString := '';
      for col := 0 to StringGrid1.ColCount - 1 do begin
        rowString := StringGrid1.Cells[col, row] + Delimiter;
      end;
      if rowString <> '' then begin
        rowString := Copy(rowString, 1, Length(rowString) - Length(Delimiter));
      end;
      SL.Add(rowString);
    end;
    HistoryText := SL.Text;
  finally
    SL.Free;
  end;
end;

使用Uwe解决TStrings的LineBreak属性:

var
  row: Integer;
  col: Integer;
  SLRows: TStringList;
  SLCols: TStringlist;
begin
  SLRows := TStringList.Create;
  try
    SLCols := TStringList.Create;
    try
      SLCols.LineBreak := '-$-';
      for row := 0 to StringGrid1.RowCount - 1 do begin
        SLCols.Clear;
        for col := 0 to StringGrid1.ColCount - 1 do begin
          SLCols.Add(StringGrid1.Cells[col, row]);
        end;
        SLRows.Add(SLCols.Text);
      end;
      HistoryText := SLRows.Text;
    finally
      SLCols.Free;
    end;
  finally
    SLRows.Free;
  end;
end;

【讨论】:

    【解决方案2】:

    除了 Delimiter(一个字符)和 DelimitedText,您还可以使用 LineBreak(一个字符串)和 Text:

    lst := TStringList.Create;
    try
      lst.LineBreak := '-$-';
      lst.Text := '16.5.2003-$-12:09-$-anna-$-Organization created';
      Memo1.Lines := lst;  // or whatever you do with it
    finally
      lst.Free;
    end;
    

    Ans 它甚至可以反过来工作。

    【讨论】:

    • 嘿,这很好。你知道什么时候引入的(哪个 Delphi 版本)?
    • 对不起,我不明白。字符串属性中的每一行都以回车符 + 换行符分隔。所以真正的字符串是: 16.5.2003-$-12:09-$-anna-$-Organization created#D#A 2.6.2005-$-13:03-$-jimmy-$-Organization modified#D#A 19.12.2005-$-13:33-$-madeleine-$-组织编辑#D#A lst := TStringList.Create;试试 lst.LineBreak := '-$-'; lst.Text := myObject.HistoryText // 例如最终使用网格中的列表 lst.Free;结尾;这是你的意思吗?
    • @Uwe, @Marjan:TStrings.LineBreak 属性是在 Delphi 2006 中引入的。
    • 是的,所以就像我的回答一样,或者使用 2 个字符串列表。您首先将 HistoryText 分配给第一个,然后处理该字符串列表中的所有项目。将第一个字符串列表中的每个字符串分配给第二个字符串列表的文本。这应该将其 linebreak 属性设置为 '-$-' 以拆分字段中的每一行。然后每个字段应该是第二个字符串列表中的一个项目。要返回 HistoryText,您可以反过来执行相同的操作:将每个 col 值添加到第二个字符串列表,然后将其整个文本添加到第一个,清除第二个,冲洗并重复每一行。
    • 在我的答案中添加了一个使用两个字符串列表的示例。
    猜你喜欢
    • 2010-10-19
    • 1970-01-01
    • 2015-12-28
    • 2020-05-31
    • 1970-01-01
    • 1970-01-01
    • 2019-04-16
    • 2014-06-29
    • 1970-01-01
    相关资源
    最近更新 更多