Содержание материала

Урок 6

Это урок 6 и его тема CharPos. Данная функция ищет первое вхождение символа в строке, и возвращает его позицию когда найдет. Если ничего не найдено, то возвращается 0. функция из Delphi делает тоже самое, но с различием, что ищется вхождение подстроки в строке. Передача символа в Pos как подстроки возможна и это путь использования Pos как CharPos. В данном уроке мы разработаем CharPos, которая будет примерно в 4 раза быстрее, чем Pos.

Как обычно мы начнем с Паскаль реализации алгоритма.

 

Code:

function CharPos2(Chr : Char; const Str : AnsiString) : Cardinal;

var

I : Integer;

begin

if (Str <> '') then

begin

   I := 0;

   repeat

     Inc(I);

   until((Str[I] = Chr) or (Str[I] = #0));

   if (Str[I] <> #0) then

     Result := I

   else

     Result := 0;

end

else

   Result := 0;

end;

 

 

В функцию предаются два параметры типа Char и string. Параметр string передается как константа. Результат работы функции типа Cardinal. В начале в функции проверяется, что входная строка не пустая и если пустая, то возвращается 0. Если строка есть, то проходим по ней пока не найдем в цикле repeat until до тех пор пока не встретим совпадение с входным символом. Если встретился символ 0, он также является признаком окончания строки и цикла. Поскольку цикл может завершиться в случае нахождения символа и в случае достижения конца строки мы должны знать причину, что бы вернуть правильный результат. Если цикл закончился нахождением символа, то мы вернем переменную счетчика, а иначе вернем 0.

Также возможно использовать длину строки как условие для окончания цикла в случае неуспешного поиска. Этот код будет выглядеть так.

Code:

function CharPos1(Chr : Char; const Str : AnsiString) : Cardinal;

var

StrLenght, I : Integer;

begin

StrLenght := Length(Str);

if StrLenght > 0 then

begin

   I := 0;

   repeat

     Inc(I);

   until((Str[I] = Chr) or (I > StrLenght));

   if I <= StrLenght then

     Result := I

   else

     Result := 0;

end

else

   Result := 0;

end;

 

 

Перед тем как перейти к ассемблерному коду, хорошо бы было посмотреть какая из Паскаль реализаций быстрее. Создадим тестовую программу для проведения измерений.

Code:

const

NOOFLOOPS : Cardinal = 200000;

SCALE : Cardinal = 1000;

 

procedure Benchmark;

var

lpPerformanceCount, StartCount, EndCount : TLargeInteger;

Succes : Boolean;

Str, Str1, FunctionName : AnsiString;

Chr1, Chr2 : Char;

I, CharPos, J, K, Bench, SumBench : Cardinal;

StringArray : array[1..255] of AnsiString;

 

begin

Series1.Clear;

Str1 := 'T';

for J := 1 to 255 do

begin

   StringArray[J] := Str1;

   Str1 := 'A' + Str1;

end;

SumBench := 0;

Chr1 := 'T';

Chr2 := 'X';

for K := 1 to 255 do

begin

   Str := StringArray[K];

   Succes := QueryPerformanceCounter(lpPerformanceCount);

   if Succes then

     StartCount := lpPerformanceCount

   else

     raise Exception.Create('QueryPerformanceCounter failed');

   for I := 1 to NOOFLOOPS dиo

   begin

     CharPos := CharPosFunction(Chr1, Str);

   end;

   for I := 1 to NOOFLOOPS do

   begin

     CharPos := CharPosFunction(Chr2, Str);

   end;

   Succes := QueryPerformanceCounter(lpPerformanceCount);

   if Succes then

     EndCount := lpPerformanceCount

   else

     raise Exception.Create('QueryPerformanceCounter failed');

   Bench := Round((EndCount - StartCount) / SCALE);

   Series1.AddXY(K, Bench, '', clBlue);

   Bench := Round(Bench / K);

   SumBench := SumBench + Bench;

   Update;

end;

FunctionName :=

   FunctionSelectRadioGroup.Items[FunctionSelectRadioGroup.ItemIndex];

ReportRichEdit.Lines.Add(FunctionName + #9 + IntToStr(SumBench));

end;

 

Добавить комментарий

Не использовать не нормативную лексику.

Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.

ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!


Защитный код
Обновить