zoukankan      html  css  js  c++  java
  • delphi 拆分字符串

    最近在使用Delphi开发一种应用系统的集成开发环境。其中需要实现一个字符串拆分功能,方法基本原型应该是:
    procedure SplitString(src: string ; ch: Char; var stringList: TStringList);
    目的是使用字符ch拆分src字符串,把拆分的结果放入stringList中。例如:src:='abc|def|ghi'; ch='|'的时候,返回的stringList应该是{abc, def, ghi}。
    开始的时候,我是使用获取ch在src中出现的位置,然后使用StrUtils单元提供的RightStr方法来分割字符串,并将结果保存在stringList中的。程序如下:
    procedure SplitString(src: string ; ch: Char; var stringList: TStringList);
    var  
     p: Integer;
     s: string ;
    begin 
     try 
      stringList.Clear;
            s := src;
            repeat 
             p := Pos(ch, s);
                if p = 0 then begin 
                 stringList.Add(s);
                    Break;
                end ;
                stringList.Add(LeftStr(s, p - 1));
                s := RightStr(s, Length(s) - p);
            until False;
        except 
         raise ;
        end ;
    end ;
    遗憾的是,上面的程序对于src中所有字符都是半角字符(英文、数字、标点等)的字符串,运行起来完全没有问题,而如果src中含有中文,问题就比较大了;Length方法可以正确地取得字符串的长度,而LeftStr和RightStr则不能正确地截取字符串。
    一个比较合理的替代方法是:遍历src中的所有字符,如果当前字符不是ch,则把ch加到临时字符串tmpstr中,否则将tmpstr加入stringList并将tmpstr赋值为空字符串。这样做可以避开对中文字符的处理。程序如下:
    procedure TXNetDevEnvHelper.SplitString(src: string ; ch: Char; var  stringList: TStringList);
    var  
        i: Integer;
     tmp : string ;
    begin 
     stringList.Clear;
        tmp := '';
        for i := 1 to Length(src) do begin 
         if src[i] <> ch then begin 
             tmp := tmp + src[i];
            end else begin 
             stringList.Add(tmp);
                tmp := '';
            end ;
        end ;
        stringList.Add(tmp);
    end ;

    开始的时候也是使用上一种方法,在拆解包含有中文的字符串时,确实出现问题,改用了下一种方法。顺便查找了下StringList拆解字符串的方法,使用该方法将使字符串的拆解更简单,具体方法如下:

    =======================================

    常规的用法大家都知道,现在来讨论它的一些高级的用法。
    先把要讨论的几个属性列出来:
    1、CommaText
    2、Delimiter & DelimitedText
    3、Names & Values & ValueFromIndex

    先看第一个:CommaText。怎么用呢?用代码说话:
    const
       constr :String = 'aaa,bbb,ccc,ddd';
    var
       strs :TStrings;
       i :Integer;
    begin
       strs := TStringList.Create;
       strs.CommaText := constr;
       for i := 0 to Strs.Count-1 do
         ShowMessage(Strs[i]);
    end;
    执行了这段代码后,可以看到ShowMessage显示出来的分别是:aaa bbb ccc ddd。
    也就是说,strs.CommaText := constr这一句的作用,就是把一个字符串以','为分割符,分段添加到TStrings中。
    那么如果不是以','来分割,又该怎么做呢?现在看第二个例子。使用Delimiter和DelimitedText。
    const
       constr :String = 'aaa/bbb/ccc/ddd';
    var
       strs :TStrings;
       i :Integer;
    begin
       strs := TStringList.Create;
       strs.Delimiter := '/';
       strs.DelimitedText := constr;
       for i := 0 to Strs.Count-1 do
         ShowMessage(Strs[i]);
    end;
    可以看到, 显示的效果和第一个例子是一模一样的。解释一下:
    Delimiter为分隔符,默认为:','。DelimitedText就是按Delimiter为分隔符的一个串,得到赋值后回把这个字符串按Delimiter的字符添加到TStrings中。
    说到这里,有想起一个属性,QuoteChar。其默认值为:'"'(不包括单引号)
    有何用呢?看例子:
    const
       constr :String = '"aaa"/"bbb"/"ccc"/"ddd"';
    var
       strs :TStrings;
       i :Integer;
    begin
       strs := TStringList.Create;
       strs.Delimiter := '/';
       strs.DelimitedText := constr;
       for i := 0 to Strs.Count-1 do
         ShowMessage(Strs[i]);
    end;
    显示出来的仍然是aaa bbb ccc ddd。为什么不是:"aaa" "bbb" "ccc" "ddd"呢?
    再来看一个例子:
    const
       constr :String = '|aaa|/|bbb|/|ccc|/|ddd|';
    var
       strs :TStrings;
       i :Integer;
    begin
       strs := TStringList.Create;
       strs.Delimiter := '/';
       strs.QuoteChar := '|';
       strs.DelimitedText := constr;
       for i := 0 to Strs.Count-1 do
         ShowMessage(Strs[i]);
    end;
    显示出来的又是aaa bbb ccc ddd。对比一下,应该不难明白吧?这个就不多说了,用得也不多。
    但是还要多说一句,当Delimiter为:','而QuoteChar为:'"'时,DelimitedText和CommaText是同等的。
    最后要说的三个是:Names & Values & ValueFromIndex。
    看看下面的代码:
    const
       constr :String = '0=aaa,1=bbb,2=ccc,3=ddd';
    var
       strs :TStrings;
       i :Integer;
    begin
       strs := TStringList.Create;
       strs.CommaText := constr;
       for i := 0 to strs.Count-1 do
       begin
         ShowMessage(strs.Names[i]);
         ShowMessage(strs.Values[strs.Names[i]]);
         ShowMessage(strs.ValueFromIndex[i]);
       end;
    end;
    通过这个例子不难看出:
    这个时候strs中的内容是:
    0=aaa
    1=bbb
    2=ccc
    3=ddd
    而Names中则是:
    0
    1
    2
    3
    在Values中则是:
    aaa
    bbb
    ccc
    ddd
    ============================================
    拆解以空格作为分割符的字符串的方法:
    DelimitedText空格也默认为分割符的原因很简单: Borland的程序员把这个属性对应的write方法的一行代码写错了而已, 你找到classes文件中的
    procedure TStrings.SetDelimitedText(const Value: string);
    var
      P, P1: PChar;
      S: string;
      begin
      BeginUpdate;
      try Clear; P := PChar(Value);
        while P^ in [#1..' '] do
         {$IFDEF MSWINDOWS}
          P := CharNext(P); 
       {$ELSE}
           Inc(P);
       {$ENDIF}
        while P^ <> #0 do
       begin if P^ = QuoteChar then
         S := AnsiExtractQuotedStr(P, QuoteChar) else
          begin
         P1 := P; // while (P^ > ' ') and (P^ <> Delimiter) do while (P^ > '') and (P^ <> Delimiter) do 看到我修改的地方了吧,大家读读代码就知道那位写源代码的大侠本意也应该如此,他多加个空格而已,所以就变成一遇到空格切分了.
  • 相关阅读:
    [题解]POJ_1417_(并查集背包
    [题解]POJ_2912_(带权并查集
    [题解]luogu_P1502_窗口的星星(扫描线
    [题解/模板]POJ_1733_Pairty game(带权并查集/扩展域
    [题解/模板]悬线法luogu_P1169_棋盘制作(悬线法
    [题解]luogu_P2059_卡牌游戏(状态设计/概率dp
    [题解]luogu_P2467_地精部落(思维dp
    「CJOJ2439」军队
    「LG2397」yyy loves Maths VI (mode)
    「LG2114」起床困难综合症
  • 原文地址:https://www.cnblogs.com/yumalei/p/10150505.html
Copyright © 2011-2022 走看看