将用分号分隔的字符串分解,如果字符串本身中包含;号则用@;来代替
如果本身包含@则用两个@@来代替}功能基本实现了,但大家看有没有什么优化的方式,
不怕代码难懂,只要优化提高,只要能实现这功能就行procedure ExtractFieldName(const Fields: string; var AStrList:TStringList);overload;
var
  i,L:Integer;
  AEsc:Integer; //转义字符的位置
  S:String;
begin
  L:=length(Fields);
  AEsc:=0;
  for i:=1 to L do
  begin
    if Fields[i]='@' then //要检查下一个字符,如果还是@则是字符串中本身包含@ //如果是;则是一个;
    begin
      if AEsc >0 then //说明上一个也是转义字符替换成一个
      begin
        S:=S+Fields[i];
        AEsc:=0
      end
      else
        AEsc:=i;
    end
    else
    if Fields[i]=';' then
    begin
      if AEsc>0 then  //上一个是@说明;否则是;
      begin
        S:=S+Fields[i];
        AEsc:=0;
      end //是结束
      else
      begin
        AStrList .Add(S);
        S:='';
      end;
    end
    else
      S:=S+Fields[i];
    if i=L
      AStrList .Add(S);
  end;
end;

解决方案 »

  1.   

    刚才提交的有个BUG ,如果最一个是@的话就会丢失。
    刚才提交的效果如下:
    字符串:A@@B;CD@;@@;123;@  
    结果
     A@B 
     CD;@
     123
    {最后一个@丢失了}将上一个修改了一下,不需要用@@来表示@
    效果如下
    字符串:A@@B;CD@;@@;123;@  
    结果
      A@@B
      CD;@;123
      @
    即将字符串中的 @; 解释成 ;注意:上面例子中的 ; 是英文中的分号。
    ----------------------------------------
    procedure ExtractFieldName(const Fields: string; var AStrList:TStringList);overload;
    var
      i,L:Integer;
      AEsc1,AEsc2:Integer; //转义字符
      S:String;
    begin
    {将给定的字符串分解,字符串之间用;号隔开,
    如果字符串本身中包含;号则用@;来代替}
      L:=length(Fields);
      AEsc1:=0;
      AEsc2:=0;
      for i:=1 to L do
      begin
        if Fields[i]='@' then //要检查下一个字符,如果还是@则是字符串中本身包含@ //如果是;则是一个;
        begin
          if AEsc1>0 then //说明上一个也是转义字符,则要检查下一个是否是分隔字符
          begin //如果下一个不是分隔字符,则说明是两个@@ ,如下一个是分隔字符则是一个@
            if AEsc2>0 then
            begin
              S:=S+'@@';
              AEsc1:=i;
              AEsc2:=0;
            end
            else
              AEsc2:=i;
          end
          else //上一个不是转义字符
            AEsc1:=i;
        end
        else
        if Fields[i]=';' then //是一个分隔字符
        begin
          if AEsc1>0 then  //上一个是@说明;否则是;
          begin   //连续两个@后加一个; 则是表示 @;
            if AEsc2>0 then
              S:=S+'@;'
            else
              S:=S+';';
            AEsc1:=0;
            AEsc2:=0;
          end
          else
          begin
            AStrList .Add(S);
            S:='';
          end;
        end
        else
        begin
          if AEsc1 >0 then //上一个是转义字符
          begin
            S:=S+'@';
            AEsc1:=0;
          end;
          if AEsc2 >0 then
          begin
            S:=S+'@';
            AEsc2:=0;
          end;
            S:=S+Fields[i];
        end;
        if i=L then //到了最后一位
        begin
          if AEsc1>0 then
            S:=S+'@';
          if AEsc2>0 then
            S:=S+'@';
          AStrList .Add(S);
        end;
      end;
    end;
      

  2.   

    叹又发现一个,会多一个空行修正如下。
    将上面代码的最后面的代码
      if i=L then //到了最后一位
        begin
          if AEsc1>0 then
            S:=S+'@';
          if AEsc2>0 then
            S:=S+'@';
          AStrList .Add(S);
        end;换成如下代码    if i=L then //到了最后一位
        begin
          if (0<(AEsc1+AEsc2))or(S<>'')or(Fields[i]=';') then
          begin
            if AEsc1>0 then
              S:=S+'@';
            if AEsc2>0 then
              S:=S+'@';
            AStrList .Add(S);
          end;这次应在没有问题了。
      

  3.   

    感觉你的描述有问题的,加入字符窜中;后面紧接着是@,那么翻译是
    比如:原字符窜为
      ADS;@FF;DFTRET
    那么你描述的为
      ADS@@@FF;DFTRET
    怎么分呢?
      

  4.   

    ADS;@FF;DFTRET会分解成
    ADS
    @FF
    DFTRET现在这个是分解字符串的。相反的操作马上就贴。
      

  5.   

    又发现一个问题呀!看来不将一个@表达成两个是不行的。现在贴同这两个函数。
    下面这个是将给定的StringList中的字符转换成用分号;分隔的字符串
    //将原字符串中的分号替换成 @; 
    //将原字符串的@替换成@@function FieldListToStr(Const AStrList:TStrings):String;
    Const
      CO_ESCSTR='@';
      CO_SPACESTR=';';
    function QuotedStrEx(Const S:String):String;
    var
      m,n:Integer;
    begin
    {给定一个字符串,将基中的@替换成@@,分号;替换成@;}
      Result:=S;
      n:=Length(Result);
      for m:=n Downto 1 do
        if Result[m] in [CO_SPACESTR,CO_ESCSTR] then
          System.Insert(CO_ESCSTR,Result,m);
    end;
    var
      i,L:Integer;
    begin
    {将字符串列表表示成为;分隔的字符}
      L:=AStrList .Count -1;
      if L>=0 then
        Result:=QuotedStrEx(AStrList.Strings [0]);
      for i:=1 to L do
        Result:=Result+CO_SPACESTR+QuotedStrEx(AStrList.Strings [i]);
    end;----------------------------------------------下面这个是将分号分隔的字符串还原
    procedure ExtractFieldName(const Fields: string; var AStrList:TStringList);
    Const
      CO_ESCSTR='@';
      CO_SPACESTR=';';
    var
      i,L:Integer;
      AEsc:Integer; //转义字符的位置
      S:String;
    begin
      L:=length(Fields);
      AEsc:=0;
      for i:=1 to L do
      begin
        if Fields[i] in [CO_ESCSTR,CO_SPACESTR] then //要检查下一个字符,如果还是@则是字符串中本身包含@ //如果是;则是一个;
        begin
          if AEsc>0 then //说明上一个是转义字符,@总是成对或@;出现
          begin
            S:=S+Fields[i];
            AEsc:=0
          end
          else
          begin
            if Fields[i]=CO_SPACESTR then
            begin
              AStrList .Add(S);
              S:='';
            end
            else
              AEsc:=i;
          end;
        end
        else
          S:=S+Fields[i];
        //到了最后一位
        if (i=L)And((0<AEsc)or(S<>'')or(Fields[i]=CO_SPACESTR)) then
        begin
          if AEsc>0 then
            S:=S+CO_ESCSTR;
          AStrList .Add(S);
        end;
      end;
    end;-------------------------------------------------------
    以上两个函数有什么办法优化,不怕难懂,只要速度快,要支持中英文。