Как правильно использовать PChars для улучшения этой оптимизации? - PullRequest
0 голосов
/ 19 апреля 2011

У меня есть функция, которая часто вызывается в моем приложении. По сути, это синтаксический анализатор csv, который «выталкивает» первое значение и заменяет входную строку на оставшуюся строку.

function StripString(mask: string; var modifiedstring: string): string;
var
  index,len: integer;
  s: string;
begin
    Index := pos(Mask, ModifiedString);
    len := Length(ModifiedString);
    if index <> 0 then
    begin
        if Index <> 1 then
        begin
            s := LeftStr(ModifiedString, index - 1);
            ModifiedString := RightStr(ModifiedString, len-index);
        end else begin
            if Length(ModifiedString)>1 then
              ModifiedString := Copy(ModifiedString,2,len)
            else
              ModifiedString := '';
            s := '';
        end;
    end else begin
        s := ModifiedString;
        ModifiedString := '';
    end;
    result := s
end;

Я хочу попробовать и оптимизировать эту процедуру, используя PChars. Итак, я придумала этот метод, но, к сожалению, в результате получаю странные символы. Я предполагаю, что это из-за неправильных указателей.

//faster method - uses PChars
function StripStringEx(mask: char; var modifiedstring: string): string;
var
  pSt,pCur,pEnd : Pchar;
begin
    pEnd := @modifiedString[Length(modifiedString)];
    pSt := @modifiedString[1];
    pCur := pSt;
    while pCur <= pEnd do
    begin
         if pCur^ = mask then break;
         inc(pCur);
    end;
    SetString(Result,pSt,pCur-pSt);
    SetString(ModifiedString,pCur+1,pEnd-pCur);
end;

Кто-нибудь "указывает" :) меня в правильном направлении?

Ответы [ 2 ]

3 голосов
/ 19 апреля 2011

Даже если вы работаете с версией указателя, я не понимаю, почему она будет быстрее.

Вызов Pos быстрее, чем ваш цикл, поскольку Pos достаточно оптимизирован.Шаблоны распределения одинаковы для обеих версий, двух распределений кучи и освобождения кучи.Я бы остановился на версии, которая работает.

Вы можете избавиться от локальной переменной s и назначить прямое значение для Result, чтобы пропустить немного подсчета ссылок.

1 голос
/ 19 апреля 2011

Я думаю, вы получите странные результаты из-за SetString для ModifiedString.SetString сначала устанавливает длину строки, а затем копирует содержимое из буфера во вновь созданную строку.Но в вашем случае буфер является местом назначения, а длина буфера только что отрегулирована.

Просто следуйте советам Дэвида и не используйте PChars.

Если хотите, вы можете сделать этонесколько короче:

function StripString(const Mask: string; var ModifiedString: string): string;
var
  Index: Integer;
begin
  Index := Pos(Mask, ModifiedString);
  if Index <> 0 then
  begin
    Result := LeftStr(ModifiedString, Index - 1);
    Delete(ModifiedString, Index);
  end
  else
  begin
    Result := ModifiedString;
    ModifiedString := '';  
  end;
end;
...