Читаем Занимательное программирование – игры с текстом онлайн бесплатно
Занимательное программирование – игры с текстом
В пособии рассмотрены алгоритмы обработки текстовой информации (отдельных символов, слов и строк) средствами языка программирования Паскаль. В том числе рассмотрены принципы использования для обработки текстовых строк такого редко используемого типа данных как множества. Для школьников, учителей информатики и всех, самостоятельно изучающих программирование.
Учебная и научная литература / Образование и наукаПри изучении в школе основ программирования по какой-то неизвестной авторам данной статьи причине работа с множественными типами данных (кроме разве что массивов и в некоторых случаях – файлов) почти не затрагивается. По крайней мере, найти в различных публикациях или на сайтах образовательной тематики какие-либо хорошие (интересные и вместе с тем поучительные) задачи оказалось довольно сложно.
Желая «сломать сложившиеся стереотипы», предлагаем читателям несколько подобных задач. Решение этих задач разберем на языке Паскаль.
Наши цели при этом:
– во-первых, показать читателям (учащимся, а также учителям информатики, которые смогут затем передать эти знания своим ученикам) принципы обработки строковых данных;
– во-вторых, продемонстрировать применение некоторых возможностей Паскаля по работе со строками и символами;
– в-третьих, показать преимущества использования такого редко используемого типа данных, как множества (как показывает практика, многие попросту не знают, как можно использовать множества в реальном программировании, помимо «чисто теоретического» решения задач на пересечение, объединение и пр. множеств).
Итак, начнем…
Как мы знаем из курса информатики, текст в компьютере представлен в виде последовательности кодов составляющих его символов – букв (латинских и строчных), знаков препинания, знаков математических операций и пр., а также специальных кодов, не имеющих отдельного визуального представления в виде символов и служащих для управления размещением текста (пример – коды табуляции, перехода на новую строку и т.д.). При этом соответствие между конкретным символом и его кодом устанавливается согласно
Таким образом, каждый символ текста в памяти компьютера занимает один (или два – для Unicode) байта и хранится там в виде целого беззнакового числа. Поэтому, чтобы компьютер «не путал» их с обычными целыми числами, в языках программирования высокого уровня, как правило, для символьных и строковых типов данных предназначены отдельные, особые типы данных.
В языке Паскаль это:
– символьный тип char, предназначенный для представления одного какого-либо символа; символьная константа записывается в апострофах, например: 'a', '0', '+' и т.д.;
– множественный (составной, структурированный, сложный) тип string, предназначенный для представления целых текстовых строк; строковая константа также записывается в апострофах, например: 'Строка'.
При этом прослеживается иерархия типов: множественный тип string можно рассматривать как некий набор данных типа char (что отражает вполне очевидный факт – строка текста состоит из символов).
Определение обоих этих типов данных (как и большинства других) в языке Паскаль производится в разделе var:
– для символьного типа данных – var
– для строкового типа данных – var
При этом строка может определяться как без указания ее размера (как продемонстрировано выше), так и с явным указанием ее длины (см. рис. 1):
var
В подобном случае параметр
Следует также отметить, что в случае, когда мы не указываем размер определяемой в разделе var строковой переменной, его всё равно определяет сама система программирования. В этом случае максимально допустимая длина строки составляет 255 символов, т.е. в памяти компьютера под такую строковую переменную резервируется 256 ячеек (одна, как и раньше, для хранения реальной длины хранящегося в этой переменной строкового значения). Все рассуждения о ситуациях, когда такой переменной присваивается более короткая или, наоборот, более длинная строка, тоже при этом остаются в силе.
Массивы символов и строк в языке Паскаль также возможны. Их определение и работа с ними осуществляются точно так же, как и с массивами чисел. Например, для описания одномерных массивов можно использовать команды:
– массив символов – var
– массив строк – var
При этом для строковых массивов можно после обозначения типа string, как и в случае простой строки, указать значение размера этих строк (все строки массива, разумеется, должны иметь одинаковый максимально допустимый размер).
Обращение же к элементам таких массивов производится полностью аналогично обращению к элементам числовых массивов – путем указания имени массива и записанного после него в квадратных скобках индекса элемента.
А теперь – внимание! – начинается самое интересное.
В отличие, например, от Бейсика, где строки рассматриваются как «единое целое», в языке Паскаль (а также в ряде других языков, например, в Си) существует
Например, если мы определили строковую переменную оператором
var stroka : string[10];
и записали в нее строку 'Привет!', то оператор
writeln(stroka[1]);
выведет на экран символ 'П', а оператор
writeln(stroka[7]);
выведет символ восклицательного знака.
Соответственно, одномерный массив строк можно аналогичным образом рассматривать как двумерный массив символов, двумерный массив строк – как трехмерный массив символов и т.д.
Эта замечательная возможность делает ненужным использование функций извлечения символа из строки (типа MID$(
И наконец, завершая теоретический экскурс в символьные и строковые типы данных, перечислим некоторые имеющиеся в Паскале стандартные функции и процедуры для работы с символами и строками (информацию о них обычно можно найти в Help’е к используемой системе программирования, мы же будем рассматривать популярную в школьной практике среду программирования Pascal ABC.Net).
При использовании этих функций и процедур необходимо помнить следующее:
– функции
– процедуры, в отличие от функций, сами по себе не возвращают значений, а изменяют значение некоторых заданных в них параметров (аргументов), поэтому в составе оператора присваивания или вывода на экран их записывать нельзя. Процедура записывается отдельным оператором, например: Delete(stroka,5,1); – правильная запись (из строки
А теперь перейдем, наконец, к решению задач.
Дана строка символов. Удалить из нее первый знак препинания.
Наиболее простое решение: определить длину введенной строки, реализовать цикл перебора всех ее символов (с 1-го до последнего, имеющего номер, равный значению длины), каждый очередной символ сравнивать с каждым из возможных символов – знаков препинания («.», «,», «;», «!» и т.д.) и при выполнении этого условия каким-то способом убрать его из строки, а затем – прервать цикл просмотра символов.
Реализуем эту идею на Паскале:
Проанализируем этот листинг.
1. Вводится строка и определяется ее длина
2. Переменная
3. Строится цикл for перебора значения переменной
4. В теле цикла мы должны извлечь очередной (записанный в позиции
5. Очередной символ (st[i]) нужно сравнивать с каждым из возможных символов – знаков препинания, записывая операции сравнения типа st[i] = '.' через логическую связку or в операторе if. Тогда в ветви then (т.е. если очередной символ строки равен хотя бы одному знаку препинания) мы запоминаем его номер позиции (
6. После завершения цикла – досрочного по break или «штатного», когда завершен перебор всех символов строки, а знак препинания в ней не найден, нам надо разделить эти два случая. Для этого мы используем «флаговую» функцию переменной
– если
– иначе, если
7. Чтобы «удалить» найденный знак препинания, сделаем следующее. Оставляя исходную строку неизменной, будем формировать из нее новую строку. Сначала запишем в нее все символы исходной строки с первого до
Решение достаточно простое. Но запись условного оператора получается довольно громоздкой: ведь в нем надо перебрать (через or) все возможные случаи равенства очередного символа какому-нибудь знаку препинания. Кроме того, подумайте, что было бы, если бы таких сравнений требовалось несколько в разных местах программы и вдруг выяснилось бы, что надо изменить (скажем, дополнить знаком двоеточия) перечень обрабатываемых знаков препинания? Пришлось бы внимательно (но все равно с риском где-то что-то пропустить) просматривать всю программу, выискивать в ней все такие операторы сравнения и дописывать в них еще одно логическое условие…
Можно ли упростить программу, а заодно – и возможные модификации перечня знаков препинания, обрабатываемых в ней? Можно! И в этом нам поможет интересный, но, к сожалению, редко используемый множественный тип данных –
Множество – это набор однотипных элементов. Однако в отличие от массива, в котором такие элементы располагаются последовательно и пронумерованы индексами, множество – это просто группа элементов, «сваленных в одну кучу». Индексов у элементов множества нет. Более того – для множества порядок записи в нем элементов не важен, например [1, 2, 3] и [3, 2, 1] – это одно и то же множество цифр. Другая особенность множества – это уникальность его элементов: каждый из них должен присутствовать в множестве только «в одном экземпляре», без повторов, – например, набор [1, 2, 3, 2, 1] множеством не является.
В языке Паскаль множества определяются следующим образом:
То есть, сначала объявляется некий «класс» множеств, скажем, множество символов или чисел, а затем создается сколько угодно конкретных множеств этого типа. Например:
А после определения типового множества при объявлении экземпляра можно задать требуемые значения элементов, например:
Множество может оставаться и пустым (не содержать никаких элементов), тогда оно обозначается как [].
Над множествами можно выполнять следующие операции:
– объединение (операция + ) – результатом является множество, включающее (по одному разу!) элементы, которые есть хотя бы в одном из исходных множеств;
– пересечение (операция * ) – результатом является множество, включающее только элементы, которые есть в каждом из исходных множеств;
– разность (операция – ) – результатом для двух исходных множеств является множество, включающее только элементы, которые есть в первом из этих множеств, но отсутствуют во втором;
– проверка вхождения элемента в множество (операция in





