Delphi中的System.Pos是否有缺陷? [英] Is System.Pos in Delphi Flawed?

查看:114
本文介绍了Delphi中的System.Pos是否有缺陷?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果TRichEdit中的文本是这样;

If the text in TRichEdit is something like this;

'hello, world'#$D#$A

然后,以下例程显示TRUE。但是,当RichEdit具有

Then the following routine displays TRUE. However when the RichEdit has

'test'#$D#$A#$D#$A'test'#$D#$A#$D#$A'test'#$D#$A

然后,例程显示FALSE。在我看来,找到逗号是有缺陷的,但找不到换行符/换行符。我创建了一个变通方法来代替字符串查找所需的内容,但我仍然很好奇为什么Delphi函数不起作用。有想法吗?

Then the routine displays FALSE. It seems to me to be flawed as it is finding the comma's but not the newlines/linefeeds. I created a workaround to walk the string instead and find what I'm looking for but am still really curious why the Delphi function doesn't work. Any ideas?

procedure TForm1.Button1Click(Sender: TObject);
var
   sTmp : String;
begin
   sTmp := RichEdit1.Lines.GetText;
   if ( ( Pos( ',', sTmp )  <> 0 ) or
        ( Pos( '"', sTmp )  <> 0 ) or
        ( Pos( '\n', sTmp ) <> 0 ) or
        ( Pos( '\r', sTmp ) <> 0 ) ) then
      Label1.Caption := 'TRUE'
   else
      Label1.Caption := 'FALSE';
end;



< h1>解决方法-Andreas版本(更快取决于输入)

Workaround - Andreas' Version (Faster Depending on Input)

function CheckChars( const sData: String ): Boolean;
var
   pCur : PChar;
begin
   pCur := PChar( sData );

   // Exit at NULL terminator
   while ( pCur^ <> #0 ) do
   begin
      case pCur^ of
         #13, #10, #34, #44 : Exit(true);
      end;
      Inc( pCur );
   end;
end;



正确用法



Correct Usage

function CheckChars( const sData: String ): Boolean
begin
   if ( ( Pos( #44, sData ) <> 0 ) or
        ( Pos( #34, sData ) <> 0 ) or
        ( Pos( #13, sData ) <> 0 ) or
        ( Pos( #10, sData ) <> 0 ) ) then
      Result := true
   else
      Result := false;
end;

适用于所有测试的字符,出于可读性考虑,我决定不混合使用引号字符和十进制字符。现在唯一的问题是哪个更快?我认为我的解决方法会更快,因为我会根据所需的所有字符检查每个字符,而当我使用System.Pos函数时,我将相同的解析例程运行4次。

Works for all characters tested, I decided not to mix quoted chars and decimal chars for readability. The only question now is which is quicker? I think my workaround would be quicker since I'm checking each char against all the ones I'm looking for, whereas when I use the System.Pos function I am running the same parsing routine 4 times.

经过一些测试,这取决于您要寻找哪种字符。使用逗号(#44)进行测试,将294k个字符放入589k长的字符串中。使用System.Pos的函数的性能约为390微秒,case语句运行的约为700微秒。

After some testing, it depends on what kind of characters you are looking for. Testing this with a comma(#44), located 294k characters into a 589k length string. The function using System.Pos has a performance of ~390 microseconds, and the case statement runs ~700 microseconds.

怎么做!

如果将字符串中的字符更改为换行符(#10),则由于重复调用,System.Pos(〜2700微秒)花费的时间要长得多。 case语句仍然运行约700微秒。

If you change the character in the string to a Linefeed(#10) then it takes much much longer for the System.Pos(~2700 microseconds) due to the repeated calls. The case statement still runs ~700 microseconds.

所以我想,如果您要查找某个特定字符,那么System.Pos绝对是可行的方法,但是,如果您要查找多个字符(我的应用程序可以这样做),只要您可以扫描并使用case语句,就不必重复调用。

So I guess if your looking for a particular character then System.Pos is definitely the way to go, however if you are looking for multiple(which my app does) then a repeated call isn't necessary when you could just scan it and use the case statement.

推荐答案

我不认为Delphi将\n识别为换行符,Pos认为您实际上是在搜索字符 \和 n。

I don't think Delphi recognises \n as a new line, Pos thinks you are actually searching for the characters "\" and "n".

尝试搜索#13 #10 (回车符和换行符)(或者,您可以使用#$ D #$ A 作为十六进制)

Try searching for #13 and #10 (Carriage Return and Line Feed) instead (Alternatively you could use #$D and #$A which would be the hex equivilent.)

例如

if ( ( Pos( ',', sTmp )  <> 0 ) or
     ( Pos( '"', sTmp )  <> 0 ) or
     ( Pos( #10, sTmp )  <> 0 ) or
     ( Pos( #13, sTmp )  <> 0 ) ) then

也计算Delphi字符串,尽管它们始终以#0结尾但不能保证该字符串不包含空字符,这意味着您的while循环可能会提前终止。

Also Delphi Strings are counted and while they always end in #0 There is no guarantee that the string doesn't contain a null character, meaning that your while loop may terminate early.

因此,您也可以循环遍历i:= 1到Length(sTmp)(开始

so alternatively you could loop through for i := 1 to Length(sTmp) (Starting at 1 as sTmp[0] is the counter).

或者您可以将while循环构造为

or you could construct your while loop as

索引:= 1;

While Index < Length(sTmp) do
begin
    case sTmp[Index] of
    etc...

这篇关于Delphi中的System.Pos是否有缺陷?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆