2.3. Строковый тип
Под строкой понимается упорядоченная последовательность литер из некоторого алфавита. Строка является самой универсальной структурой данных в том смысле, что любой алгоритм может быть представлен как алгоритм преобразования строк. Возможно представление строки вектором литер. Тип массив, имеющий вид:
packed array[M..N] of Char
где M меньше N, называется упакованным строковым типом (слово packed можно опустить, поскольку оно не оказывает действия в Borland Pascal). Упакованный строковый тип имеет некоторые свойства, не характерные для других регулярных типов. Одним из недостатков векторного представления является необходимость задания границы вектора, ориентированного на максимально возможную длину строки, что на практике приводит к не эффективному использованию ресурсов. Одним из вариантов решения данного вопроса является введение специального маркера конца строки. Таким образом, в момент работы программы, можно было бы контролировать фактическую длину строки √ число ее символов в некоторый момент времени. Массив вида:
array[0..X] of Char
где X - положительное целое число, называется массивом с нулевой базой. Массивы с нулевой базой используются для хранения строк с завершающим нулем, которые состоят из последовательности ненулевых символов, за которыми следует символ NULL (#0). Никаких ограничений на длину строк с завершающим нулем не накладывается, но 16-разрядная архитектура DOS и Windows ограничивает их размер 65535 символами. Для использования строк с завершающим нулем необходимо подключить модуль Strings. В этом же модуле описаны специальные процедуры и функции для работы с этим типом данных.
В качестве альтернативного решения учета фактического количества символов строки был введен специальный стандартный тип String, значением которого является последовательность символов с динамическим атрибутом длины (который зависит от действительного числа символов при выполнении программы) и константным атрибутом размера (в диапазоне от 1 до 255). Текущее значение атрибута длины можно получить с помощью стандартной функции Length. Внутреннее представление значения строкового типа связано с максимальной ее длиной - строка занимает столько байт, какова максимальная длина строки, плюс один байт. Первый байт содержит текущую динамическую длину строки, а последующие байты содержат символы строки. Бит длины и символы рассматриваются, как значения без знака. Максимальная длина строки - 255 символов, плюс байт длины (string[255]).
Строковую переменную можно проиндексировать с помощью одиночного индексного выражения, значение которого должно быть в диапазоне 0...n, где n - указанный в описании размер строки. Это дает доступ к каждому символу в строковом значении, если значение символа имеет тип Char. Первый символ строковой переменной (индекс 0) содержит динамическую длину строки, то есть Length( S ) тождественно Ord( S[ 0 ] ). Если атрибуту длины присваивается значение, то компилятор не проверяет, является ли это значение меньшим описанного размера строки. Можно указать индекс строки и вне ее текущей динамической длины. В этом случае считываемые символы будут случайными, а присваивания вне текущей длины не повлияют на действительное значение строковой переменной.
Строковый тип могут иметь типизированные константы. Описание типизированной константы строкового типа содержит максимальную длину строки и ее начальное значение:
const
Answer: string[3] = 'Yes';
NewPos: string[2] = #13#10;
Основными операциями для строк являются вставка заданной литеры в указанную позицию строки и удаление литеры из заданной позиции строки, поиск вхождения заданной литеры в строку. Соответствующие операции реализованы как стандартные процедуры (Delete, Insert) и функции (Pos). Реализованы также функции преобразования строки в ее численное представление (Val) и обратно (Str). Borland Pascal позволяет использовать операцию ╚+╩ (которая реализована также как стандартная процедура Concat) для объединения двух строковых операндов. Результатом операции s + t, где s и t имеют строковый тип, символьный тип (Char) или упакованный строковый тип, будет конкатенация s и t. Результат будет совместим с любым строковым типом (но не с символьным Char и не с упакованным строковым типом). Если длина результирующей строки превышает 255 символов, то она усекается до 255 символов. К идентификатору строкового типа и к ссылке на переменную строкового типа можно применять стандартные функции Low и High. В этом случае функция Low возвращает 0, а High возвращает атрибут размера (максимальную длину) данной строки.
Отношение между любыми двумя строковыми значениями устанавливается согласно отношению порядка между значениями символов в соответствующих позициях. В двух строках разной длины каждый символ более длинной строки без соответствующего символа в более короткой строке принимает значение "больше"; например, 'Abc' больше, чем 'Ab'. Нулевые строки могут быть равны только другим нулевым строкам, и они являются наименьшими строковыми значениями.
Разберем решение типичной задачи, связанной с обработкой строк.
Текст задания
Удалить из входной строки все символы ╚+╩, ╚-╩, ╚*╩, а каждый из оставшихся символов заменить на последующий.
Решение
program StringSample;
var
S: String;
Counter: Integer;
begin
readln( S );
while ( pos( '*', S )> 0 ) or ( pos( '+', S )> 0)
or ( pos( '-', S )> 0 ) do begin {цикл того,
delete( S, pos( '*', S ), 1); чтобы удалить не 1-е,
delete( S, Pos( '+', S ), 1); а все вхождения}
delete( S, pos( '-', S ), 1)
end;
for Counter:= 1 to Length( S ) do
S[ Counter ]:= chr( ord ( S[ Counter ] ) + 1 );
writeln( S )
end.
Варианты заданий
1. Вывести таблицу умножения в 16-ричной системе исчисления.
2. Дана последовательность, содержащая от 1 до 90 слов, в каждом из которых от 1 до 10 строчных русских букв; между соседними словами - не менее одного пробела, за последним словом - точка. Вывести слова по алфавиту.
3. Дан текст из 60 литер. Вывести этот текст, подчеркивая (ставя минусы в соответствующих позициях следующей строки) все входящие в него заглавные и строчные русские буквы.
4. Для введенной даты вывести название знака зодиака.
5. Дана последовательность, содержащая от 2 до 30 слов, в каждом из которых от 2 до 10 латинских букв; между соседними словами - не менее одного пробела, за последним словом - точка. Вывести все слова, отличные от последнего слова, в которых нет повторяющихся букв.
6. Число от 1 до 1999 вывести римскими цифрами.
7. Дана последовательность, содержащая от 2 до 30 слов, в каждом из которых от 2 до 10 латинских букв; между соседними словами - не менее одного пробела, за последним словом - точка. Вывести все слова, отличные от последнего слова, предварительно удалив среднюю букву в каждом слове нечетной длины.
8. Дана последовательность, содержащая от 2 до 30 слов, в каждом из которых от 2 до 10 латинских букв; между соседними словами - не менее одного пробела, за последним словом - точка. Вывести все слова, отличные от последнего слова, в которых гласные буквы чередуются с согласными.
9. Дан текст из заглавных латинских букв. Определить, является ли этот текст правильной записью римскими цифрами целого числа от 1 до 999, и, если является вывести это число арабскими цифрами в десятичной системе.
10. Даны две литеры - латинская буква (от a до h) и цифра (от 1 до 8). Рассматривая их как координаты поля шахматной доски, на котором находится конь, нарисовать шахматную доску, пометив крестиками все поля, которые "бьет" этот конь, и ноликами все остальные.
11. Дана последовательность, содержащая от 2 до 30 слов, в каждом из которых от 2 до 10 латинских букв; между соседними словами - не менее одного пробела, за последним словом - точка. Вывести все слова, отличные от последнего слова, перенеся первую букву каждого слова в его конец.
12. Дана последовательность, содержащая от 2 до 30 слов, в каждом из которых от 2 до 10 латинских букв; между соседними словами - не менее одного пробела, за последним словом - точка. Вывести все слова, отличные от последнего слова, перенеся последнюю букву каждого слова в его начало.
13. Дана последовательность, содержащая от 2 до 30 слов, в каждом из которых от 2 до 10 латинских букв; между соседними словами - не менее одного пробела, за последним словом - точка. Вывести все слова, отличные от последнего слова, удалив из каждого слова первую букву.
14. Дана последовательность, содержащая от 2 до 30 слов, в каждом из которых от 2 до 10 латинских букв; между соседними словами - не менее одного пробела, за последним словом - точка. Вывести все слова, отличные от последнего слова, удалив из каждого слова последнюю букву.
15. Дана последовательность, содержащая от 2 до 30 слов, в каждом из которых от 2 до 10 латинских букв; между соседними словами - не менее одного пробела, за последним словом - точка. Вывести все слова, отличные от последнего слова, удалив из каждого все последующие вхождения первой буквы.
16. Дана последовательность, содержащая от 2 до 30 слов, в каждом из которых от 2 до 10 латинских букв; между соседними словами - не менее одного пробела, за последним словом - точка. Вывести все слова, отличные от последнего слова, удалив из каждого все предыдущие вхождения последней буквы.
17. Дана последовательность, содержащая от 2 до 30 слов, в каждом из которых от 2 до 10 латинских букв; между соседними словами - не менее одного пробела, за последним словом - точка. Вывести все слова, отличные от последнего слова, оставив в каждом слове только первые вхождения каждой буквы.
18. Даны две литеры - латинская буква (от a до h) и цифра (от 1 до 8). Рассматривая их как координаты поля шахматной доски, на котором находится ладья, нарисовать шахматную доску, пометив крестиками все поля, которые "бьет" эта ладья, и ноликами все остальные.
19. Даны две литеры - латинская буква (от a до h) и цифра (от 1 до 8). Рассматривая их как координаты поля шахматной доски, на котором находится слон, нарисовать шахматную доску, пометив крестиками все поля, которые "бьет" этот слон, и ноликами все остальные.
20. Дана последовательность, содержащая от 2 до 30 слов, в каждом из которых от 2 до 10 латинских букв; между соседними словами - не менее одного пробела, за последним словом - точка. Вывести все слова, отличные от последнего слова, в которых каждая буква входит не менее двух раз.
21. Даны две литеры - латинская буква (от a до h) и цифра (от 1 до 8). Рассматривая их как координаты поля шахматной доски, на котором находится ферзь, нарисовать шахматную доску, пометив крестиками все поля, которые "бьет" этот ферзь, и ноликами все остальные.
22. Дана последовательность, содержащая от 2 до 30 слов, в каждом из которых от 2 до 10 латинских букв; между соседними словами - не менее одного пробела, за последним словом - точка. Вывести все слова, отличные от последнего слова, в которых первая буква повторяется.
23. Дана последовательность, содержащая от 2 до 30 слов, в каждом из которых от 2 до 10 латинских букв; между соседними словами - не менее одного пробела, за последним словом - точка. Вывести все слова, отличные от последнего слова, в которых буквы упорядочены по алфавиту.
24. Дан текст из 60 литер. Вывести только строчные русские буквы, входящие в этот текст.
25. Дан текст из строчных русских букв, за которыми следует точка. Вывести текст заглавными русскими буквами.
26. Дан непустой текст из заглавных русских букв, за которым следует точка. Определить, упорядочены ли эти буквы по алфавиту.
27. Вывести в алфавитном порядке все различные русские буквы, входящие в заданный текст из 200 литер.
28. Дана последовательность содержащая от 1 до 30 слов, в каждом из которых от 1 до 5 строчных латинских букв; между соседними словами запятая, за последним словом √ точка. Вывести все слова, которые встречаются в последовательности по одному разу.
29. Даны два различных слова, в каждом из которых от 1 до 8 строчных латинских букв и за каждым из которых √ пробел. Вывести эти слова в алфавитном порядке. (Считать, что литера ╚пробел╩ предшествует любой литере √ букве.)
30. Дана последовательность содержащая от 1 до 30 слов, в каждом из которых от 1 до 5 строчных латинских букв; между соседними словами запятая, за последним словом √ точка. Те слова, перед которыми в последовательности находятся только меньшие (по алфавиту) слова, а за ними только большие.