delphi中VBspcript_TRegExp类(正则表达式)怎么用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了delphi中VBspcript_TRegExp类(正则表达式)怎么用相关的知识,希望对你有一定的参考价值。
delphi 中 VBScript.RegEx 怎么用?
参考技术A 这个vb script Regular Expression 5.5对象是IE5.5自带的,所以很方便引用。首先介绍一下这个对象 只要你的服务器安装了IE5.x,就会带VBscript5.5。其实,“正则表达式”原本是Unix下面的专利,尤其是在Perl语言中使用的最为广泛,正是由于“正则表达式”的强大功能,才使得微软慢慢将正则表达式对象移植到了视窗系统上面,利用“正则表达式”对象,我们就可以非常方便的对各种数据进行合法性的校验了。 首先,让我们来了解一下究竟什么是VBscript的“正则表达式”对象,我们先来看一段程序: Function CheckExp(patrn, strng) Dim regEx, Match 建立变量。 Set regEx = New RegExp 建立正则表达式对象 regEx.Pattern = patrn 设置模式 regEx.IgnoreCase = true 设置是否区分字符大小写。 regEx.Global = True 设置全局可用性。 Matches = regEx.test(strng) 执行搜索,matches是布尔值 CheckExp = matches End Function 在这段程序程序中,我们看到可以使用“New RegExp”来得到一个正则表达式对象,然后对这个对象进行正则匹配模板的赋值,也就是告诉正则表达式对象,你想要匹配一个什么样子的模板,然后使用方法Test来检测待处理的数据究竟和我们给出的模版是否相匹配,如果不匹配,那就表明待处理的数据不是合法的数据,从而也就实现了数据合法性的校验,我们可以看出,使用一个设计合理的匹配模板,我们可以轻松的校验一批格式类似的数据信息。 当然,VBscript5.0中的“正则表达式”对象还有很多的其他的方法和属性,比如方法Replace(),利用他我们就可以很快的实现现在网上很时髦的UBB风格的论坛以及BBS,这不在我们讨论范围之内,以后再加以论述,我们现在就看看在数据校验方面正则表达式对象常用的方法和属性: 常用方法: Execute 方法 描述:对指定的字符串执行正则表达式搜索。 语法:object.Execute(string) Execute 方法的语法包括以下几个部分: object:必需的。总是一个 RegExp 对象的名称。 string:必需的。要在其上执行正则表达式的文本字符串。 说明:正则表达式搜索的设计模式是通过 RegExp 对象的 Pattern 来设置的。Execute 方法返回一个 Matches 集合,其中包含了在 string 中找到的每一个匹配的 Match 对象。如果未找到匹配,Execute 将返回空的 Matches 集合。 Test方法 描述:对指定的字符串执行一个正则表达式搜索,并返回一个 Boolean 值指示是否找到匹配的模式。 语法:object.Test(string) Test 方法的语法包括以下几个部分: 说明:正则表达式搜索的实际模式是通过RegExp对象的Pattern属性来设置的。RegExp.Global属性对Test方法没有影响。如果找到了匹配的模式,Test方法返回True;否则返回False。 常用属性: Global属性 描述:设置或返回一个 Boolean 值,该值指明在整个搜索字符串时模式是全部匹配还是只匹配第一个。 语法:object.Global [= True | False ] object 参数总是 RegExp 对象。如果搜索应用于整个字符串,Global 属性的值为 True,否则其值为 False。默认的设置为 True。 IgnoreCase属性 描述:设置或返回一个Boolean值,指明模式搜索是否区分大小写。 语法:object.IgnoreCase [= True | False ] object 参数总是一个 RegExp 对象。如果搜索是区分大小写的,则 IgnoreCase 属性为 False;否则为 True。缺省值为 True。 Pattern属性 描述:设置或返回被搜索的正则表达式模式。 这是一个最重要的属性,我们主要是设置这个属性来实现数据校验的。 语法:object.Pattern [= "searchstring"] Pattern 属性的语法包含以下几个部分: object:必需的。总是一个 RegExp 对象变量。 searchstring:可选的。被搜索的正则字符串表达式。它可能包含设置部分表格中的各种正则表达式字符。 设置:在书写正则表达式的模式时使用了特殊的字符和序列。下表描述了可以使用的字符和序列,并给出了实例。 字符描述: \:将下一个字符标记为特殊字符或字面值。例如"n"与字符"n"匹配。""与换行符匹配。序列"\\"与"\"匹配,"\("与"("匹配。 ^ :匹配输入的开始位置。 $ :匹配输入的结尾。 * :匹配前一个字符零次或几次。例如,"zo*"可以匹配"z"、"zoo"。 + :匹配前一个字符一次或多次。例如,"zo+"可以匹配"zoo",但不匹配"z"。 ? :匹配前一个字符零次或一次。例如,"a?ve?"可以匹配"never"中的"ve"。 .:匹配换行符以外的任何字符。 (pattern) 与模式匹配并记住匹配。匹配的子字符串可以从作为结果的 Matches 集合中使用 Item [0]...[n]取得。如果要匹配括号字符(和 ),可使用"\(" 或 "\)"。 x|y:匹配 x 或 y。例如 "z|food" 可匹配 "z" 或 "food"。"(z|f)ood" 匹配 "zood" 或 "food"。 n:n 为非负的整数。匹配恰好n次。例如,"o2" 不能与 "Bob 中的 "o" 匹配,但是可以与"foooood"中的前两个o匹配。 n, :n 为非负的整数。匹配至少n次。例如,"o2,"不匹配"Bob"中的"o",但是匹配"foooood"中所有的o。"o1,"等价于"o+"。"o0,"等价于"o*"。 n,m :m 和 n 为非负的整数。匹配至少 n 次,至多 m 次。例如,"o1,3" 匹配 "fooooood"中前三个o。"o0,1"等价于"o?"。 [xyz] :一个字符集。与括号中字符的其中之一匹配。例如,"[abc]" 匹配"plain"中的"a"。 [^xyz] :一个否定的字符集。匹配不在此括号中的任何字符。例如,"[^abc]" 可以匹配"plain"中的"p". [a-z] :表示某个范围内的字符。与指定区间内的任何字符匹配。例如,"[a-z]"匹配"a"与"z"之间的任何一个小写字母字符。 [^m-z] :否定的字符区间。与不在指定区间内的字符匹配。例如,"[m-z]"与不在"m"到"z"之间的任何字符匹配。 \b :与单词的边界匹配,即单词与空格之间的位置。例如,"er\b" 与"never"中的"er"匹配,但是不匹配"verb"中的"er"。 \B :与非单词边界匹配。"ea*r\B"与"never early"中的"ear"匹配。 \d :与一个数字字符匹配。等价于[0-9]。 \D :与非数字的字符匹配。等价于[^0-9]。 \f :与分页符匹配。 \n:与换行符字符匹配。 \r:与回车字符匹配。 \s :与任何白字符匹配,包括空格、制表符、分页符等。等价于"[ \f\t\v]"。 \S :与任何非空白的字符匹配。等价于"[^ \f\t\v]"。 \t :与制表符匹配。 \v :与垂直制表符匹配。 \w :与任何单词字符匹配,包括下划线。等价于"[A-Za-z0-9_]"。 \W :与任何非单词字符匹配。等价于"[^A-Za-z0-9_]"。 \num :匹配 num个,其中 num 为一个正整数。引用回到记住的匹配。例如,"(.)\1"匹配两个连续的相同的字符。 \n:匹配 n,其中n 是一个八进制换码值。八进制换码值必须是 1, 2 或 3 个数字长。 例如,"\11" 和 "\011" 都与一个制表符匹配。"\0011"等价于"\001" 与 "1"。八进制换码值不得超过 256。否则,只有前两个字符被视为表达式的一部分。允许在正则表达式中使用ASCII码。 \xn:匹配n,其中n是一个十六进制的换码值。十六进制换码值必须恰好为两个数字长。例如,"\x41"匹配"A"。"\x041"等价于"\x04" 和 "1"。允许在正则表达式中使用 ASCII 码。 --------------------------------------------------------------------------- 下面讲如何在delphi中引入该对象 1. 下载并安装最新版的"Microsoft(r) Windows(r) Script" 2. RegExp包含在vbscript.dll中所以我们必须先注册regsvr32 vbscript.dll 注(安装了Ie5后默认已经包含该控件) 3.在Delphi中引入"Microsoft VBScript Regular Expressions" 主菜单->Project->Import type library->在列表中选择"Microsoft VBScript Regular Expressions 5.5" 注意:是import type library,而不是component-import activeX control 我的机器上有两个版本,一个1.0,一个5.5, 路径分别为system32\vbscript.dll\2, system32\vbscript.dll\3 这个2,3应该指版本, Class Name一栏中有三个类:TRegExp,TMatch, TMatchCollection Pallete Page 我选择装到Sample页面上, Unit dir Name:D:\Program Files\Borland\Delphi7\Imports\,保持不变。 最后按“install”按钮,会生成安装包文件,我选择新建了目录:E:\Component\Vbscript Regex,这个dpk文件是个wrapper,用的是Imports目录中的VBScript_RegExp_55_TLB单元。 done!生成TRegExp控件。 使用控件 任务:字符串转换格式,原来的格式是每条数据以%开头,中间有三个字段,以"分隔,如: %"1-1"李应林"鄞州一中队" %"1-2"李应林"鄞州一中队" 要转换为用逗号分隔,如1-1,李应林,鄞州一中队 首先在窗体中拖一个TRegExp var colMatches: IMatchCollection; //匹配对象集合 objMatch: Match; //一个匹配对象 subMatch: ISubMatches; //子匹配对象,就是分组 i, j, k: integer; begin RegExp1.Global := true; RegExp1.Pattern := '%"(\d1,2-\d1,2)"([^"]+)"([^"]+)"'; RegExp1.IgnoreCase := true; colMatches := RegExp1.Execute(strs[i]) as IMatchCollection; for j := 0 to colmatches.Count - 1 do begin objMatch := colMatches.Item[j] as Match; submatch := objMatch.SubMatches as ISubMatches; for k:=0 to submatch.Count -1 do Str:=Str + ',' + submatch.Item[k]; Listbox1.Items.Add(copy(Str,2,length(str))); end; end;如何在数组的自定义类对象中使用 DefineProperties - Delphi
【中文标题】如何在数组的自定义类对象中使用 DefineProperties - Delphi【英文标题】:How to use DefineProperties in a custom Class Object for Arrays - Delphi 【发布时间】:2014-01-06 21:59:40 【问题描述】:我正在尝试创建自己的类对象并使用它来为我的应用程序存储各种数据类型,这在使用 Published Properties 时一切正常,我可以毫无问题地将这些流式传输到磁盘并返回。但我还需要流式传输一些整数和字符串数据类型的数组。
我知道数组和其他数据类型不能发布属性,因为 Delphi 不知道如何流式传输它们,我被引导相信您需要使用 DefineProperties 来完成此操作,我创建了一个测试数组作为公共属性的字符串,我可以很好地读取和写入它,但是我需要将它流式传输到磁盘,以便我可以保存它以备将来使用。
我能找到的关于这个主题的唯一内容是:
Array of a custom class as a property
我试图复制此代码并对其进行操作以存档我需要的内容,但我无法保存它,我似乎遗漏了一些明显的东西,我正在使用的测试代码如下,我没有收到任何错误这段代码,将属性流发布到磁盘可以,但我的私有阵列没有。任何帮助将不胜感激。
谢谢。
unit UnitDataSet;
//------------------------------------------------------------------------------
interface
uses System.Classes;
$M+
//------------------------------------------------------------------------------
type
TDataStrings = Array [1..50] of String;
TDataSet = class(TComponent)
protected
procedure DefineProperties(Filer: TFiler); override;
procedure ReadArray(Reader: TReader);
procedure WriteArray(Writer: TWriter);
private
FArrayToSave : TDataStrings;
FPStr : String;
function GetItem(I: Integer): String;
procedure SetItem(I: Integer; Value: string);
public
constructor Create(aOwner: TComponent); override;
destructor Destroy; override;
procedure LoadFromStream(const Stream: TStream);
procedure LoadFromFile(const FileName: string);
procedure SaveToStream(const Stream: TStream);
procedure SaveToFile(const FileName: string);
property Items[I: Integer]: String read GetItem write SetItem;
published
property StringItem : String read FPStr write FPStr;
end;
//------------------------------------------------------------------------------
var
DataSet: TDataSet;
implementation
uses TypInfo, Sysutils;
TDataSet
//------------------------------------------------------------------------------
procedure TDataSet.DefineProperties(Filer: TFiler);
begin
inherited;
Filer.DefineProperty('DataArray', ReadArray, WriteArray, True);
end;
//------------------------------------------------------------------------------
destructor TDataSet.Destroy;
begin
inherited;
end;
//------------------------------------------------------------------------------
function TDataSet.GetItem(I: Integer): string;
begin
Result := '';
if (I > 0) and (I < Length(FArrayToSave)) then
Result := FArrayToSave[I];
end;
//------------------------------------------------------------------------------
procedure TDataSet.SetItem(I: Integer; Value: string);
begin
if (I > 0) and (I < Length(FArrayToSave)) then
FArrayToSave[I] := Value;
end;
//------------------------------------------------------------------------------
procedure TDataSet.LoadFromFile(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
LoadFromStream(Stream);
finally
Stream.Free;
end;
end;
//------------------------------------------------------------------------------
procedure TDataSet.LoadFromStream(const Stream: TStream);
var
Reader: TReader;
PropName, PropValue: string;
begin
Reader := TReader.Create(Stream, $FFF);
Stream.Position := 0;
Reader.ReadListBegin;
while not Reader.EndOfList do
begin
PropName := Reader.ReadString;
PropValue := Reader.ReadString;
SetPropValue(Self, PropName, PropValue);
end;
FreeAndNil(Reader);
end;
//------------------------------------------------------------------------------
procedure TDataSet.SaveToFile(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmCreate);
try
SaveToStream(Stream);
finally
Stream.Free;
end;
end;
//------------------------------------------------------------------------------
procedure TDataSet.SaveToStream(const Stream: TStream);
var
PropName, PropValue: string;
cnt: Integer;
lPropInfo: PPropInfo;
lPropCount: Integer;
lPropList: PPropList;
lPropType: PPTypeInfo;
Writer: TWriter;
begin
lPropCount := GetPropList(PTypeInfo(ClassInfo), lPropList);
Writer := TWriter.Create(Stream, $FFF);
Stream.Size := 0;
Writer.WriteListBegin;
for cnt := 0 to lPropCount - 1 do
begin
lPropInfo := lPropList^[cnt];
lPropType := lPropInfo^.PropType;
if lPropType^.Kind = tkMethod then Continue;
PropName := lPropInfo.Name;
PropValue := GetPropValue(Self, lPropInfo);
Writer.WriteString(PropName);
Writer.WriteString(PropValue);
end;
Writer.WriteListEnd;
FreeAndNil(Writer);
end;
//------------------------------------------------------------------------------
constructor TDataSet.Create(aOwner: TComponent);
begin
inherited;
end;
//------------------------------------------------------------------------------
procedure TDataSet.ReadArray(Reader: TReader);
var
N: Integer;
begin
N := 0;
Reader.ReadListBegin;
while not Reader.EndOfList do begin
Reader.ReadListBegin;
FArrayToSave[N] := Reader.ReadString;
Reader.ReadListEnd;
Inc(N);
end;
Reader.ReadListEnd;
end;
//------------------------------------------------------------------------------
procedure TDataSet.WriteArray(Writer: TWriter);
var
I: Integer;
begin
Writer.WriteListBegin;
for I := 1 to High(FArrayToSave) do begin
Writer.WriteListBegin;
Writer.WriteString(FArrayToSave[I]);
Writer.WriteListEnd;
end;
Writer.WriteListEnd;
end;
//------------------------------------------------------------------------------
initialization
DataSet := TDataSet.Create(Nil);
finalization
FreeAndNil(DataSet);
end.
//------------------------------------------------------------------------------
这是我用 Arioch 建议的代码修改从下面重写的 Class 代码:
unit UnitCharSett;
interface
//------------------------------------------------------------------------------
uses System.Classes;
//------------------------------------------------------------------------------
type
TCustomDatSetA = Array [0..99] of String;
TCustomCharSet = class(TComponent)
public
procedure LoadFromStream(const Stream: TStream);
procedure LoadFromFile(const FileName: string);
procedure SaveToStream(const Stream: TStream);
procedure SaveToFile(const FileName: string);
end;
TZCharSet = class(TCustomCharSet)
private
FFullArray : TCustomDatSetA;
function GetItem(I: Integer): String;
procedure SetItem(I: Integer; Value: string);
protected
procedure DefineProperties(Filer: TFiler); override;
procedure ReadArray(Reader:TReader);
procedure WriteArray(Writer:TWriter);
public
property Items[Index: Integer]: string read GetItem write SetItem;
published
end;
//------------------------------------------------------------------------------
implementation
uses
System.TypInfo, System.SysUtils;
//------------------------------------------------------------------------------
procedure TCustomCharSet.LoadFromFile(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
LoadFromStream(Stream);
finally
Stream.Free;
end;
end;
//------------------------------------------------------------------------------
procedure TCustomCharSet.LoadFromStream(const Stream: TStream);
begin
Stream.ReadComponent(Self);
end;
//------------------------------------------------------------------------------
procedure TCustomCharSet.SaveToFile(const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create(FileName, fmCreate);
try
SaveToStream(Stream);
finally
Stream.Free;
end;
end;
//------------------------------------------------------------------------------
procedure TCustomCharSet.SaveToStream(const Stream: TStream);
begin
Stream.WriteComponent(Self);
end;
//------------------------------------------------------------------------------
TZCharSett
//------------------------------------------------------------------------------
procedure TZCharSet.DefineProperties(Filer: TFiler);
begin
inherited;
Filer.DefineProperty('DataArray', ReadArray, WriteArray, True);
end;
//------------------------------------------------------------------------------
function TZCharSet.GetItem(I: Integer): string;
begin
Result := '';
if (I > -1) and (I < Length(FFullArray)) then
Result := FFullArray[I];
end;
//------------------------------------------------------------------------------
procedure TZCharSet.ReadArray(Reader: TReader);
var
N: Integer;
S: String;
begin
for N := Low(FFullArray) to High(FFullArray) do begin
FFullArray[N] := '';
end;
Reader.ReadListBegin;
N := Reader.ReadInteger;
if N = Length(FFullArray) then
begin
N := Low(FFullArray);
while not Reader.EndOfList do
begin
S := Reader.ReadString;
if N <= High(FFullArray) then
FFullArray[N] := S;
Inc(N);
end;
end;
Reader.ReadListEnd;
end;
//------------------------------------------------------------------------------
procedure TZCharSet.SetItem(I: Integer; Value: string);
begin
if (I > -1) and (I < Length(FFullArray)) then
FFullArray[I] := Value;
end;
//------------------------------------------------------------------------------
procedure TZCharSet.WriteArray(Writer: TWriter);
var
I: Integer;
begin
Writer.WriteListBegin;
Writer.WriteInteger(Length(FFullArray));
for I := Low(FFullArray) to High(FFullArray) do begin
Writer.WriteString(FFullArray[I]);
end;
Writer.WriteListEnd;
end;
//------------------------------------------------------------------------------
initialization
RegisterClasses([TZCharSet]);
//------------------------------------------------------------------------------
end.
【问题讨论】:
当然,您的实际问题的简单答案是创建一个TFileStream
并致电WriteComponent
。
ReadArray
中的索引减一。它从零开始。顺便说一句,在 Delphi 中使用基于 1 的数组会引起混淆。首选基于零的数组。事实上,更喜欢动态数组。 FArrayToSave
似乎命名错误。在ReadArray
中使用它时看起来很奇怪。 GetItem 和 SetItem 中的 if 语句看起来很糟糕。他们鼓励代码的使用者传递无效的索引,并且永远不会发现他们弄错了。我认为您需要先修复基础知识,然后再继续。
...在项目选项中设置了使用调试 DCU
"for I := 1 to High(FArrayToSave)" - 很奇怪,“1 to 50”或“Low to High”。并且读取数组应该进行完整性检查以不写入元素 51、52 等(如果损坏的 DFM 或新版本的组件会创建具有更长数组的 dfm)
类 TDataSet 的名称不会与 STOCK TDataSet 冲突吗?
【参考方案1】:
您实际上是如何尝试读写它的?我认为您正在尝试制作复杂的不兼容的东西,而不是使用标准方法。
为什么不使用标准的 VCL 流程序?
procedure TMyDataSet.SaveToStream(const Stream: TStream);
begin
Stream.WriteComponent(self);
end;
procedure TMyDataSet.LoadFromStream(const Stream: TStream);
begin
Stream.ReadComponent(self);
end;
但是,如果不使用 TFiler 和标准 VCL 流媒体,而是使用 RTTI (GetPropList) 编写自定义代码 - 那么它不会将这些虚拟属性 APi custom 调用到TFiler
并且只会显示真实属性。
所以我的建议是使用如上所示的标准方法并简化和强化代码。
由于RegisterClass
使用类名,您最好选择另一个名称,不要与来自库存数据库单元的真实TDataSet
冲突。
修复名称并注册类,以便 VCL 流媒体可以通过名称找到它!例如:
procedure TMyDataSet.ReadArray(Reader: TReader);
var
N: Integer; S: String;
begin
N := Low(FArrayToSave);
Reader.ReadListBegin;
while not Reader.EndOfList do begin
S := Reader.ReadString; // even if we would not save it - we should remove it from the input
if N <= High(FArrayToSave) then
FArrayToSave[N] := S;
Inc(N);
end;
Reader.ReadListEnd;
end;
procedure TMyDataSet.WriteArray(Writer: TWriter);
var
I: Integer;
begin
Writer.WriteListBegin;
for I := Low(FArrayToSave) to High(FArrayToSave) do begin
Writer.WriteString(FArrayToSave[I]);
end;
Writer.WriteListEnd;
end;
initialization
DataSet := TMyDataSet.Create(Nil);
RegisterClasses([TMyDataSet]);
finalization
DataSet.Free;
end.
此外,我认为您最好 - 为了将来的可扩展性 - 将数组长度保存在 DFM 中。
procedure TMyDataSet.WriteArray(Writer: TWriter);
var
I: Integer;
begin
Writer.WriteInteger(Length(FArrayToSave));
Writer.WriteListBegin;
for I := Low(FArrayToSave) to High(FArrayToSave) do begin
....
procedure TMyDataSet.ReadArray(Reader: TReader);
var
N: Integer; S: String;
begin
for N := Low(FArrayToSave) to High(FArrayToSave) do begin
FArrayToSave := ''; // in case DFM would have less elements than 50
N := Reader.ReadInteger;
if N <> Length(FArrayToSave) then... recovery from unexpected DFM version error
N := Low(FArrayToSave);
Reader.ReadListBegin;
while not Reader.EndOfList do begin
PS。你不需要 $M+ 因为 TComponent 已经派生自 TPersistent
PPS。想对问题中的更新发表评论,但手机拒绝这样做(太长了?)所以把它放在这里。
1:由于我们不再使用 RTTI,因此不再需要使用 Typinfo 单元。 2:if N = Length(FFullArray) then
缺少 ELSE 路径。好的,现在我们了解到 DFM 已损坏或不兼容,然后呢?我认为我们最好提出一些错误。或者尝试删除 N 个字符串的列表,以便可以读取下一个属性。甚至删除任何类型/数量的元素列表,直到列表结束。永远不会保证未来兼容,但至少可以进行一些尝试,即使只是显式地因错误而停止。跳过阅读并默默地将阅读器留在属性中间,所以下一个属性会变得疯狂,我认为不是这样做的方法。
通常,David 关于忽略 setter 和 getter 中不正确的索引是正确的。除非您有意通过设置或获取“免费”“未绑定”索引(两者都没有代码)来从稀疏数组中的默认模板创建一些不寻常的隐式项目模式,否则至少在 Delphi 中更好的方法是“失败”早期的”。这就是您班级的用户默认情况下所期望的。有点像
Procedure class.CheckArrayIdx(const i: integer);
Var mx, mn : integer;
Begin
Mn := low(myarray) ; Mx := high(myarray);
If (i <= mx) and (I >= mn) then exit;
Raise ERangeError.CreateFmt('%s.Items index should be %d <= %d <= %d', [
Self.ClassName, mn, I, mx]) ;
End;
这个过程在setter和getter中都可以作为第一行调用。然后你可以使用肯定正确的索引值。
【讨论】:
无论多么奇怪,读者似乎都有相同的逻辑(尽管读入了错误的索引)。 中肯的建议,但为什么这会改变行为?除了阅读器上的虚假索引。 @SertacAkyuz 你确定EndOfList
在读取内部列表后会如何表现?
@Arioch - 不,实际上我不是。
@DavidHeffernan 实际上有三个建议(+ 名称和注册)。并且非典型的无意义的列表使用可能会导致 VCL 进入意想不到的糟糕测试的代码路径。以上是关于delphi中VBspcript_TRegExp类(正则表达式)怎么用的主要内容,如果未能解决你的问题,请参考以下文章