|
Длинные строки
Среда Турбо Паскаль 7.0
обладает весьма интересным новшеством: в ней введена
поддержка длинных строк, т.е. строк, длина которых может
превышать 255 байт. Как известно, тип String в Турбо
Паскале имеет максимальную длину 255 байт. Это связано
с тем, что истинная длина строки в этом типе указывается
первым байтом, мощность которого не позволяет определять
строки большей длины. В то же время в языке С используется
другой подход к заданию текстовых строк: первый байт
строки является ее первым символом, второй байт - вторым
символом и т.д. пока не встретится байт с символом #0.
Таким образом, длина строки не указывается явно, как
в типе String, а определяется по замыкающему символу
#0. Ясно, что такие строки могут иметь произвольную
длину, ограничиваемую лишь объемом оперативной памяти
или принятой схемой ее адресации: в MS-DOS такой границей
является длина сегмента, поэтому максимально возможная
длина С-строки для ПК составляет 65535 символов. Такие
строки в дальнейшем будем называть ASCIIZ-строками.
Для реализации операций над ASCIIZ-строками
в язык введен новый тип PChar, определяемый как указатель
на символ:
type
PChar =Char;
Однако такой обычный для Паскаля тип-указатель
в рамках Турбо Паскаля 7.0 трактуется необычным способом:
считается, что он указывает на цепочку символов, заканчивающуюся
терминальным нулем, т.е. на ASCIIZ-строку. Более того,
с этим типом совместим любой одномерный символьный массив
с нулевой левой границей, а переменные типа PChar можно
индексировать, как если бы они были массивами символов.
Следующая программа напечатает все заглавные буквы английского
алфавита:
{$Х+} {Включаем расширенный синтаксис}
var
Chars : array [0..26] of Char; {Массив
символов}
PChars: PChar; {Указатель на символ}
k : Integer;
begin
for k := 0 to 25 do
Chars[k] := Chr(k+ord('A'); {Наполняем
массив}
PChars := Chars; {Указателю присваиваем
массив!}
PChars[26] := #0; {Индексируем указатель!}
WriteLn(PChars) {Печатаем указатель!}
end.
Три последние оператора программы недопустимы
в стандартном Паскале и в ранних версиях Турбо Паскаля,
но возможны в версии 7.0, если включен расширенный синтаксис
(директивой {$Х+} или опцией Options/Compiler/Extended
syntax). Обратите внимание: процедура WriteLn этой версии
умеет работать с ASCIIZ-строками.
Для поддержки ASCIIZ-строк разработан
модуль Strings, в котором реализованы необходимы процедуры
и функции.
Функция StrCat.
Объединяет строки. Заголовок:
Function StrCat(Dest, Source: PChar):
PChar;
Копирует строку Source в конец строки
Dest и возвращает указатель на начало Dest.
Функция StrComp.
Сравнивает строки. Заголовок:
Function StrComp(Strl, Str2: PChar):
Integer;
Побайтно сравнивает строку Strl со строкой
Strl и возвращает следующий результат:
=0 Strl=Str2;
>0 Strl>Str2;
<0 Strl<Str2.
Функция StrCopy.
Копирует строку. Заголовок:
Function StrCopy(Dest, Source: PChar):
PChar;
Копирует строку Source в строку Dest
и возвращает указатель на Dest. StrCopy не проверяет
реальный размер памяти, связанный с Dest (он должен
быть не меньше StrLen(Source)+1).
Процедура StrDispose.
Удаляет строку из кучи. Заголовок:
Procedure StrDispose(Str: PChar);
Строка Str должна быть предварительно
помещена в кучу функцией StrNew. Если Str=NIL, процедура
ничего не делает.
Функция StrECopy.
Объединяет строки. Заголовок:
Function StrECopy(Dest, Source: PChar):
PChar;
Эта функция работает в точности как
StrCat, но возвращает указатель на конец сцепленных
строк, т.е. на терминальный ноль.
Функция StrEnd.
Возвращает конец строки. Заголовок:
Function StrEnd(Str: PChar): PChar;
Функция возвращает указатель на терминальный
ноль ASCIIZ-строки Str.
Функция StrlComp.
Сравнивает строки. Заголовок:
Function StrlComp(Strl, Str2: PChar):
PChar; .
Функция сравнивает строки, игнорируя
возможную разницу в высоте букв. Возвращает такой же
результат, как и StrComp. Замечу, что функция правильно
работает лишь с латиницей. Для кириллицы ее нужно модифицировать
(см. ниже).
Функция StrLCat.
Объединяет строки. Заголовок:
Function StrLCat(Dest, Source: PChar;
MaxLen: Word): PChar;
Копирует символы строки Source в конец
строки Dest до тех пор, пока не будут скопированы все
символы или когда длина сцепленной строки Dest не достигнет
MaxLen. Возвращает указатель на сцепленную строку.
В отличие от StrCopy эта функция блокирует
возможное переполнение области памяти, связанной с Dest.
Обычно в качестве MaxLen используется выражение SizeOf
(Dest) -1. Например:
{$Х+}
Uses Strings;
var
S: array [0..9] of Char;
begin
StrCopy(S, 'Turbo');
StrLCat(S, ' ', SizeOf(S)-1);
StrLCat(S, 'Pascal', SizeOf(S)-1);
WriteLn(S) {Напечатает "Turbo Pas"}
end;
Функция StrLComp.
Сравнивает строки. Заголовок:
Function StrLComp(Dest, Source: PChar;
MaxLen: Word): PChar;
В отличие от StrComp сравнивает не более
MaxLen символов строк. Возвращаемый результат такой
же, как и у StrComp.
Функция StrLCopy.
Заголовок:
Function StrLCopy(Dest, Source: PChar;
MaxLen: Word): PChar;
Копирует символы из строки Source в
строку Dest до тех пор, пока не будет скопирована вся
строка или пока не будет скопировано MaxLen символов.
В отличие от StrCopy блокирует возможное переполнение
области памяти, связанной с Dest. В качестве MaxLen
обычно используется выражение SizeOf (Dest) -1. Например:
{$Х+}
Uses Strings;
var
S: array [0..9] of Char;
begin
StrLCopy(S, 'Turbo Pascal', SizeOf(S)-1);
WriteLn(S) {Напечатает "Turbo Pas"}
end;
Функция StrLen.
Возвращает длину строки. Заголовок:
Function StrCattStr: PChar): Word;
Функция StrLIComp.
Сравнивает строки с учетом регистра.
Заголовок:
Function StrLIComp(Str1, Str2: PChar;
MaxLen: Word): PChar;
Сравнивает не более MaxLen символов
строк, проверяя точное соответствие высоты букв. Возвращаемый
результат см. StrComp. Функция правильно работает только
с латиницей.
Функция StrLower.
Преобразует в строчные буквы. Заголовок:
Function StrLower(Str: PChar): PChar;
Преобразует заглавные буквы строки Str
к строчным и возвращает указатель на результат. Функция
правильно работает только с латиницей.
Функция StrMove.
Копирует строку. Заголовок:
Function StrMove(Dest, Source: PChar;
Count: Word): PChar;
Копирует точно Count символов строки
Source в строку Dest и возвращает указатель на результат.
Функция игнорирует действительные размеры строк и может
выйти за их пределы.
Функция StrNew.
Помещает строку в кучу. Заголовок:
Function StrNew(Str: PChar): PChar;
Функция Str Pas.
Преобразует ASCHZ-строку в строку String.
Заголовок:
Function StrPas(Str: PChar,) : String;
Функция StrPCopy.
Преобразует строку String в ASCIIZ-строку.
Заголовок:
Function StrPCopy(Str: PChar; S: String):
PChar;
Возвращает указатель на Str.
Функция StrPos.
Ищет подстроку. Заголовок:
Function StrPos(Strl, Str2: PChar):
PChar;
Ишет подстроку Str2 в строке Strl и
возвращает указатель на первое вхождение Str2 или NIL,
есди подстрока не найдена.
Функция StrRScan.
Ищет последний символ. Заголовок:
Function StrRScan(Str: PChar; Ch: Char):
PChar;
Ищет символ Ch в строке Str и возвращает
указатель на последний обнаруженный символ Ch или NIL,
если символ не найден.
Функция StrScan.
Ищет первый символ. Заголовок:
Function StrScan(Str: PChar; Ch: Char):
PChar;
Ищет символ Ch в строке Str и возвращает
указатель на первый обнаруженный символ Ch или NIL,
если символ не найден.
Функция StrUpper.
Заголовок:
Function StrLower(Str: PChar): PChar;
Преобразует строчные буквы строки Str
к заглавным и возвращает указатель на результат. Функция
правильно работает только с латиницей.
Четыре функции модуля Strings (StrLower,
StrUpper, StrlComp и StrLIComp) используют преобразование
высоты букв и работают корректно только для букв латинского
алфавита (латиницы). Для русских букв эти функции можно
изменить следующим образом:
{Этот модуль содержит модификацию функций
стандартного модуля Strings для работы с кириллицей
(альтернативный вариант кодировки}
{$Х+}
Unit StringsR;
INTERFACE
Function LoCase(Ch: Char): Char;
Function UpCase(Ch: Char): Char;
Function StrLower(Str: PChar): PChar;
Function StrUpper(Str: PChar): PChar;
Function StrlComp(Strl, Str2: PChar):
Integer;
Function StrLIComp(Strl, Str2: PChar;
MaxLen: Word): Integer;
IMPLEMENTATION
Uses Strings;
Function LoCase(Ch: Char): Char;
{Преобразует латинскую или русскую букву
Ch к строчной}
begin
case Ch of
'A' . .'Z':LoCase:= Chr(ord('a')+ord(Ch)-ord('A'));
'A' . .'П':LoCase:= Chr(ord('a')+ord(Ch)-ord('A'));
'P' . .'Я':LoCase:= Chr(ord('p')+ord(Ch)-ord('P'));
else
LoCase:= Ch
end
end;
{-------------------}
Function UpCase(Ch: Char): Char;
{Преобразует латинскую или русскую букву
Ch к заглавной}
begin
case Ch of
'a'..'z': UpCase := Chr(ord('A')+ord(Ch)-ord('a'));
'a'..'n': UpCase := Chr(ord('A')+ord(Ch)-ord('a'));
'p'..'я': UpCase := Chr(ord('P')+ord(Ch)-ord('p'));
else
UpCase:= Ch
end
end;
{-------------}
Function StrLower(Str: PChar): PChar;
{Преобразует латинские и русские буквы
строки Str к строчным}
var
k: Word;
begin
for k := 0 to StrLen(Str)-1 do
Str[k]:= LoCase(Str[k]);
StrLower:= Str
end;
{-----------}
Function StrUpper(Str: PChar): PChar;
{Преобразует латинские и русские буквы
строки Str к заглавным}
var
k: Word;
begin
for k :=0 to StrLen(Str)-1 do
Str[k]:= UpCase(Str[k]);
StrUpper:= Str
end;
{------------}
Function StrlComp (Str1, Str2 : PChar):
Integer;
{Сравнивает две строки, игнорируя возможную
разницу в высоте латинских или русских букв}
var
k: Word;
Max: Word;
begin
{Определяем максимальное количество
сравниваемых символов как минимум
длин строк}
Мах := StrLen(Str1) ;
if StrLen (Str2).<Max then
Max := StrLen(Str2) ;
{Проверяем символы до первого несовпадения.Буквы
преобразуем к заглавным}
for k := 0 to Max-1 do
if UpCase(Strl[k])<>UpCase(Str2[k])
then
begin
{Строки не равны}
StrIComp := ord(UpCase(StrlCk]))-ord(UpCase(Str2[k]));
Exit
end;
{Разницы нет - результат зависит от
совпадения длин}
StrIComp := StrLen(Str1)-StrLen(Str2)
end;
{--------------}
Function StrLIComp(Str1, Str2: PChar;
MaxLen: Word): Integer;
{Сравнивает не более MaxLen символов
строк, проверяя точное соответствие высоты букв}
var
k. Max: Word;
begin
{Определяем максимальное количество
сравниваемых символов как минимум
длин строк и MaxLen}
Мах := MaxLen;
if StrLen(Strl)<Max then Max := StrLen(Strl);
if StrLen(Str2)<Max then Max := StrLen(Str2);
{Проверяем символы до первого несовпадения.Буквы
преобразуем к заглавным}
for k := 0 to Max do
if UpCase(Str1 [k])<>UpCase(Str2[k])
then
begin
StrLIComp := ord(UpCase(Str1[k]))-ord(UpCase(Str2[k]));
Exit
end;
{Разницы нет. Если проверено MaxLen
символов, строки считаются равными, в противном случае
результат зависит от совпадения длин строк}
if Max=MaxLen then
StrLIComp := 0
else
StrLIComp := StrLen(Str1)-StrLen(Str2)
end;
end.
Если Вы будете использовать этот модуль,
ссылайтесь на него в предложении Uses после ссылки на
стандартный модуль Strings:
Uses Strings, StringsR, ...
|