Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Delphi.doc
Скачиваний:
15
Добавлен:
19.03.2015
Размер:
176.13 Кб
Скачать

Функции для работы со строками, о которых многие часто забывают, или вовсе не знают

Как ни странно, но очень часто в форумах можно встретить вопросы, а главное ответы на них, показывающие, что многие программисты, пишущие на Delphi не знают о существовании некоторых, весьма полезных функций.

В этой части статьи я кратко расскажу о тех, которые, на мой взгляд, бывают полезны. Я не буду подробно о них рассказывать. Точное их описание Вы сможете найти в справочной системе. Здесь же я лишь упомяну о том, как обычно их использую я, и для некоторых из них приведу пример использования из реальной жизни. Рассматривайте данный раздел, как ссылки на функции, о которых вам следует почитать в справочной системе.

procedure SetLength (var S; NewLength: Integer)

Позволяет распределить память для динамической строки. Замечу, если строка уже содержит некоторое число символов, они копируются в результирующий экземпляр. Если конечно влезут. Это позволяет "расширять" уже существующий экземпляр строки.

Очень часто я использую эту функцию, когда хочу использовать динамическую строку как буфер. Например, при вызове функций Windows API:

function ComputerNetName :String;

// Возвращает сетевое имя компьютера

var Len :Cardinal;

begin

Len := MAX_COMPUTERNAME_LENGTH+1;

SetLength(Result,Len); // выделить память для буфера

if GetComputerName(pChar(Result),Len) then

SetLength(Result,Len) // установить точный размер

else

Result := '';

end;

procedure SetString(var s: string; buffer: PChar; len: Integer);

Распределяет память под экземпляр строки, копирует в него len байт из буфера buffer (если он не Nil), и присваивает ссылку на этот экземпляр переменной s. После вызова этой функции, значение счётчика ссылок полученного экземпляра всегда равно 1.

Её удобно использовать, когда нужно преобразовать в строку массив символов, не заканчивающийся #0.

function SysErrorMessage(ErrNo: Integer): string;

// Получение описания ошибки по коду

var

Size :Integer;

Buffer :array[0..1024] of Char;

begin

Size := FormatMessage

(FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ARGUMENT_ARRAY

,nil ,ErrNo ,0 ,@Buffer,SizeOf(Buffer) ,nil

);

SetString(Result, Buffer, Size);

end;

procedure UniqueString (var str: string)

Гарантирует что после вызова, str будет указывать на уникальный экземпляр значеничя строки. Т.е., str будет указывать на строку счетчик ссылок которой будет равен 1. Если необходимо, делает копию исходного значения. Обычно нет необходимости использовать эту функцию. Однако, иногда мне надо получить указатель на строку (pChar), для того что бы изменить её. А поскольку, как я уже говорил, указатели pChar не обеспечиваются контролем за изменением строк. Это может привести к побочным изменениям в "других" строках, если счётчик ссылок исходной строки был >1. Вот и приходится применять эту функцию.

procedure Wr (Msg :String);

// вывод строки в консольное окно в OEM кодировке

begin

UniqueString(Msg); // получить "персональный" экземпляр строки

Windows.CharToOem(pChar(Msg),pChar(Msg)); // преобразование его

Write(Msg); // вывод преобразованного экземпляра на консоль

end;

Здесь, поскольку параметр передаётся по значению, при вызове будет создана локальная копия переменной (указателя) Msg. Об этом я ещё расскажу ниже. Эта переменная, при завершении процедуры будет уничтожаться, что приведёт к освобождению "персональной" копии экземпляра переданной и преобразованной строки.

function AnsiCompareStr(const S1, S2: string): Integer;

function AnsiCompareText(const S1, S2: string): Integer;

function CompareStr(const S1, S2: string): Integer;

function CompareText(const S1, S2: string): Integer;

Функции этой группы используются для сравнения строк. Результатом будет одно из значений:

>0 если S1 > S2 <0 если S1 < S2 =0 если S1 = S2

Особенно удобно использование этих функций при реализации алгоритмов сортировки.

Разница между ними следующая:

Те, чьё имя заканчивается на Str, выполняют точное сравнение с учётом регистра символов, а те, что заканчиваются на Text, выполняют сравнение без учета регистра символов.

Те чьё имя начинается на Ansi, сравнивают с учётом упорядоченности символов определяемой текущей языковой настройкой Windows. Функции без Ansi, сравнивают символы как 8-битные значения, что для некоторых языковых кодировок может дать не совсем правильные результаты. В общем случае, при таком сравнении, правильным можно считать лишь результат сравнения строк содержащих только латинские символы. Например, если сравниваемые строки содержат русскую буквы 'Ё' или 'ё', то результат сравнения будет неправильным. Поэтому, я практически всегда использую функции с префиксом Ansi. Даже учитывая то, что они работают чуть медленнее.

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

function AnsiSameStr (const S1, S2: string): Boolean;

function AnsiSameText (const S1, S2: string): Boolean;

function SameText (const S1, S2: string): Boolean;

Эти функции возвращают True если обе строки равны, иначе их результат False. Обратите внимание, на отсутствие в этой группе функции SameStr. Её просто не существует! Да и зачем, если тот же результат можно получить, выполнив выражение S1 = S2.

function AnsiStartsStr (const ASubText, AText: string): Boolean;

function AnsiStartsText (const ASubText, AText: string): Boolean;

Возвращают True если строка AText начинается с ASubText.

function AnsiMatchStr (const AText: string; const AValues: array of string): Boolean;

function AnsiMatchText (const AText: string; const AValues: array of string): Boolean;

Возвращают True если строка AText встречается среди списка AValues. Пример использования:

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]