Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Программирование. Процедурное программирование. Учебное пособие
.pdf
Основные возможности процедурного программирования при работе с комбинированными данными…
Глава 2. ОСНОВНЫЕ ВОЗМОЖНОСТИ
ПРОЦЕДУРНОГО ПРОГРАММИРОВАНИЯ
ПРИ РАБОТЕ С КОМБИНИРОВАННЫМИ ДАННЫМИ
ПРОИЗВОЛЬНОГО ОБЪЕМА И СОЗДАНИИ
ОТДЕЛЬНО КОМПИЛИРУЕМЫХ ПРОГРАММ
2.1. Нечисловые типы данных и инструменты работы с ними
Строки
В программировании утвердилось понятие набора символов, кото-
рый представляет собой совокупность символов одного или нескольких
алфавитов, цифровых, пунктуационных и других отображаемых символов, а также непечатных служебных символов. Отображение набора
символов в числовые коды называют кодировкой символов (или кодовой
таблицей).
Существует множество кодировок символов, и в связи с этим, чтобы
правильно интерпретировать сохраненный на компьютере текст, нужно
знать, в какой кодировке он был записан. Чаще всего установленное программное обеспечение использует стандартную системную локализованную кодовую таблицу для работы с текстами.
В Delphi предусмотрено несколько типов данных для работы с сим-
волами и строками. Строка понимается как последовательность символов.
Для хранения одиночного символа используется тип данных Char, для хранения строки неограниченной длины –
string
чить максимально возможную длину строки, это значение указывается
в квадратных скобках после слова
string.
Пример объявления строковых переменных
. Если необходимо ограни-
var
C: Char;
S: string;
FIO: string[100];
В тексте программы символы и строки записываются в апострофах,
кроме того, строкой можно манипулировать как индексированным массивом и заменять или считывать ее отдельные символы. Символы в строке
нумеруются с единицы.
51

Глава 2
Примеры обращения к символам и строкам
C := '!';
S := 'Привет.';
S[7] := C;
Примеры объединения строк
S := S + ' Как дела?'; // с помощью оператора конкатенации
S := Concat(S, ' Как дела?'); // с помощью функции Concat
Для работы со строками в Delphi определены следующие процедуры
и функции:
function Length(Str: string): Integer;
Возвращает длину строки Str.
function Pos(Substr: string; Str: string): Integer;
Возвращает номер символа, с которого начинается подстрока Substr в строке Str,
либо 0, если вхождение не найдено.
procedure Delete(var Str: string; Index: Integer; Count:
Integer);
Удаляет из строки Str Count символов, начиная с символа под номером Index.
procedure Insert(Substr: string; Str: string; Index:
Integer);
Вставляет подстроку Substr внутрь строки Str, начиная c индекса Index.
function Copy(Str: string; Index: Integer; Count:
Integer): string;
Возвращает подстроку длины Count из строки Str, начиная с индекса Index.
function Concat(S1: string;...;Sn: string): string;
Объединяет две или более строк в одну.
function StrToInt(S: string): Integer;
Преобразует строку в число целого типа.
function IntToStr(Value: Integer): string;
Преобразует целое число в строку.
function StrToFloat(S: string): Extended;
Преобразует строку в число вещественного типа.
function FloatToStr(Value: Extended): string;
Преобразует вещественное число в строку.
52

Основные возможности процедурного программирования при работе с комбинированными данными…
Множества
Еще одним полезным типом данных является множество, которое
интерпретируется как множество всех подмножеств элементов базового
множества. Базовое множество должно быть порядковым, содержащим не
более 256 элементов. Для объявления типа данных множеством используется ключевое слово
set of
. Переменная-множество может хранить любое
подмножество элементов базового типа, включая пустое множество. Множество как значение переменной задается перечислением его элементов
в квадратных скобках. Для множеств определены операции объединения
(+), пересечения (*) и разности (–) двух множеств, а также операция при-
in
надлежности (
) элемента заданному множеству. Приведем небольшой
пример работы с множествами целых чисел из диапазона от 1 до 10.
var
S1, S2, S3: set of 1..10;
begin
S1 := [1, 2];
S2 := [3, 4, 2, 5];
S3 := S1 * S2; // S3 = [2]
WriteLn(2 in S3);
Рассмотрим пример программы на данную тему.
Пример программы № 8
С клавиатуры вводится текстовая строка. Требуется определить
количество слов в ней и заменить все точки в тексте восклицательными
знаками. Результат вывести на экран.
Разработка программы
Для хранения в программе текстовой строки объявим строковую пе-
S
ременную
, значение которой пользователь вводит с клавиатуры.
Для замены всех символов «точка» на символы «восклицательный
знак» организуем цикл, в котором будем находить очередное вхождение
Pos
заменяемого символа (при помощи функцией
) и присваивать ему за-
мещающий символ. Условием выхода из цикла является возвращение 0
Pos
при очередном вызове
, т. е. отсутствие заменяемого символа в строке.
Строка текста состоит из слов и символов-разделителей, к которым
в нашем случае относятся знаки препинания и пробел. Анализируя текстовую строку, можно заметить, что в ней чередуются подстроки, которые являются словами, и подстроки, которые содержат только символыразделители. Объявим константное множество
Separators
, в котором пе-
речислим все возможные символы-разделители.
53

Глава 2
Для упрощения алгоритма в начало и конец строки добавим пробелы
и затем, просматривая строку посимвольно, будем считать количество переходов подстрок со слов в подстроки разделительных символов, а результат накапливать в переменной
Заведем вспомогательную логическую переменную
Count
. Это и будет количество слов.
CharType
, значение которой договоримся считать истинным, если текущая просматриваемая подпоследовательность состоит из разделителей. При изменении
типа подстроки, выявляемого условием ((S[I] in Separators) <> CharType),
будем обновлять значение CharType, а если оно еще и соответствует концу
слова, то увеличивать значение Count.
Текст программы полностью приведен в листинге 8. Результат рабо-
ты программы приведен на рис. 6.
Рис. 6. Результат работы программы
Листинг 8. Текст программы № 8
program Example8;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
const
// Символы-разделители
Separators = [',', '.', '!', '?', '-', ' '];
var
S: string;
Count, I, P: Integer;
CharType: Boolean;
begin
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
WriteLn('Введите строку:');
ReadLn(S);
// Замена каждого символа "точка" на символ "восклицательный
знак"
P := Pos('.', S);
while P > 0 do
54

Основные возможности процедурного программирования при работе с комбинированными данными…
begin
S[P] := '!';
P := Pos('.', S);
end;
WriteLn('Результат:');
WriteLn(S);
// Подсчет количества слов в строке
S := ' ' + S + ' ';
Count := 0;
CharType := true;
for I := 1 to Length(S) do
if (S[I] in Separators) <> CharType then
begin
if CharType then
Count := Count + 1;
CharType := not CharType;
end;
WriteLn('Количество слов в тексте: ', Count);
ReadLn;
end.
Контрольные вопросы и задания
1. Охарактеризуйте понятия «набор символов» и «кодировка символов».
Перечислите процедуры и функции, определенные в Delphi для
2.
работы со строками.
Какой индекс имеет первый символ в строке Delphi?
3.
Что такое множество?
4.
Приведите примеры задач, для решения которых удобно исполь-
5.
зовать множество.
2.2. Комбинированный тип данных. Файловый тип данных.
Основные инструменты по работе с ними
Комбинированный тип данных
При решении практических задач часто объекты характеризуются не
одним значением, а несколькими (в том числе значениями разных типов).
Например, информацию о дате можно характеризовать значениями: день, месяц и год. В языке Delphi для такой цели служит тип данных
record
Запись состоит из элементов, называемых полями, в качестве кото-
рых могут быть скалярные переменные, массивы, записи низших уровней,
массивы записей.
(запись).
55

Глава 2
Пример объявления записи TBook («книга»),
объявления переменной типа записи и массива записей
type
// Запись «книга»
TBook = record
Name: string[50]; // наименование книги
Author: string[30]; // автор книги
Year: Integer; // год издания
end;
var
B: TBook; // переменная типа записи
MyLibrary: array[1..100] of TBook; // массив записей
В оперативной памяти элементы записи располагаются последова-
тельно в том порядке, в котором они описаны. Объем памяти, занимаемой
записью, складывается из длин ее полей.
Обращение к элементам записи осуществляется с использованием
составных имен. Составное имя начинается с имени записи и содержит
имя поля, отделенное точкой.
Пример обращения к полям записи
B.Name := 'Война и мир';
B.Author := 'Толстой Л.Н.';
Для сокращения обращений к нескольким полям одной и той же за-
with
писи предусмотрен оператор присоединения
.
Пример распечатки информации о книге с использованием
оператора with
with B do
begin
WriteLn('Название книги: ', Name);
WriteLn('Автор книги: ', Author);
WriteLn('Год издания: ', Year);
end;
Записи в Delphi могут содержать вариантную часть, которая задается
описанием
case <поле признака> of <список вариантов>;
где <поле признака> – описание переменной порядкового типа.
56

Основные возможности процедурного программирования при работе с комбинированными данными…
Каждый вариант записи определяется константой выбора, за которой
следует двоеточие и список полей, заключенный в круглые скобки. В любой записи может быть только одна вариантная часть, и располагаться она
может за всеми фиксированными полями.
В следующем примере описывается тип записи TFigure с постоян-
ными полями S и P с вариантной частью, состоящей из одного, двух или
трех полей в зависимости от признака фигуры. Признак фигуры (поле TF)
объявляется как переменная перечислимого типа TTypeFigure, принимающего три возможных значения.
Пример объявления записи с вариантами
type
// Тип фигуры: окружность, прямоугольник, треугольник
TTypeFigure = (Circle, Rectangle, Triangle);
// Запись "Фигура" с вариантами
TFigure = record
S, P: Real; // S - площадь, P - период
case TF:TTypeFigure of // Вариативная часть записи
Circle: (R: Real); {Радиус круга}
Rectangle: (A, B: Real); {Длины сторон прямоугольника}
Triangle: (C1, C2, C3: Real); {Длины сторон треугольника}
end;
В следующем примере демонстрируется возможность работы с запи-
сью, имеющей вариантную часть. Следует обратить внимание на способ
ввода/вывода значений перечислимого типа. Для вывода константы, объявленной в перечислимом типе, ее следует привести к типу Integer. Для
ввода поля TF записи X вначале вводится целочисленная переменная, которая в дальнейшем приводится к типу TTypeFigure. Подробнее о приведении типов см. в п. 2.3.
Пример использования записи с вариантами
var
X: TFigure;
T: Integer;
begin
Write('Введите признак: ',Integer(Circle),' - окружность, ',
Integer(Rectangle),' - прямоугольник, ', Integer(Triangle), '
- треугольник: ');
ReadLn(T); // Тип вводится как целое число
with X do
begin
TF := TTypeFigure(T); {T приводится к перечислимому типу}
57

Глава 2
case TF of
Circle: // Вариант для круга
begin
Write('Введите радиус: '); ReadLn(R);
S := PI*R*R; P := 2*PI*R;
end;
Rectangle: // Вариант для прямоугольника
begin
Write('Введите длины сторон прямоугольника: ');
ReadLn(A, B);
S := A*B; P := 2*(A+B);
end;
Triangle: // Вариант для треугольника
begin
Write('Введите длины сторон треугольника: ');
ReadLn(C1, C2, C3);
P := C1 + C2 + C3;
S := Sqrt(P*(P-2*C1)*(P-2*C2)*(P-2*C3))/4;
end;
end;
end;
Файловый тип данных
Термином «файл» обычно называют файл, хранящийся на диске
компьютера. В операционной системе файл – это поименованная совокупность байтов. Имя файла может содержать расширение (например, .doc),
которое несет информацию о содержимом файла; оно используется операционной системой для поиска программы, с помощью которой этот файл
следует открыть.
Файлом в программировании называют специальный тип данных,
позволяющий хранить последовательность элементов одного типа и манипулировать ею. В отличие от массива, в котором элементы имеют индексы, файл обеспечивает последовательный неиндексированный доступ,
начиная с первого элемента и по очереди переходя к следующему до конца файла.
В Delphi поддерживается работа с несколькими типами файлов: тек-
стовыми, типизированными и нетипизированными. В настоящем учебном
пособии рассматриваются только два первых типа файлов.
Текстовый файл – это специальный вид файла, в котором помимо
символов, составляющих текст, содержатся служебные символы, обозначающие перевод строки. В операционной системе Windows это пара служебных символов CR+LF с кодами 13 и 10 соответственно.
58

Основные возможности процедурного программирования при работе с комбинированными данными…
Типизированный файл – файл, состоящий из последовательности
компонент одинакового типа. Файл может иметь любой тип компонент, за
исключением файлового. Требуется, чтобы длина компоненты была постоянна.
В языке программирования Delphi для работы с текстовыми файлами
существует тип данных TextFile, а для типизированных файлов – тип File
of <тип компоненты>, где <тип компоненты> – некоторый тип (встроенный или пользовательский, за исключением файлового).
Примеры объявления файловых переменных
var
F : TextFile; // Текстовый файл
FI : File of Integer; // Типизированный файл из целых чисел
Catalog : File of TBook; // Типизированный файл из записей
Для всех типов файлов можно обозначить общий порядок работы.
Манипуляция с файлом, хранящимся на диске, происходит через файловую переменную соответствующего типа данных. Для начала работы нужно назначить файловой переменной имя файла на диске (существующего
либо который будет создан), затем файл следует открыть в одном из режимов работы («на чтение», «на запись»). Далее можно выполнять операции
записи в файл либо чтения из него. По окончании работы с файлом его
следует закрыть. Все эти операции поддерживаются стандартными процедурами и функциями Delphi с небольшими различиями для разных типов
файлов, которые будут оговорены далее.
В языке программирования Delphi поддержка текстовых файлов реа-
лизована следующим набором процедур и функций.
procedure AssignFile(var F: TextFile; FileName: string);
Процедура, назначающая файловой переменной F имя внешнего файла
FileName, с которым будут выполняться все дальнейшие операции до закрытия
файла. FileName может содержать полный путь к файлу, начиная с диска, например: 'C:\MyPrograms\Matrix.txt'. Если указано только имя файла, то при выполнении программы поиск файла будет производиться в директории, где находится исполнимый файл программы.
procedure Reset(var F: TextFile);
Открывает текстовый файл в режиме «на чтение» и устанавливает текущую позицию на начало файла. В случае если файл уже открыт, то сначала закрывает
его и снова открывает. Если файл с указанным именем не будет найден, возникнет ошибка открытия файла.
59

Глава 2
procedure Rewrite(var F: TextFile);
Создает новый файл с указанным именем на диске и открывает его в режиме «на
запись». В случае если файл с таким именем существует, старое содержимое будет потеряно.
procedure Append(var F: TextFile);
Открывает текстовый файл в режиме «на запись» с текущей позицией, установленной на конец файла (т. е. новые данные будут дописываться в конец файла).
function EoF(var F: TextFile): Boolean;
Проверяет, достигнут ли конец файла, и возвращает соответствующий результат.
function EoLn(var F: TextFile): Boolean;
Проверяет текущую позицию в файле, соответствует ли она концу строки, и возвращает соответствующий результат.
procedure Read(F: TextFile; V1; Vn);
Cчитывает одно или несколько значений из текстового файла F и помещает их
в переменные V1...Vn. Алгоритм чтения зависит от типа переменных, а именно:
1. Если V1 – строковая переменная без ограничения длины, то одна строка файла до символов перевода строки будет считана и помещена в нее; при этом если
переменные V2...Vn тоже строковые, то в них будут помещены пустые строки.
2. Если V – целочисленная переменная, то после пропуска пробельных символов будет произведен поиск последовательности подряд идущих значащих символов, эта последовательность будет преобразована в целочисленное представление и результат записан в переменную V. Если окажется, что последовательность содержит нечисловые символы и преобразование невозможно, процедура
вернет ошибку чтения.
3. Похожим образом происходит чтение значений других примитивных типов
данных.
procedure ReadLn(F: TextFile; V1; Vn);
Процедура, аналогичная процедуре Read, которая дополнительно после чтения
значений производит перевод текущей позиции в файле на начало следующей
строки.
procedure Write(var F: TextFile; P1; Pn);
Процедура, записывающая в файл переданные значения P1...Pn, предварительно
преобразованные в символьное представление. Процедура поддерживает форматированный вывод: следом за параметром через двоеточие указывается общее
количество символов, отводимых на вывод. При необходимости вывод дополняется впереди идущими пробелами. Для вещественного значения еще раз через
двоеточие можно указать количество выводимых символов после запятой.
60
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
