最近在使用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
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