logo
Краткий курс лекций

Строковые операции

До сих пор мы с вами рассматривали программы, реализующие алгоритмы обработки числовых данных. Однако хоть ЭВМ изначально и были созданы только для этой цели, по мере развития аппаратной части появилась возможность оцифровывать данные других типов, хранить их в памяти машины, перерабатывать, выводить во внешний по отношению к компьютеру мир. Проще всего можно было так поступить с текстовой информацией. Если не ставить перед машиной задачу "понимания" смысла текста, то задача оцифровки сводится к установлению правил замены символов (литер) при вводе в компьютер на их коды и обратной замены при выводе информации на экран или принтер. Такие правила, конечно же, были составлены. Как водится, сначала их было множество (вспомните разнообразие таблиц кодировки), затем весь мир остановился на ASCII.

Все языки программирования высокого уровня имеют средства работы с литерными величинами. Паскаль - не исключение. Как вам уже известно, в стандарте языка описаны два типа переменных для литерных величин. Это - String и Char. Напомню - переменная типа Char может содержать в себе только один единственный символ, тип String предназначен для хранения строковых величин до 255 символов длиною. Кстати, вы знаете не все о типе String. При описании переменной этого типа вы можете сами указать максимальное число символов, которое можно занести в нее. Конечно же, это число не должно превышать 255. Делается это так:

Var

S : String[30];

Для чего это нужно?

Дело в том, что при компиляции для каждой переменной отводится свой участок памяти. Если мы будем выделять для всех переменных типа String по 256 байт, то это приведет к тому, что при использовании достаточно большого их количества, памяти может и не хватить? Но если в переменной мы собираемся хранить, например, фамилию пользователя, то тридцати символов (тридцати байт) для этого вполне достаточно. Таким образом, экономится память и увеличивается быстродействие программ.

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

Также, новым для вас явится то, что при использовании строковой переменной, к каждому ее символу можно обратиться отдельно. Необходимо только знать номер нужного символа от начала строки. Его достаточно поставить после имени переменной типа String в квадратных скобках.

Пример: S[5] - пятый символ строки S.

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

Обратите внимание на то, что нумерация символов в строке начинается с единицы. Внутри квадратных скобок вместо числа может находиться выражение, результатом которого является целое число. Главное чтобы символ с таким номером в строке существовал. Но как же узнать, сколько символов в данный момент находится в строковой переменной? Для этого существует специальная функция, которая возвращает длину строковой переменной в символах. Это функция Length. Ее формат: Length(S)

Здесь S - либо строковая величина, либо строковая переменная.

Приведенная далее программа выводит на экран длину введенной пользователем строковой величины.

Program Str1;

Var

S : String;

Begin

Writeln('Введите последовательность символов');

Readln(S);

Writeln('Вы ввели строку из ',Length(S), ' символов')

End.

Другой пример:

Решим задачу: "Введенную строку вывести на экран по одному символу в строке экрана".

Program Str2;

Var

S : String;

I : Byte;

Begin

Writeln('Введите строку');

Readln(S);

For I:=1 to Length(S) do {организуем цикл, начиная с первого символа}

Writeln(S[I]) {строки, до последнего (номер последнего}

{совпадает с количеством символов строки S) }

End.

Какие же еще действия можно выполнять с переменными строкового типа?

Две строковые величины можно состыковывать. Эта операция называется конкатенацией и обозначается знаком "+".

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

R:= 'kadabra';

H:= 'abra';

S:=H+R;

в переменной S будет значение 'abrakadabra'.

Для конкатенации результат зависит от порядка операндов (в отличие от операции сложения). Следует помнить о том, какой максимальной длины может быть результирующая переменная, так как в случае превышения значением выражения числа, указанного после String в описании переменной, "лишние" символы в переменную не попадут.

Строковые величины можно сравнивать между собой. Это относится также и к строковым переменным. Но как же компьютер определяет, какая строка больше: та, которая длиннее?

та, которая содержит больше заглавных букв?

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

Код символа в Паскале можно определить при помощи функции Ord.

Ее формат: Ord(C), где С - либо непосредственно указанный символ, либо переменная символьного типа, либо один символ строковой переменной. Вообще, функция Ord имеет более глубокий смысл, но об этом - позже. Есть и обратная функция, которая возвращает символ по известному коду. Это функция Chr(N), где N - выражение, приводящее к целому числу в интервале от 0 до 255 (возможные значения кода символа). Очевидно, что Chr(Ord(C))=C, Ord(Chr(N))=N.

Следующая маленькая программа выводит на экран кодовую таблицу: Program Str3;

Var

I : Byte;

Begin

For I:=32 to 255 do

Write('VV',I:4, '-',Chr(I))

End.

Цикл в программе начинается с 32 потому, что символы с кодами от 0 до 31 являются управляющими и не имеют соответствующего графического представления.

Задача: "Определить, является ли введенная строка "перевертышем". Перевертышем называется такая строка, которая одинаково читается с начала и с конца. Например, "казак" и "потоп" - перевертыши, "канат" - не перевертыш".

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

Program Str4;

Var

S,B : String;

I : Byte;

Begin

Writeln('Введите строку');

Readln(S);

B:=''; {Переменной B присваиваем значение "пустая строка"}

For I:=1 to Length(S) do

B:=S[I]+B; {Конкатенация. Символы строки S пристыковываются к}

{переменной B слева. Самым левым окажется последний.}

If B=S Then Writeln('Перевертыш') Else Writeln('Не перевертыш')

End.

Число, записанное в строковую переменную, естественно числом не является, но очень часто требуется его все же использовать в качестве числа. Для этого нужно произвести преобразование типа. Перевод строкового представления числа в числовое выполняет в Паскале оператор Val.

Его формат:

Val(S,X,C);

Здесь S - строка, содержащая число, X - числовая переменная, в которую будет помещен результат, С - переменная целочисленного типа, в которую помещается первого встреченного в S отличного от цифры символа. Если после выполнения оператора Val переменная С имеет значение 0, то это означает, что преобразование типа прошло совершенно успешно и в строке нецифровых символов не встретилось.

Противоположное действие осуществляет оператор Str. Формат оператора:

Str(X,S);

X - число (либо арифметическое выражение), S - строковая переменная.

В переменную S попадает строковое представление числа X. Это нужно, например, при необходимости выводить на экран числа в графическом режиме (будет изучено позже), так как стандартные процедуры вывода на экран там работают только со строковыми величинами.

Для иллюстрации рассмотрим такую задачу: "Найти сумму цифр введенного натурального числа". Используя только числовые переменные, решить ее можно, но предлагаемое здесь решение, по-моему, проще.

Program Str5;

Var

S : String;

I,X,A,C : Integer;

Begin

Writeln('Введите натуральное число');

Readln(S); {Число вводится в строковую переменную}

A:=0;

For I:=1 To Length(S) Do

Begin

Val(S[I],X,C); {Цифровой символ превращается в число}

A:=A+X {Цифры суммируются}

End;

Writeln('Сумма цифр равна ',A)

End.

Теперь рассмотрим еще несколько действий над строками: оператор DELETE(S,I,C) из строковой переменной S удаляет C символов, начиная с I-того;

оператор INSERT(SN,S,I) вставляет подстроку SN в строковую переменную S перед символом с номером I;

функция COPY(S,I,C) возвращает подстроку строки S из C символов, начиная с символа с номером I;

функция Pos(SN,S) возвращает номер символа, с которого в строке S начинается подстрока SN (позицию первого вхождения подстроки в строку). Если такой подстроки нет, то возвращается ноль.

Пример их использования:

"Во введенной строке заменить все вхождения подстроки 'ABC' на подстроки 'KLMNO'".

Program Str6;

Var

S : String;

A : Byte;

Begin

Writeln('Введите строку');

Readln(S);

While Pos('ABC',S)<>0 Do

Begin

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

Delete(S,A,3);

Insert('KLMNO',S,A)

End;

Writeln(S)

End.

. СТРОКИ

Особое место в языке ПАСКАЛЬ занимают массивы символов. Стандартный ПАСКАЛЬ допускает два способа хранения символьных массивов в памяти ЭВМ: распакованный и упакованный. Распакованные массивы символов хранятся в памяти ЭВМ по одному символу в машинном слове, упакованные - по одному символу в байте. При описании упакованного массива симво лов используют служебное слово PACKED, например:

var MAS: Packed Array[1..20] of Char;

Описание распакованного массива символов имеет вид:

var M: Array[1..20] of char;

Для преобразования символьного массива из распакованной формы в упакованную и наоборот, из упакованной в распакованную, в язык ПАС КАЛЬ введены две стандартные функции Pack, UnPack.

Упакованный массив символов образует символьную строку. Символьная строка может быть либо строковой константой, либо строковой перемен ной. Строковая константа, или строка, представляет собой совокупность символов, заключенную в апострофы. Строка - это элементарная конс трукция языка ПАСКАЛЬ. Строковые константы могут входить в состав вы ражений. Как и числовые константы, они могут быть описаны в разделе описания констант.

Строковые переменные - это одномерные упакованные массивы симво лов, для описания которых в TURBO PASCAL введен тип String. Например, если строка содержит до 30 символов, ее тип будет опре делен как

type s= String[30];

Длина строки не может содержать более, чем 255 символов.

В TURBO PASCAL определено понятие строки переменной длины, в этом

случае ее описание задается как

type s= String;

Тип String без указания длины совместим со всеми типами строк.

Особенностью строковых переменных является то, что к ним можно об ращаться как к скалярным переменным, так и к массивам. Во втором слу чае применяется конструкция "переменная с индексом", что обеспечивает доступ к отдельным символам строки. При этом нижняя граница идекса равна 1. Отдельный символ строки совместим с типом Char.

В памяти ЭВМ строка занимает количество байтов, на единицу большее ее длины. Нулевой байт строки содержит ее длину.

Для строк определены операции присваивания, слияния (конкатенации) и сравнения.

Для сравнения строк применяются все операции отношения. Сравнение строк происходит посимвольно, начиная с первого символа. Строки рав ны, если имеют одинаковую длину и посимвольно эквивалентны.

Строки могут быть элементами списка ввода - вывода, при этом запи сывается имя строки без индекса.

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

Инициализация строк может производиться как с помощью типизирован ных констант:

const sName: String[9]= 'IBM PC/AT';

так и с использованием второй разновидности функции FillChar:

FillChar( var V; NBytes: Word; C: Char );

например:

FillChar(A, SizeOf(A), '0');

Для работы со строками в TURBO PASCAL включены процедуры и функции, которые обеспечивают редактирование и преобразование строк.