Странное поведение при использовании StrUtils ‘SearchBuf’

#delphi

#delphi

Вопрос:

Я убираю старый код, который раньше использовал FastStrings, и я внедрил свою старую процедуру ‘PosAnyCase’, которая должна работать как ‘Pos’. (Я надеялся, что SearchBuf лучше, чем вызывать прописные буквы в обеих строках).

 function PosAnyCase( const AFindStr, AStr : string ) : integer;
// Returns the position of this substring within a string ignoring case
  

Я использую SearchBuf следующим образом:

 function PosAnyCase( const AFindStr, AStr : string ) : integer;
// Returns the position of this substring within a string ignoring case
var
  Start, ResultPos : PChar;
begin
  Start := PChar( AStr );

  ResultPos := SearchBuf(
    Start, ByteLength( AStr ),
    0, 0,
    AFindStr, [soDown] );

  if ResultPos = nil then
    Result := 0
   else
    Result := ResultPos-Start 1;
end;
  

Когда я вызываю эту процедуру из своих модульных тестов, проходят следующие тесты:

   Check(
    PosAnyCase( '', '123' ) = 0 );
  Check(
    PosAnyCase( '2', '123' ) = 2 );
  Check(
    PosAnyCase( 'A', 'ABC' ) = 1 );
  Check(
    PosAnyCase( 'a', 'ABC' ) = 1 );
  Check(
    PosAnyCase( 'the', 'hellot there' ) = 8 );
  Check(
    PosAnyCase( 'THE', 'hellot there' ) = 8 );
  

Но этот тест НЕ ВЫПОЛНЯЕТСЯ:

 Check(
    PosAnyCase( 'nice', 'does not have n i c e' ) = 0 );
  

Что я делаю не так, пожалуйста? Документация по SearchBuf очень ограничена….
Спасибо

Комментарии:

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

2. Спасибо, Роб, да, я пробовал отлаживать его. ‘ResultPos’ (PChar) показывает ‘хороший’. Странно. Затем это выпадает из процедуры как 29, что длиннее строки.

3. Это потому, что, как я объяснил, длина неверна, и происходит переполнение буфера, которое находит другое 'nice' . Приятно!

4. Дэвид, ах, длина байта! Да, изменение длины сортирует его. Я думал, что буфер представляет собой буфер байтов, даже для Unicode. Дух! Спасибо.

5. В документации говорится, что вы должны передавать длину в байтах. Документация неверна. Вы следовали ему до буквы, и это вас подвело.

Ответ №1:

Вызов ByteLength неверен. Хотя в документации явно указано, что параметром является длина в байтах, это не так. Вы должны использовать Length вместо этого, потому что функция фактически ожидает единиц char , а не единиц byte .

Комментарии:

1. Они еще не исправили документацию ! Я не могу в это поверить.