字符串处理问题,获取字符串中两个子串中间的内容。 ( 积分: 100 )

  • 主题发起人 主题发起人 zdwlp
  • 开始时间 开始时间
Z

zdwlp

Unregistered / Unconfirmed
GUEST, unregistred user!
问题如下:
1:
s,s1,s2:string;
s1:='123';
s2:='123';
memo1.text:='123*123abcabdabeabcabc*123123';
现在要获得s:=一个处理方法,s的值为'*123abcabdabeabcabc*123'
也就是说,获得一个字符串中两点之间的内容,注意,这开始和结束两个点在memo1.text里不是唯一的。
 
问题如下:
1:
s,s1,s2:string;
s1:='123';
s2:='123';
memo1.text:='123*123abcabdabeabcabc*123123';
现在要获得s:=一个处理方法,s的值为'*123abcabdabeabcabc*123'
也就是说,获得一个字符串中两点之间的内容,注意,这开始和结束两个点在memo1.text里不是唯一的。
 
这个点有可能和其它不想要点重复,,,,是吗?
能不能再描述下你想要点的定义,,,就是说你到底想要怎么取你的内容,,,如上面的代码没什么一定的定义区间!
 
1、正则表达式
2、
s := StringReplace('123*123abcabdabeabcabc*123123', '*123', #13, [rfReplaceAll]);
Memo1.Lines.CommaText := s;
 
meet兄,你的理解是正确的,比如abcde每个字符代表一个字符串,那么a/b/d/e可能是相等的,而我要得出的值是bcd或者bc或者cd
 
xianguo兄,你给出的2是我一直用的方法,但是如果没有中间的*的话,或者说该字符串更加复杂且无规律,比如一篇N多字的文章,就很难了,而且没有通用性。
您所说的1正则表达式我今天想到了,可惜没接触过这方面的东东,可否指点一二?
恳请赐教!
 
或者这样说,一篇文章里面,有100个互不相临的'abc',我怎样取出任意两个'abc'之间的字符串?
比如第10个和第68个之间
 
判断memo1.text:='123*123abcabdabeabcabc*123123';中的*位置,然后语句*的开始和结束位置生成字符串*123abcabdabeabcabc*
 
关键不在这里,如果没有第一个*呢?
 
这是一个通用点的算法,用这个函数可以返回在源字符串(S)里面,位于开始子串(StarStr)和结束子串(EndStr)中间的一个子串。
因为是在网吧写的,没有条件测试,就简单地写个只能获取第一个中间子串的算法先吧。
function getmidstr(S,StarStr,EndStr:string):string;
var
i,LenS,LenStarStr,LenEndStr:integer;
midstr:string;
geted:boolean;
begin
if S<>'' then
begin
LenS:=Length(S);
LenStarStr:=Length(StarStr);
LenEndStr:=Length(EndStr);
midstr:='';
i:=1;
geted:=false;
While (i<=LenS) and not geted then
if S='*' then
begin
if midstr='' then
begin
if Copy(S,i+1,LenStarStr)=StarStr then
begin
midstr:='*'+StarStr;
i:=i+LenStarStr;
end
else
i:=i+1
end
else
if Copy(S,i+1,LenEndStr)=EndStr then
begin
midstr:='*'+EndStr;
geted:=true
end
else
midstr:=''
end
else
begin
if midstr<>'' then
midstr:=midstr+S;
i:=i+1
end;
Result:=midstr
end
else
Result:=''
end;
 
试了很久还是有问题:供你参考一下吧!
Var
myExpr: TRegExpr;
begin
myExpr := TRegExpr.Create;
myExpr.Expression := '"(.*123?)"';
try
if myExpr.Exec('"123*123abcabdabeabcabc*123123"') then
repeat
ListBox1.Items.Add(myExpr.Match[1]);
until not MyExpr.ExecNext;
finally
myExpr.Free;
end;
 
呵呵,yf_zq兄的答案是我期待的,但是我在实施的时候也遇到问题,就是前、后两个点都是重复的,所以正则表达式实现起来依然有难度(我昨天才开始了解了一点正则表达式,不是很懂)
正则表达式用来进行模糊字符串匹配,但是跟我之前的算法一样,都需要有一个或者几个“唯一”的字符串作为“点”来定位,如果这样的话,我觉得如果可以直接定位到“点”的计数,比如第3次“123”出现的地方,就ok了。
所以我觉得问题的关键在于,是怎样定位到具体的前边和后边的“点”的计数
 
干脆换个思路,一段字符串为“123123123123123123123123”
有没有函数可以一次定位到第N个123?
或者谁能写出这样的函数/方法?
 
//来自:zdwlp, 时间:2005-5-19 22:15:00, ID:3078869
//或者这样说..比如第10个和第68个之间
posex难道不能解决吗?
function FindSubStrEx(srcStr: string; subStr: string; subID: Ineger = 1; startIndex: DWORD= 1): Integer;
//startIndex和srcStr联合决定了从哪里开始查找.其实如果使用PChar则更明了和简单
//subID:从当前的位置查找第几个subStr 0->第一个
//结果:索引,0表示没有找到
var
iSubLen: Integer;
iPos: Integer;
iCount: Integer;
begin
Result:= 0;
iSubLen:= Length(subStr);
iPos:= startIndex;
for iCount:=0 to subID do
begin
iPos:= PosEx(subStr, srcStr, iPos);
if iPos<1 then
exit;
Inc(iPos, iSubLen);
end;
Result:= iPos - iSubLen;
end;
 
在CSDN上找到了一个超快的函数:
//function QuickPos(const Substr, S: WideString; MatchesIndex: Integer = 1): Integer;
//function QuickPosBack(const Substr, S: WideString; MatchesReverseIndex: Integer = 1): Integer;

function _InlineCompareText(const Substr, S: WideString; StartIndex: Integer = 1; LenOfSubstr: Integer = -1; LenOfS: Integer = -1): Boolean;
var
I: Integer;
begin
if LenOfSubstr = -1 then LenOfSubstr := Length(Substr);
if LenOfS = -1 then LenOfS := Length(S);
if LenOfSubstr > LenOfS then
begin
Result := False;
Exit;
end;
for I := 1 to LenOfSubstr do
if Substr <> S[I + StartIndex - 1] then
begin
Result := False;
Exit;
end;
Result := True;
end;

// Returns the 1. index of a substring within a string start at a certain index.
// C: 2004-07-05 | M: 2004-07-05 | P: 1.0+
function _PosForward(const Substr, S: WideString; StartIndex: Integer; LenOfSubstr: Integer = -1; LenOfS: Integer = -1): Integer;
var
I: Integer;
begin
Result := 0;
case LenOfSubstr of
0: Exit;
-1: LenOfSubstr := Length(Substr);
end;
if LenOfS = -1 then LenOfS := Length(S);

for I := StartIndex to LenOfS do
begin
if (S = Substr[1]) and _InlineCompareText(Substr, S, I, LenOfSubstr, LenOfS) then
begin
Result := I;
Exit;
end;
end;
end;

// Returns the 1. index of a substring within a string.
// Note: Searching time will increase when MatchesIndex increased.
// C: 2004-04-09 | M: 2004-07-05 | P: 1.0+
function QuickPos(const Substr, S: WideString; MatchesIndex: Integer = 1): Integer;
var
LenOfS, LenOfSubstr: Integer;
begin
Result := Pos {Pos}(Substr, S);

if (MatchesIndex = 1) or (Result = 0) then Exit;
LenOfS := Length(S);
LenOfSubstr := Length(Substr);

while (MatchesIndex > 1) and (Result > 0) do
begin
Result := _PosForward {Pos}(Substr, S, Result + 1, LenOfSubstr, LenOfS); // Tip!! Do not use func.Copy!!
if Result = 0 then Exit;
Dec(MatchesIndex);
end;
end;

// Returns the last index of a substring within a string.
// Todo: Using asm to rewrite this function. The asm-code looks very like func.Pos!
// C: 2004-04-09 | M: 2004-07-03 | P: n/a
function _PosBack(const Substr, S: WideString; StopIndex: Integer = -1; LenOfSubstr: Integer = -1): Integer;
var
I: Integer;
begin
Result := 0;
case LenOfSubstr of
0: Exit;
-1: LenOfSubstr := Length(Substr);
end;
if StopIndex = -1 then StopIndex := Length(S);

for I := StopIndex - LenOfSubstr + 1 downto 1 do
begin
if (S = Substr[1]) and _InlineCompareText(Substr, S, I, LenOfSubstr) then
begin
Result := I;
Exit;
end;
end;
end;

// Returns the last index of a substring within a string.
// C: 2004-04-09 | M: 2004-07-03 | P: n/a
function QuickPosBack(const Substr, S: WideString; MatchesReverseIndex: Integer = 1): Integer;
var
LenOfSubstr: Integer;
begin
Result := _PosBack {Pos}(Substr, S);

if (MatchesReverseIndex = 1) or (Result = 0) then Exit;
LenOfSubstr := Length(Substr);

while (MatchesReverseIndex > 1) and (Result > 0) do
begin
Result := _PosBack {Pos}(Substr, S, Result + LenOfSubstr - 2, LenOfSubstr);
Dec(MatchesReverseIndex);
end;
end;

我用quickpos取出的值是正确的,但是用
ShowMessage(Copy(Memo1.Text, QuickPos(Edit1.Text, Memo1.Text, SpinEdit3.IntValue) + Length(Edit1.Text), QuickPos(Edit1.Text, Memo1.Text, SpinEdit4.IntValue) - QuickPos(Edit1.Text, Memo1.Text, SpinEdit3.IntValue)))
取出字符串却错误,何解?
 
终于搞定了,放出来大家分享一下吧,自己摸索的,和zjan521兄给出的如出一辙
//在串中查找第i个子串的位置 正确
/////////////////////////////////////////////////////////////////
function iPosEx(N: Integer; SubString, AString: string): Integer;
var
p: Integer;
nSub: Integer;
begin
nSub := Length(SubString);
Result := 0;
p := 0;
while N > 0 do
begin
p := PosEx(SubString, AString, p + 1);
if p = 0 then
Break;
Dec(N);
Result := p;
Inc(p, nSub);
end;
if N > 0 then
Result := -1;
end;
 
后退
顶部