Лекция

При тестировании программы было получено:
Исходный массив: gnkbeqgmsin
Отсортированный массив: beggikmnnqs
Задача 2
На вход программе подаются строчные английские буквы. Ввод этих символов заканчивается точкой (другие символы, отличные от «.» и букв «a»..«z», во входных данных отсутствуют). Написать программу на Паскале, которая будет выводить буквы, встречающиеся во входной последовательности, в порядке уменьшения частоты их встречаемости. Каждая буква должна быть выведена один раз. Точка при этом не учитывается[1].
Идея алгоритма. Формируется массив символов английского алфавита от «а» до «z». Дадим массиву имя Alf, а элементы пронумеруем от 0 до 25. В другом массиве Schet[0..25] будем вести счетчики повторений каждой буквы в последовательности вводимых символов. В Schet[0] — счетчик «а», в Schet[1] — счетчик «b» и т. д. В начале счетчики обнуляются.
В цикле посимвольно вводятся данные и подсчитывается количество каждой буквы в своем счетчике. Цикл заканчивается, когда будет введена точка. Затем сортируется массив счетчиков по убыванию значений. Применяется алгоритм сортировки методом пузырька. Одновременно с перестановками в массиве Schet производятся аналогичные перестановки в массиве Alf. В конце по порядку выводятся оба этих массива, при этом пропускаются счетчики, равные нулю, и соответствующие им буквы
[1] Задача взята из демоверсии ЕГЭ по информатике.

При тестировании программы была введена последовательность символов:
rgfdeewgree.
В результате получено:
e- 4
g- 2
r- 2
d- 1
f- 1
w- 1
2.2.14. Комбинированный тип данных
Все структурные типы данных, с которыми вы уже познакомились (массивы, строки), представляют собой совокупности однотипных величин. Комбинированный тип данных — это структурный тип, состоящий из фиксированного числа компонентов (полей) разных типов.
Комбинированный тип объявляется в программе в разделе типов:
Туре <имя> = record
<имя поля 1>: <тип>;
<имя поля N>: <тип> end
Поля могут иметь любые типы, в том числе и комбинированный тип.
Например, данные о результатах экзаменов, полученных учеником по трем предметам, могут быть представлены одной величиной комбинированного типа:
Type results = record
Family: string[15]; {Фамилия ученика}
Rus: 2..5; {Оценка по русскому языку}
Alg: 2..5; {Оценка по алгебре}
Phiz: 2..5 {Оценка по физике}
end;
После этого в разделе переменных следует описание:
Var exam: results;
Величина комбинированного типа называется записью. Элементы записи идентифицируются составными именами следующей структуры:
<переменная комбинированного типа>.<имя поля>
Например: exam.family, exam.rus
В программе может использоваться массив, элементами которого являются записи.
Пример 1
На экзаменационном листе содержатся сведения о результатах экзаменов, сданных 30 учениками класса. Ввести эти данные в компьютер и получить список всех отличников.
В программе используется описание комбинированного типа result1 приведенное выше. Исходные данные организуются в массив следующей структуры.
Var list: array[1..30] of results;
После ввода в этот массив исходных данных следует фрагмент программы:
for i:=l to 30 do
if (list[i].rus=5) and (list[i].alg=5) and (list[i].phiz=5) then Writeln(list [i] .family);
Программа отбирает записи, в которых все поля с оценками равны 5, и выводит соответствующие поля фамилий.
А теперь обсудим проблему: как наиболее удобным способом организовать ввод данных в этой программе? Вводить с клавиатуры неудобно из-за большого объема данных. При каждом повторном запуске программы нужно начинать ввод сначала. А при отладке это наверняка придется делать многократно. Гораздо удобнее подготовить файл с исходными данными с помощью текстового редактора. После этого без проблем можно повторять ввод многократно. Так и поступим. Подготовим текстовый файл следующего вида:
Таблица успеваемости 10А класса
Фамилия Рус.яз. Алгебра Физика
Антонов 4 5 5
Андреева 5 3 4
Боброва 5 5 5
Васильева 5 3 4
Гриднев 5 5 5
…………
Таблица содержит данные с фамилиями и оценками 30 учеников класса. Обратите внимание на то, что фамилии записываются в отдельных строках. Необходимость этого связана с реализацией алгоритма (см. далее): при вводе символьной строки прочитывается полностью очередная строка текстового файла до признака EOLN. При этом фамилии должны содержать не более 15 символов, а первые оценки (по русскому языку) — располагаться не раньше 16-й позиции в своей строке.
Сохраним этот файл в том же каталоге, в котором предполагаете сохранить программу: под именем 10_a.txt. Составим программу с вводом таблицы успеваемости и выводом списка отличников. Фамилии отличников выведем на экран и сохраним в файле с именем Best.txt.
program Examen;
type
results = record
Fam: string[15];
Rus: 2..5;
Alg: 2..5;
Phiz: 2..5
end;
var
list: array[1..30] of results; {Массив записей}
i: integer; F1, F2: text;
begin
Assign(F1, '10_a2.txt'); {Связывание Fl с файлом 10_a.txt}
Assign(F2, 'Best.txt'); {Связывание F2 с файлом Best.txt}
Reset(F1); {Открытие файла Fl для чтения}
Rewrite(F2); {Открытие файла F2 для записи}
Readln(F1); Readln(F1); {Пропуск 2-х строк в файле F1}
{Цикл ввода из файла F1}
for i := 1 to 30 do
begin
ReadLn(F1, list[i].fam, list[i].rus, list[i].alg, list[i].phiz);
if (list[i].rus = 5) and (list[i].alg = 5) and (list[i].phiz = 5)
then
begin
Writeln(list[i].fam); {Вывод фамилии на экран}
Writeln(F2, list[i].fam) {Запись фамилии в файл F2}
end
end;
Close(F1); Close(F2) {Закрытие файлов}
end.
Пример 2
Решая рассмотренную задачу с оценками, можно обойтись без массива записей. Кроме того, можно не ставить ограничения на число учеников в классе. Их число выяснится в процессе чтения файла с таблицей успеваемости. Составим программу, которая кроме вывода списка фамилий отличников подсчитает их количество и процент отличников по отношению к полному составу класса.
program Examen_2;
type
results = record
Fam: string[15];
Rus: 2..5;
Alg: 2..5;
Phiz: 2..5
end;
var
list: results; {Одна переменная комбинированного типа} I, K: integer;
F1, F2: text;
Begin
Assign(F1, '10_a.txt');
Assign(F2, 'Best.txt');
Reset(F1); Rewrite(F2);
Readln(F1); Readln(F1);
I := 0; K := 0; {Инициализация счетчиков}
{Цикл до конца чтения файла}
while not EOF(F1) do
begin
Readln(F1, list.Fam, list.Rus, list.Alg, list.Phiz);
I := I + 1; {Подсчет числа учеников}
if (list.rus = 5) and (list.alg = 5) and (list.phiz = 5) then
begin
Writeln(list.fam);
Writeln(F2, list.fam);
K := K + 1; {Подсчет числа отличников}
end
end;
Writeln('Из ', I, ' учеников в классе ', K, ' отличников, что составляет ', K / I * 100:4:1, '%');
Close(F1); Close(F2){Закрытие файлов}
End.
В этой программе переменная I используется как счетчик числа учеников, а переменная К — как счетчик числа отличников.
Стандартная логическая функция EOF (end of file) примет значение true, когда процесс чтения из файла дойдет до его конца.
В результате выполнения программы кроме списка отличников на экран выведется строка:
Из 30 учеников в классе 8 отличников, что составляет 26.7%