С моей технической точки зрения:
, наиболее очевидно, не сделайте предположения о том, как функция X должна была бы быть разработана/реализована.
, Но что еще более важно, на основе моего недавнего опыта, что происходит, то, что у владельца/клиента продукта есть некоторые привычки, или используйте некоторые инструменты для достижения определенных задач. Затем вместо того, чтобы объяснить его практический опыт, он абстрагирует то, что он думает как общее понятие, и это приводит к сбою связи, где и стороны (владелец продукта и технический персонал) смотрят друг на друга как на невежественных мужланов. Вы ничего не можете достигнуть вместе, пока у Вас всех нет общего словаря. Остановите разговор, как только что-то кажется неясным, и попытайтесь определить каждое слово.
Некоторые примеры:
И, наконец, не пытаются думать обо всем заранее, это - слишком много предположения для создания. Работайте многократно. Программное обеспечение является "мягким", это означает, что может измениться. Лучше внести небольшие изменения за время, чем быть упрямым о ранних предположениях.
Что касается управления проектами, недавно методология ТОЛПЫ помогла мне разобраться во всем виде сбоев связи. По крайней мере, из-за его прозрачности такая методология позволяет видеть то, что могло бы вызвать отказ прежде, чем потратить впустую слишком много времени или денег.
Попробуйте это / эти:
function RPos(const aSubStr, aString : String; const aStartPos: Integer): Integer; overload;
var
i: Integer;
pStr: PChar;
pSub: PChar;
begin
pSub := Pointer(aSubStr);
for i := aStartPos downto 1 do
begin
pStr := @(aString[i]);
if (pStr^ = pSub^) then
begin
if CompareMem(pSub, pStr, Length(aSubStr)) then
begin
result := i;
EXIT;
end;
end;
end;
result := 0;
end;
function RPos(const aSubStr, aString : String): Integer; overload;
begin
result := RPos(aSubStr, aString, Length(aString) - Length(aSubStr) + 1);
end;
Перегрузка обеспечивает способ вызова RPos с использованием наиболее эффективных startpos для поиска с самого конца строки без необходимости вычислять это самостоятельно. Для повышения эффективности никакая проверка не выполняется на startpos, если явно указано.
В моем наборе тестирования производительности SmokeTest это получается примерно на 20% быстрее, чем ваш FastPosBack (который, кстати, содержит ошибку «выключено на один», а также требует некоторых параметров, которые он фактически не использует).
Вы можете использовать Pos
в сочетании с ReverseString
(из StrUtils)
Во-первых, подумайте, нужно ли решение с оптимизацией скорости. Если маловероятно, что он будет вызываться 100000 раз в реальном использовании, можно перевернуть строки и использовать существующий поиск подстроки.
Если скорость является проблемой, есть много хороших ресурсов для написания собственных. Поищите в Википедии «алгоритмы строкового поиска». Я размещу ссылку и пример алгоритма, когда буду за компьютером. Сейчас я набираю это со своего телефона.
Обновление:
Вот обещанный мною пример:
function RPOS(pattern: string; text:string): Integer;
var patternPosition,
textPosition: Integer;
begin
Result := -1;
for textPosition := Length(text) downto 0 do
begin
for patternPosition := Length(pattern) downto 0 do
if not (pattern[patternPosition] = (text[textPosition - (Length(pattern) - patternPosition)])) then
break;
if patternPosition = 0 then
Result := textPosition -Length(pattern) + 1;
end;
end;
По сути, это перевернутый наивный (грубый) алгоритм поиска строк. Он начинается в конце шаблона и текста и продолжается до начала. Я могу гарантировать, что она менее эффективна, чем функция Delphi Pos (), хотя могу ' Я не могу сказать, быстрее он или медленнее, чем комбинация Pos () - ReverseString (), поскольку я ее не тестировал. В нем есть ошибка, причину которой я не нашел. Если две строки идентичны, возвращается -1 (не найдено).
Delphi поставляется с функцией, которая может искать в обратном направлении, SearchBuf
в модуле StrUtils. Однако он специализируется на поиске слов, поэтому может вести себя не так, как вы хотите. Ниже я превратил его в функцию, соответствующую вашему желаемому интерфейсу.
function FastPosBack(const aSourceString, aFindString: AnsiString;
const aSourceLen, aFindLen, StartPos: Integer): Integer;
var
Source, Match: PAnsiChar;
begin
Source := PAnsiChar(ASourceString);
Match := SearchBuf(Source, ASourceLen, ASourceLen, 0,
AFindString, [soMatchCase]);
if Assigned(Match) then
Result := Match - Source + 1
else
Result := 0;
end;
I use the RPOS variants from Free Pascal's strutils function:
http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/rtl/objpas/strutils.pp?view=markup
the string,string version is nearly the same as Deltics', but there are variants:
Function RPosEX(C:char;const S : AnsiString;offs:cardinal):Integer; overload;
Function RPosex (Const Substr : AnsiString; Const Source : AnsiString;offs:cardinal) : Integer; overload;
Function RPos(c:char;const S : AnsiString):Integer; overload;
Function RPos (Const Substr : AnsiString; Const Source : AnsiString) : Integer; overload;
They are licensed unde FPC's LGPL+linking exception license, but since I wrote them, I hereby release them under BSD license.
Не в стандартном RTL, а в INDY (модуль idGlobalProtocols согласно онлайн-справке), который является частью недавних установок Delphi:
function RPos(
const ASub: String,
const AIn: String,
AStart: Integer = -1
): Integer;