长串

String类型其实是一个指向特定格式的内存块的指针,在Delphi1中,定义一个String类型的变量的方式为:

var
    nStr : PString;

在Delphi后来的版本后,直接使用String关键字,但其本身仍然是一个指向串的指针:

var

    nStr : String;

    Len : Integer;

begin

    nStr := 'HelloWorld';

    Len := Sizeof(nStr);  //4

end;

Sizeof(nStr)其实是该指针的大小,并不是串的大小。判断串的大小需要用Length()方法。如果该指针为nil,则该串为空。否则则指向一个字符序列。

在Delphi中,String类型又分为:

ShortString, AnsiString, WideString.

在默认情况下:

var 

    nStr1 : String;    

    nStr2 : AnsiString;  

使用String关键字申明的nStr1变量相当于nStr2.

一个长串(String/AnsiString)的内部情况如下:

    偏移位置(Byte)

        -8                   //(-8..-4)存储一个整型的引用计数,对于常量串,这个值置为-1。

        -4                   //(-4..0)存储一个整型的串长度

        1..Length       //存储串

        Length + 1    //末尾追加一个NULL

注:WideString没有引用计数,其他与之相同。

对于两个串实现赋值

nStr1 := nStr2;

编译器会将其转换成两个步骤:第一先将nStr2的引用计数增加1,第二将nStr1指针置为与nStr2指针相同。

另外值得注意的是,如果将一个串传递到某个程序中,而且不打算对该串进行修改,那么最好的方式是将该串申明为const。因为如果没有申明为const(而且,这个串你正好也不需要修改),编译器就会认定你可能会修改它,因此就会建立一个局部不可见的串变量来保存它。使用时将它的引用计数增加,等使用完了就递减。编译器为了保证该串的引用计数能被递减以释放,会增加一个try .. finally块来确保。因此,在此会略微增加程序的开销。

如下:

function CountOfString1(nStr : String): Integer;
var
  i: Integer;
begin
  for i := 0 to Length(nStr) do
    if nStr[i] = '1' then
      inc(Result);
end;

function CountOfString2(const nStr : String): Integer;
var
  i: Integer;
begin
  for i := 0 to Length(nStr) do
    if nStr[i] = '1' then
      inc(Result);
end;

procedure TForm1.btn1Click(Sender: TObject);
var
  i: Integer;
  Tick : Cardinal;
begin
  Tick := GetTickCount;
  for i := 0 to 10000000 - 1 do
    CountOfString1('HelloWorld1');
  ShowMessage(Format('%d', [GetTickCount - Tick]));  //我的机器显示大致在240-250之间
end;

procedure TForm1.btn2Click(Sender: TObject);
var
  i: Integer;
  Tick : Cardinal;
begin
  Tick := GetTickCount;
  for i := 0 to 10000000 - 1 do
    CountOfString2('HelloWorld1');
  ShowMessage(Format('%d', [GetTickCount - Tick]));  //我的机器显示大致在120- 130之间
end;

 最后就是串的Pos()方法。

该方法是返回一个子串在一个更大的串中的位置。但是,如果我们要想知道某一个字符在某个大串中的位置,使用该方法,编译器又会做一些额外的操作,如下:

var

    nChar : Char;

    nStr : String;

    nPos : Integer;

begin

    nPos := Pos(nChar, nStr);

end;

使用上面的方式查找位置,编译器会自动将这个字符转换成一个长度为1的串。转换后再调用该Pos()函数。因为要调用一个自动的而且不可见的串,所以自然在使用结束后要将其释放,这里就会额外的用到try .. finally块来确保释放该串。

所以:

var

    i, nPos : Integer;
    nChar : Char;
    nStr : String;

begin

    for i := 1 to Length(nStr) do

    begin

        if nChar = nStr[i] then

        bein

            nPos := i;

            Break;

        end;

    end;

end;

使用该方式反而会比上面的方法更快一些。当然,如果本身就是要查找一个串在另一个串中的位置,也就没有这种可以略微减少开销的方式了。

再者,如果想要在串后面追加串:

nStr1 := nStr1 + nStr2; 

一般我们都是这样做,使用‘+’连接符。

但是,如果我们要在串后面追加一个字符呢:

nStr1 := nStr1 + nChar;

如果使用这样的方法,那么编译器还是会将这个nChar转换成串。

原文地址:https://www.cnblogs.com/Blogs-young-chan/p/5692209.html