Библиотека программиста

«Любой дурак может написать программу, которую поймет компилятор. Хорошие программисты пишут программы, которые смогут понять другие программисты»

Мартин Фаулер

Главная страница > Язык Object Pascal > 7. Поддержка строк с завершающим нулем

7. Поддержка строк с завершающим нулем

Эти строки (null-terminated strings) используются многими языками, в том числе и средой Windows. Строка с завершающим нулем представляет собой массив символов, индекс первого элемента которого – нулевой. Первый встречающийся в массиве символ с кодом 0 является признаком конца строки. В Object Pascal можно использовать строки с завершающим нулем, для чего имеются языковые средства, а также подпрограммы в модуле SysUtils.

Например, следующие объявления могут быть использованы для обработки таких строк:

type

TIdentifier = array[0..15] of Char;

TFileName = array[0..259] of Char;

TMemoText = array[0..1023] of WideChar;

Таким статически размещенным массивам (с нулевым первым индексом) можно присваивать строковые константы. Динамические массивы для этой цели использовать нельзя.

Использование указателей, массивов и строковых констант.

Для обработки строк с завершающим нулем можно использовать указатели типа PChar. Строковые константы совместимы по присваиванию с типами PChar and PWideChar types, которые представляют собой указатели на массивы Char and WideChar values. Например:

var P: PChar;

P := 'Hello world!';

Такой фрагмент эквивалентен следующей конструкции:

const TempString: array[0..12] of Char = 'Hello world!'#0;

var P: PChar;

P := @TempString;

Строковые константы можно также передавать любой подпрограмме, формальные параметры которой являются параметрами значениями или параметрами const типов PChar или PWideChar, например, StrUpper('Hello world!'). Как и в случае присваивания, компилятор генерирует строковую константу и передает ее адрес подпрограмме. Также строковые константы типа PChar или PWideChar можно создавать и таким способом:

const

Message: PChar = 'Program terminated';

Digits: array[0..9] of PChar = ('Zero', 'One', 'Two', 'Three', 'Four',

'Five', 'Six', 'Seven', 'Eight', 'Nine');

Символьные массивы с нулевым первым индексом совместимы с типами PChar и PWideChar. Когда такой массив используется вместо указателя, компилятор преобразует его в константный указатель, значение которого совпадает с адресом первого элемента массива. Например:

var

MyArray: array[0..32] of Char;

MyPointer: PChar;

begin

MyArray := 'Hello';

MyPointer := MyArray;

SomeProcedure(MyArray);

SomeProcedure(MyPointer);

end;

В этом фрагменте процедура SomeProcedure вызывается дважды с одним и тем же значением.

Указатель на строку можно индексировать, начиная с нуля, как массив. Индекс указывает смещение относительно начала строки и прибавляется к значению указателя для получения адреса символа перед разыменованием указателя. Для переменных типа PWideChar индекс автоматически умножается на 2. Значение P[-1] указывает на символ, предшествующий первому, и компилятор не контролирует эту ситуацию. Функция StrUpper иллюстрирует использование указателей:

Function StrUpper(Dest, Source: PChar; MaxLen: Integer): PChar;

var

i: Integer;

Begin

i := 0;

while (i < MaxLen) and (Source[i] <> #0) do

begin

Dest[i] := UpCase(Source[i]); Inc(i);

end;

Dest[i] := #0;

Result := Dest;

End;

Смешивание строк AnsiString и строк с завершающим нулем PChar.

Можно смешивать длинные строки AnsiString и строки с завершающим нулем PChar в выражениях и в операторах присваивания. Также можно передавать строки PChar подпрограммам с параметрами AnsiStrings. Можно также выполнять приведение типа (typecast). При этом применяются следующие правила:

• если S имеет тип AnsiString, PChar(S) возвращает указатель на первый символ строки. Например, если Str1 and Str2 являются строками AnsiString, можно вызвать функцию MessageBox Win32 API таким образом:

MessageBox(0, PChar(Str1), PChar(Str2), MB_OK);

• можно также использовать выражение Pointer(S) для приведения длинной строки к нетипизированному указателю. Если при этом строка является пустой, выражение будет равно nil.

• при приведении типа переменной AnsiString к указателю, значение последнего остается корректным до тех пор, пока переменной не будет присвоено новое значение или пока переменная будет находиться в области видимости

• когда выражение типа AnsiString приводится к типу указатель, указатель должен обычно считаться доступным только по чтению. Этот указатель можно использовать для модификации строки с осторожностью при выполнении всех следующих условий:

а) выражение является переменной;

б) строка не является пустой

в) строка является единственной, т.е. число ссылок на нее равно 1. Для того чтобы это гарантировать, надо использовать подпрограммы SetLength, SetString или UniqueString;

г) строка не была модифицирована после того, как было сделано приведение типа;

д) все модифицируемые символы принадлежат строке, т.е. указатель не используется для ссылки вне строки.

Те же правила относятся и к смешиванию типов WideString со значениями PWideChar.

{$Q+,R+}

Program StrTest;

{Проверка операций со строками. @Овсянник В.Н., сентябрь 2001}

{$APPTYPE CONSOLE}

uses SysUtils;

var

ShortSGlob : ShortString;

AnsiSGlob : string;

SPChar : PChar;

Procedure TestProc(s1 : ShortString; s2 : string; s3 : PChar;

var s1v : ShortString; var s2v : string; var s3v : PChar);

var

ShortSLoc : ShortString;

AnsiSLoc : string;

Begin

ShortSLoc[3]:='3';

SetLength(AnsiSLoc,5);{без этого оператора программа работает некорректно,

что выражается в пропуске выполняемых операторов}

AnsiSLoc[3]:='3';

WriteLn('ShortSLoc="',ShortSLoc,'"'); {вывод случайных символов,

за исключением '3'}

WriteLn('AnsiSLoc ="',AnsiSLoc,'"'); {#0#0'3'#0#0}

// SPChar:=ShortSLoc; Ошибка: несовместимые типы

// SPChar:=AnsiSLoc; Ошибка: несовместимые типы

// SPChar:=PChar(ShortSLoc); Ошибка: недопустимое приведение типа

AnsiSLoc:=SPChar;

SPChar:=PChar(AnsiSLoc);

WriteLn('SPChar:=PChar(AnsiSLoc); SPChar="',SPChar,'"');{вывод пустой строки }

SPChar:='ABC';

// SPChar:=SPChar+PChar(AnsiSLoc); Ошибка: нельзя применять операцию "+"

End;

BEGIN

TestProc(ShortSGlob,AnsiSGlob,SPChar,ShortSGlob,AnsiSGlob,SPChar);

TestProc(ShortSGlob, PChar(SPChar), SPChar,ShortSGlob,AnsiSGlob,SPChar);

{ TestProc(ShortSGlob,ShortSGlob,

ShortSGlob, Ошибка: несовместимыетипы

ShortSGlob,AnsiSGlob,SPChar);

}

{ TestProc(ShortSGlob,PChar(SPChar),SPChar,ShortSGlob,

PChar(SPChar), Ошибка: типы факт. и форм. п-ров д.б. идентичны

SPChar);

}

ShortSGlob[3]:='3';

SetLength(AnsiSGlob,5);{без этого оператора программа работает некорректно,

что выражается в пропуске выполняемых операторов}

AnsiSGlob[3]:='3';

WriteLn('ShortSGlob="',ShortSGlob,'"');{вывод пустой строки}

WriteLn('AnsiSGlob ="',AnsiSGlob,'"'); {вывод: #0#0'3'#0#$14 - ?}

ReadLn;

END.





<< Предыдущая статья
«6. Строковые типы данных»
Следующая статья >>
8. Структурные типы