Урок 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; |
- Назад
- Вперёд >>
Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.
ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!