- •Основное содержание
- •Языки и системы программирования
- •Этапы решения задачи на эвм
- •6. Анализ результатов решения задачи и уточнение в случае необходимости математической модели с повторным выполнением этапов 2-5.
- •7. Сопровождение программы:
- •Основные характеристики программ
- •Тема 2. Основные понятия алгоритмизации. (4 часа)
- •1. Словесный способ записи алгоритма
- •3. Псевдокод.
- •Тема 3. Языки и системы программирования.
- •Характеристики языков программирования
- •Алфавит и словарь языка
- •Ключевые слова
- •Переменные и константы
- •Типы данных
- •Данные и значения
- •Операции и их типы
- •Выражения и приоритет операций
- •Структура программы
- •Отладка и тестирование программ
- •1. Сущность рекурсии
- •2. Сложная рекурсия
- •3. Имитация работы цикла с помощью рекурсии
- •4. Рекуррентные соотношения. Рекурсия и итерация
- •5. Деревья
- •5.1. Основные определения. Способы изображения деревьев
- •5.2. Прохождение деревьев
- •5.3. Представление дерева в памяти компьютера
- •6. Примеры рекурсивных алгоритмов
- •6.1. Рисование дерева
- •6.2. Ханойские башни
- •6.3. Синтаксический анализ арифметических выражений
- •6.4. Быстрые сортировки
- •6.5. Произвольное количество вложенных циклов
- •6.6. Задачи на графах
- •6.7. Фракталы
- •7. Избавление от рекурсии
- •7.1. Явное использование стека
- •7.2. Запоминание последовательности рекурсивных вызовов
- •7.3. Определение узла дерева по его номеру
- •Тип указатель. Динамические переменные
- •Динамические переменные
Типы данных
Прежде, чем приступить к рассмотрению типов данных, постараемся понять, для чего это вообще надо. Прежде всего, Object Pascal, равно как и его предшественник - язык Pascal, а так же C и C++ относятся к строго типизированным языкам программирования. Типизированные языки, в отличие от нетипизированных (начиная с BASIC и заканчивая различными языками сценариев вроде JavaScript), имеют то преимущество, что уже на этапе синтаксической проверки кода компилятор не допустит заведомо неверных операций. К примеру, вы не сможете сложить строку с числом. Кроме того, типизация положительно сказывается на быстродействии программ: благодаря тому, что компилятор заранее "знает", что за данные ему следует обработать в каждом конкретном случае, он может подбирать оптимальные инструкции при генерации машинного кода.
Теперь рассмотрим собственно типы данных, имеющиеся в Object Pascal. Прежде всего отметим, что они бывают простыми (числа, символы), структурными (массивы, записи), процедурными и вариантными. Знакомство со структурными и процедурными типами мы отложим до соответствующей главы, а пока что перечислим категории простых типов данных:
Целочисленные (Integer);
Вещественные (Real);
Булевы (Boolean);
Символьные (Character);
Строковые (String).
Практически в каждой категории имеется несколько типов данных. В свою очередь это так же вызвано необходимостью более эффективного использования ресурсов компьютера. Например, если для какой-то переменной достаточно диапазона значений от 1 до 100, то зачем для нее выделять память, достаточную для хранения миллиардных значений? Так что начнем подробное с целочисленных типов, как наиболее простых и наглядных.
Всего в современных версиях Delphi предусмотрено 7 различных типов данных для целых чисел, все они приведены в таблице 3.2.
Таблица 3.2. Типы целочисленных данных |
|||
Тип |
Диапазон |
Байт (бит) памяти |
Отрицательные значения |
Byte |
от 0 до 255 |
1 (8) |
Нет |
ShortInt |
от -128 до 127 |
1 (8) |
Да |
Word |
от 0 до 65535 |
2 (16) |
Нет |
SmallInt |
от -32768 до 32767 |
2 (16) |
Да |
LongWord |
от 0 до 4294967295 |
4 (32) |
Нет |
LongInt |
от -2147483648 до 21474483647 |
4 (32) |
Да |
Int64 |
от -9223372036854775808 до 9223372036854775807 |
8 (64) |
Да |
ПРИМЕЧАНИЕ Здесь следует сразу оговориться про понимание памяти в программировании. Так, память считают в байтах. Каждый байт состоит из 8 бит. Бит - это минимальная единица информации, бит может принимать только 2 значения, 0 или 1. Каждая переменная, в зависимости от типа, занимает то или иное количество байт в памяти. Отметим так же, что 2 байта образуют слово (word), а 4 байта - двойное слово.
Помимо перечисленных основных типов, в Delphi имеется еще 2 автоматических целочисленных типа - Integer и Cardinal. Первое, в типичном случае, является синонимом для LingInt, хотя может быть приведено и к типу Int64. Например, если объявит переменную типа Integer и попробовать записать в нее значение, превышающее максимально допустимый размер для типа LongInt, то она автоматически преобразуется в Int64:
var x: integer; ... x: = 21474483647; // здесь x имеет тип LongInt x: = x + 1; { число 21474483648 не помещается в 4-х байтовый LongInt, переменная x автоматически приводится к 8-байтовому типу int64 }
Что касается Cardinal, то это - устаревшее определение для LongWord, вы сможете встретить его, если будете просматривать исходные коды, написанные во времена первых версий Delphi. Самым распространенным на практике целочисленным типом данных является Integer.
Перейдем к вещественным типам. Для них так же предусмотрены фиксированные типы (правда, в отличие от целочисленных, их не 7, а 6), и один автоматический. Рассмотрим основные типы в таблице 3.3.
Таблица 3.3. Типы вещественных данных |
|||
Тип |
Диапазон |
Байт памяти |
Точность |
Real48 |
от ±2.9*10^-39 до 1.7*10^38 |
6 |
11.дек |
Single |
от ±1.5*10^-45 до 3.4*10^38 |
4 |
07.авг |
Double |
от ±5.0*10^-324 до 1.7*10^308 |
8 |
15-16 |
Extended |
от ±3.4*10^-4951 до 1.1*10^4932 |
10 |
19-20 |
Comp |
от -2^63+1 до 2^63 -1 |
8 |
19-20 |
Currency |
от -922337203685477.5808 до 922337203685477.5807 |
8 |
19-20 |
Имеется так же и автоматический тип - Real, введенный для совместимости с программами, написанными в Delphi 2 или 3. Сейчас тот тип, что был в ранних версиях Delphi, называется Real48 и практически не используется. Вместо него рекомендуется использовать такие типы, как Single или Double. Если же задать тип Real в программе, то он будет автоматически приведен к типу Double.
Нечто подобное можно сказать и про тип Comp - этот 64-разрядный вещественный тип данных изжил себя с момента появления целочисленного типа Int64, и присутствует лишь в целях совместимости со старым программным кодом.
Зато тип Currency активно используется, особенно при работе с базами данных. Как следует из его названия (Currency - валюта), данный тип предпочтительно использовать для финансовых расчетов. И хотя Currency относится к вещественным типам данных, компилятор обращается с ним как с целым, что позволяет добиться меньших ошибок при округлениях.
В целом, что касается целых и вещественных типов, достаточно запомнить всего две вещи: вещественным типам данных можно присваивать любые численные значения, а целочисленным - только целые:
var x: integer; y: double; ... x := 5; y := 5.25; // обратите внимание, что дробная часть отделяется точкой y := x + y; // так делать можно x := x + y; // а так - нельзя, поскольку результатом должно быть целое
Булевы, или логические типы данных представлены в Delphi типами Boolean, ByteBool, WordBool и LongBool. Все они отличаются только размером памяти, выделяемым для хранения значения, причем значений может быть только 2 - false (ложь) и true (истина):
var x, y: Boolean; ... x := true; y := false;
Основным типом является 1-байтовый Boolean (он же ByteBool), 2-байтовый WordBool и 4-байтовый LongBool предусмотрены лишь для совместимости в целях взаимодействия с другими языками и платформами.
Что касается символьных типов данных, то в Delphi предусмотрено 2 их типа - ANSIChar и WideChar. Первый является однобайтовым и может хранить в себе 1 символ из множества символов ANSI, коих насчитывается 256. Второй же тип является 2-байтовым и предназначен для хранения 2-байтовых же символов Unicode. Как и в других случаях, Delphi имеет синоним для символьных типов - Char, который на сегодня является аналогом ANSIChar. Что касается присвоения значений, то обычные символы (буквы и цифры) присваивают переменным символьного типа как есть, лишь заключая их в одиночные кавычки. А специальные символы, например, возврат каретки (Enter) назначают при помощи их номера в таблице ANSI, и выделяют знаком решетки:
var x, y: Char; // x и y получают тип ANSIChar ... x := a; // обычные символы y := #13; // возврат каретки в таблице ANSI имеет номер 13
Наконец, еще одним, причем, в общем-то, уже не совсем простым типом данных являются строки. Строковые типы данных отличаются от символьных тем, что могут хранить не единичный символ, а множество символов. В Delphi имеется 3 типа строк: ShortString, AnsiString и WideString. Первый тип строк - ShortString - достался в наследство от языка Pascal и 16-битной Delphi 1.0. Такие строки могут иметь не более 255 символов, и занимают от 2 до 256 байт памяти, в зависимости от размера: Что касается современных строковых типов - AnsiString и WideString, то они могут иметь практически неограниченную длину (AnsiString - до 2 млрд. символов, WideString - до 1 млрд.) и занимать, соответственно, от 4 байт до 2 Гигабайт памяти. При этом по аналогии с символьными типами, тип AnsiString предназначен для хранения обычных строк, а WideString - для строк в формате Unicode. Ну и еще один тип строк - String является синонимом для типа AnsiString:
var str1: ShortString; // короткая строка var str2: AnsiString; // длинная строка var str3: String; // тоже длинная строка ... str1 := Начало.; // Строковые значения заключаются в одинарные кавычки str2 := Конец.; str3 := str1 + str2; // получим длинную строку, содержащую Начало.Конец.
В целом, несмотря на кажущееся разнообразие типов данных, на практике чаще всего ограничиваются всего лишь 5-6 основными типами. Это: Integer, Double, Boolean, Char, String, и иногда - еще и Currency.
