Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
delphi / песни о паскале.pdf
Скачиваний:
62
Добавлен:
26.03.2016
Размер:
5.16 Mб
Скачать

Глава 44 Строки

Строковый тип STRING известен нам с первых глав книги, без него компьютер не общался бы с нами на «человечьем» языке. Так изучим строки получше. В современных версиях Паскаля применяют несколько строковых типов, сейчас мы рассмотрим только короткие строки, введенные ещё в Borland Pascal (в новых версиях Паскаля этот тип называется ShortString).

Строка – особый род массива

С первого взгляда строка похожа на массив символов. Так ли это? — проверим. Известно, что строка может вместить до 255 символов. Объявим массив из 255 символов и сравним его размер с размером строки. Напомню, что функция SizeOf возвращает размер памяти, занимаемой переменной.

var S1

: array [1..255] of CHAR; { это массив из 255 символов }

S2

: String;

{ это строка длиной 255 символов }

begin

 

 

 

Writeln (SizeOf(S1));

{ печатает 255

}

Writeln (SizeOf(S2));

{ печатает 256

}

Readln;

 

 

end.

 

 

 

 

 

 

 

Запустили программку? И что? Странно, но размер строки S2 оказался равным 256 байтам, что на единицу больше размера массива. Почему? Где прячется ещё один байтик? Ответ представлен на рис. 98.

Длина строки хранится в

«Мусор» – неиспользуемые байты

байте с нулевым индексом

 

6

‘P’

‘A’

‘S’

‘C’

‘A’

‘L’

0

1

2

3

4

5

6

7

255

Индексы

Рис. 98 – Размещение слова «PASCAL» в строковой переменной

Здесь показана внутренность строковой переменной со словом «PASCAL». Байты с 1-го по 6-й содержат буквы этого слова, а остальные байты не заняты. Но в

331

Глава 44

Строки

начале массива обнаружен ещё один байт — с нулевым индексом. Он содержит число 6 — это длина слова «PASCAL». Значит, строковый тип — это массив со скрытым нулевым байтом, хранящим фактическую длину строки (эту длину возвращает функция Length).

Укороченные строки

Память — жилище переменных — всегда чем-нибудь занята. Даже пустая строка (нулевой длины) занимает 256 байтов памяти, и содержит что либо. Это «что либо» программисты называют мусором, а мусор никому не интересен. Так разумно ли отводить 256 байтов для строки, если большая её часть забита всяким вздором? Ведь память — ценный ресурс, и профессионал бережет её. К примеру, для строки, хранящей фамилию, вполне хватило бы и 20 байтов.

Это понимали и создатели Паскаля, они позаботились об экономии памяти. Строковые типы можно объявлять с указанием длины. Для этого после слова STRING в квадратных скобках указывают нужный размер строки, например:

type

TStrA = string[11];

{ строка для 11

символов }

 

TStrB = string[31];

{ строка для 31

символа }

var

A : TStrA;

B : TStrB;

 

 

 

 

 

 

Здесь объявлены два строковых типа данных; первый из них вмещает до 11 символов, а второй — до 31. Соответственно переменная A будет занимать в памяти 12 байтов, а переменная B — 32 байта (с учетом нулевого байта). Согласитесь, — экономия солидная, особенно для массива из таких строк. Во всем остальном, кроме размера, короткие строки ничем не отличаются от переменных типа STRING.

А что случится при копировании длинной строки в короткую? А ничего, — не вместившиеся символы будут «отрублены». Следующая ниже программа P_44_1 подтверждает это, испытайте её.

332

 

 

 

Глава 44

 

 

 

 

Строки

 

 

 

 

 

 

{ P_44_1

- укороченные строки }

 

 

var S1

: string;

{ размер строки по умолчанию = 255 }

 

 

S2

: string[5];

{ размер укороченной строки = 5 символов }

 

begin

S1:='abc'; S2:='abcdefgh';

Writeln('Строка S1: Размер =', SizeOf(S1):4,' Длина = ',

Length(S1):4,' Значение= '+S1);

Writeln('Строка S2: Размер =', SizeOf(S2):4,' Длина = ',

Length(S2):4,' Значение= '+S2);

Writeln('Нулевой байт строки S1 = ', Byte(S1[0]));

Writeln('Нулевой байт строки S2 = ', Byte(S2[0]));

Readln;

end.

Операции со строками

Итак, уяснив внутреннее устройство строк, обратимся к связанным с ними операциям. Что мы умеем делать со строками сейчас? А вот что:

вводить и выводить строки процедурами ввода и вывода;

объединять несколько строк в одну (складывать);

определять длину строки функцией Length;

проверять строки на равенство и неравенство;

обращаться к отдельным символам строки (доступ по индексу).

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

искать одну строку внутри другой;

копировать часть строки в другую строку;

вставлять одну строку внутрь другой;

удалять часть символов из строки;

сравнивать две строки в смысле алфавитного порядка.

Рассмотрим всё это подробней. Представленные далее объявления процедур и функций даны мною лишь для пояснений, их не надо вставлять в программы.

Поиск в строке (Pos)

Функция Pos ищет одну строку внутри другой, её объявление выглядит так.

333

Глава 44

Строки

function Pos(SubS: string; S: string): Integer;

Функция принимает два параметра:

SubS – подстрока, которую ищут (то есть фрагмент строки);

S – строка, в которой ищут.

Если искомый фрагмент SubS найден, функция возвращает его позицию — индекс первого символа SubS внутри строки S, а иначе возвращает ноль. Если строка S содержит несколько искомых фрагментов, возвращается индекс первого из них. Вот примеры.

S:= 'BORLAND PASCAL';

 

 

 

p:= Pos('LA', S);

{ 4

}

p:= Pos('PAS', S);

{ 9

}

p:= Pos('pas', S);

{

0

– подстрока не найдена }

p:= Pos('A', S);

{

5

– первая из трех букв "A" }

 

 

 

 

Искомым фрагментом может быть и отдельный символ. Поиск ведется с учетом регистра; это значит, что заглавная и строчная буквы «P» считаются разными буквами.

Копирование части строки (Copy)

Функция Copy возвращает часть заданной строки.

function Copy(S: string; Index, Count: Integer): string;

Входных параметров три:

S – строка, из которой копируются символы;

Index – индекс первого копируемого символа;

Count – количество копируемых символов.

А вот примеры её применения.

S:= ’Free Pascal forever!’;

T:=

Copy(S,

6,

6);

{

’Pascal’ }

T:=

Copy(S,

6,

255);

{

’Pascal forever!’ }

Если копируемых символов затребовано больше, чем содержится в исходной строке, то скопируются все символы до конца строки (как в последнем примере).

334

Глава 44

Строки

Вставка в строку (Insert)

Объединять строки сложением просто. А если надо вставить строку в середину другой? Тогда обратитесь к процедуре Insert.

procedure Insert(S1: string; var S2: string; Index: Integer);

Входные параметры:

S1 – вставляемая строка;

S2 – ссылка на принимающую строку;

Index – позиция вставки.

Вот один пример:

S:='Спартакчемпион!';

 

{ В позицию 8

вставляются три символа: тире и два пробела }

Insert(' – ',

S, 8);

{ Спартак – чемпион! }

 

 

 

Если позиция вставки превышает длину строки S2, то строка S1 добавится в конец S2. Если длина итоговой строки S2 превысит допустимый размер, лишние символы будут отброшены.

Удаление символов из строки (Delete)

Говорят: ломать — не строить. Попытайтесь, однако, удалить часть символов из строки. Слабо? А процедура Delete справляется с этим играючи.

procedure Delete(var S: string; Index, Count : Integer);

Параметры таковы:

S – ссылка на строку;

Index – индекс первого удаляемого символа;

Count – количество удаляемых символов.

Вот случай применения процедуры.

335

Глава 44

Строки

S:= ’Free Pascal forever!’;

Delete(S, 6, 7);

{ ’Free forever!’ }

Сравнение строк

Мы уже сравнивали строки на равенство (вспомните проверку пароля). Но строки сравнивают и на больше–меньше — лексикографически. При этом сравниваются слева направо коды символов двух строк в смысле их алфавитного порядка. Если длины строк разные и короткая совпадает с началом длинной, то большей считается длинная строка. Вот примеры:

Writeln (’Borland’ > ’Pascal’); { false, поскольку ’B’ < ’P’ }

Writeln (’ABC’ > ’AB’);

{true, поскольку ’ABC’ длиннее ’AB’ }

Writeln (’ABC’ > ’abc’);

{ false, поскольку ’A’ < ’a’ }

Writeln (’45’ > ’1000’);

{ true, поскольку ’4’ > ’1’ }

В первом примере код буквы «B» меньше кода буквы «P», поэтому левая строка меньше правой. Во втором случае первые символы совпадают, но левая строка длиннее, а значит больше. В третьем примере левая строка меньше, — тоже в соответствии с таблицей кодировки. Обратите внимание на неожиданный результат сравнения строк, составленных из цифр, — это вам не числа!

Сравнивая строки, можно отсортировать их в лексикографическом порядке (как если бы они располагались в словаре). К сожалению, такое сравнение работает только для латинских букв, для русских оно не всегда верно, приходится изобретать свою функцию сравнения (в DELPHI этой проблемы нет).

Перевод символов в верхний регистр (UpСase)

Функция UpСase меняет код латинской буквы, переводя её из нижнего в верхний регистр. Иными словами, она превращает строчную (маленькую) латинскую букву в заглавную (большую). Объявление функции таково.

function UpCase(Ch: Char): Char;

Входной параметр — символ, а возвращается почти тот же символ, только «подросший», вот примеры.

c:= UpCase(’r’);

{ ’R’ }

c:= ’n’;

 

c:= UpCase( c );

{ ’N’ }

 

 

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

336

Соседние файлы в папке delphi