Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование. Процедурное программирование. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
Основные возможности процедурного программирования при работе с комбинированными данными…
Глава 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
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]