📄 mybpstring.pas
字号:
Unit MyBPString;
Interface
Uses SyncObjs;
(**********************************************************************
用例:
procedure TForm1.Button1Click(Sender: TObject);
var
e :TMyEnumStrAny;
begin
e.s := Edit1.Text; {字符元素串}
e.si := 1; {起始字符元素位置}
e.sLen := ord(e.s[0]); {字符元素总数}
e.pi := 1; {起始档位置}
e.pMax := StrToIntDef(Edit2.Text, 1);
if (e.pMax > SizeOf(e.p)) then exit;
ListBox1.Clear;
while MyEnumStrAny(e) do ListBox1.Items.Add(MyGetEnumStr(e));
end;
**********************************************************************)
// 列举字符串中任意字符的任意组合 ( 穷举 )
Type
TMyEnumStrAny = Packed Record {列举字符串中任意字符的任意组合的数据结构}
S: String[255]; {被列举的字符串}
sI: integer; {指向 s 中的位置}
sLen: Byte; {被列举的字符串长}
P: Array[1..32] Of Byte; {已经列举的字符在 s 中的位置}
Pi: Byte; {指向 s 中的位置}
pMax: Byte; {要列举出的字符串最大的字符个数}
End;
{ 返回: 按 pMax 的长, 未列举完时返回 true, 否则返回 false, 每次调用列举出一个新的组合
各位字符在 TMyEnumStrAny.s 中的位置存放在 TMyEnumStrAny.p 中, 按 s[p[i]]取出
各位字符.
备注: 此函数采用算盘加法原理(满档进一)来处理的.
}
Function MyEnumStrAny(Var e: TMyEnumStrAny): Boolean;
Function MyGetEnumStr(Var e: TMyEnumStrAny): String;
Implementation
Var
mCS: TCriticalSection; {设置临界处理对象, 防止共享数据时的冲突}
Function MyEnumStrAny(Var e: TMyEnumStrAny): Boolean;
Var
I, P: Byte;
Begin
mCS.Enter;
Result := true; {注释用算盘加法原理来描述}
If (e.sI <= e.sLen) Then
Begin {如果未满档时}
e.P[e.Pi] := e.sI; {原档位上一珠}
inc(e.sI); {下一粒珠的位置}
mCS.Leave;
Exit; {返回}
End; {如果是满档叶}
e.sI := 1; {第一粒珠位置}
For I := 1 To e.Pi Do
Begin
P := e.P[I];
If (P < e.sLen) Then
Break; {查已使用了的档是否有未满档的}
End;
If (I > e.Pi) And (e.Pi = e.pMax) Then
Begin {如果已使用了的档是全满档时}
Result := false; {并且档数已经达到要求时, 说明所有列举已经完成}
mCS.Leave;
Exit;
End;
For I := e.Pi Downto 2 Do
Begin {满档进一处理}
P := e.P[I];
If (P < e.sLen) Then
Break; {如果要处理的当前档未满档时不处理}
P := e.P[I - 1];
If (P = e.sLen) Then
Break; {如果要处理的当前档的前一档已满档时不处理}
e.P[I] := 1; {否则当前档为第一粒珠}
e.P[I - 1] := e.P[I - 1] + 1; {前一档加多一粒珠}
End;
For I := 1 To e.Pi Do
Begin
P := e.P[I];
If (P < e.sLen) Then
Break; {档数未达到要求时 查已使用了的档是否有未满档的}
End;
If (I > e.Pi) Then
Begin {如果已使用了的档是全满档时}
inc(e.Pi); {增加一新档位, 已使用了的档全满档进位处理}
For I := 1 To e.Pi Do
{if e.Pi-1=i then }
e.P[I] := 1; {都上第一粒珠}
End;
inc(e.sI); {下一粒珠的位置}
mCS.Leave;
End;
(**********************************************************************
取调用 MyEnumStrAny 后列举出的字符串
**********************************************************************)
Function MyGetEnumStr(Var e: TMyEnumStrAny): String;
Var
I: Byte;
Begin
mCS.Enter;
Result := '';
For I := 1 To e.Pi Do
Result := Result + e.S[e.P[I]];
mCS.Leave;
End;
{装入时初始化}
Initialization
mCS := TCriticalSection.Create;
{关闭时}
Finalization
mCS.Free;
End.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -