Учебник по программированию.

Первые шаги. Язык программирования PascalABC.

 

 

Учебник по программированию. Создание сайтов. Первые шаги.
Предыдущий параграф Назад в содержание Следующий параграф


Глава II. Типы данных.


§7. Типы данных. Порядковые типы языка Pascal.

Типы данных.

Во втором параграфе мы немного узнали о типах данных. Это было необходимо, что бы начать программировать. В данном параграфе мы подробно рассмотрим все типы данных существующие в Pascal.

Для начала выясним, что такое сам термин «типы данных». Для этого перечислим ряд аспектов, некоторые из которых уже были приведены во втором параграфе.

Память в компьютере состоит из элементарных ячеек, в которых может содержаться только единичка или нолик. У каждой ячейки существует свой уникальный адрес. Размер памяти в одну ячейку называется битом. Размер памяти в 8 ячеек называется байтом. 1024 байта составляют килобайт. А 1024 килобайта составляют один мегабайт. 1024 мегабайта один гигабайт, а 1024 гигабайта один тиробайт.

У вас должен возникнуть уместный вопрос: почему в одном килобайте 1024 байта. Дело в том, что приставка, например, кило в обычной жизни обозначает, что число надо помножить на тысячу. Например, 5 километров это 5000 метров. А вот при обозначении количества памяти приставка кило обозначает, что число надо помножить на 1024. Такое число возникло не просто случайно, оно равно двум в степени десять . В своё время первые программисты договорились и решили объём памяти в 1024 байта называть одним килобайтом. Соответственно 1 килобайт, помноженный на один килобайт, будет равен одному мегабайту. А один мегабайт, помноженный на один мегабайт, будет равен одному гигабайту. И так далее.

Причиной такой договорённости послужила структура самих компьютеров. И первым программистам было удобно использовать именно это число.

Для примера можем посчитать, сколько элементарных ячеек содержится в оперативной памяти в один гигабайт. Один гигабайт это 1024 мегабайта. Один мегабайт это 1024 килобайта. Соответственно в одном гигабайте содержится 1024 х 1024 = 1048576 килобайт. Ещё раз помножим на 1024 и получим 1073741824 байта. Помножим это число на 8 получим 8589934592 бит. Вот столько элементарных ячеек памяти содержится в оперативной памяти объёмом в один гигабайт.

Двигаемся дальше. Представим себе, что нам необходимо обработать 24 элементарных ячейки памяти, или говоря другими словами 24 бита. Содержание этих ячеек можно представить в виде списка. Например, он может быть таким:


00000001000000100001010000001101


Теперь подумайте, как из этого, на первый взгляд хаотичного списка, понять, что здесь записано. Может быть, здесь дата чьего-то дня рождения, или здесь имя какого-то человека. Здесь может быть всё что угодно от имени человека, до цифровой фотографии. Обратите внимание, отсюда и пошло название цифровой фотографии. Т.е. фотография храниться в цифрах.

Для того, что бы компьютеру было понятно какая информация записана в памяти как раз и существуют типы данных. Например, если мы разделим этот список на 4 группы по 8 бит тогда получим 4 байта информации. Для наглядности перепишем список с пробелами:


00000001 00000010 00010100 00001101


Для примера мы можем рассмотреть такой список следующим образом: всего здесь получилось четыре двоичных числа. Допустим, первое число будет обозначать число месяца, второе месяц, третье первые две цифры года, четвёртое   вторые две цифры года. Соответственно данный список мы рассмотрели как какая-то дата. В таком случае нам понятно, что обозначает этот на, первый взгляд, бессмысленный, хаотичный список единичек и ноликов.

В принципе мы можем читать этот список как угодно. Можно по два бита можно по одному или по пять. Обозначать этот список может тоже всё, что угодно, главное, мы должны заранее договориться о том, как его читать и что он будет обозначать.

Именно такая договорённость и есть типы данных. Т.е. используя определённый тип мы «договариваемся с компьютером», что определённое количество бит, будут обозначать определённое число или букву, или ещё что-то другое.

О двоичных цифрах сейчас мы говорить не будем, потому что на данном этапе в этом нет необходимости. Главное вы должны усвоить, что если вы хотите использовать, допустим, целое число, то вы должны выбрать тип целых чисел, если какое-либо дробное число, то тип real, если символ, то тип char и так далее.

Теперь перейдём непосредственно к изучению типов данных. В Pascal ряд типов по некоторым признакам можно объединить в группы. Далее приведу схему, на которой наглядно видны все типы и группы.



Данной схемой вы можете пользоваться на первый порах, для выбора нужного типа, в дальнейшем она запомниться сама собой. А так же логика объединения типов в группы так же станет вам понятна.


Порядковые типы.

Особенностью порядковых типов является то, что переменная любого порядкового типа имеет конечное число возможных значений и то, что несколько переменных какого-либо порядкового типа можно расположить в порядке убывания или возрастания, т.е. упорядочить (отсюда и название). А так же то, что только переменные порядковых типов могут быть параметром цикла For to do.


Целые типы.

Как уже было сказано, переменная целого типа содержит в себе целое число. Мы изучили уже тип целых чисел Byte. Переменная такого типа может содержать в себе целое число от 0 до 255 включительно. Занимает оно в памяти компьютера 1 байт. Если нам понадобиться отрицательное число или число больше 255, тогда мы можем использовать тип Integer. Переменная такого типа может содержать в себе целые числа от -32768 до +32767 включительно. Однако такая переменная будет занимать в памяти 2 байта.

Далее таблица, в которой приведены все целые типы языка Pascal:


Название

Перевод

названия на русский

Размер

занимаемой

памяти в байтах

Диапазон

значений

от

до

Byte

Байт

1

0

255

ShortInt

Короткое целое

1

-128

+127

Word

Слово

2

0

65 535

Integer

Целое

2

-32 768

+32 767

LongInt

Длинное целое

4

-2 147 483 648

+2 147 483 647


Для удобства запоминания в таблице приведён перевод названий типов. В столбце диапазон значений приведённые числа входят в этот диапазон. Например, переменная типа Integer может содержать в себе число 32 767, а вот число 32768 уже не может.

Если вы объявили переменную какого-либо типа, то не будет ни какой разницы, какое число в ней записано, 0 или, например, 199. В любом случае оно будет занимать в памяти одно и то же число байт. Поэтому вы должны выбирать тип данных исходя из того, какое максимальное значение может принять переменная в ходе работы данной программы. Это нужно для того, что бы ни занимать лишнюю память.

Так же стоит отметить, что операции с большими числами могут занимать больше времени, чем с маленькими. Поэтому не следует использовать, например, тип LongInt, если вы заведомо знаете, что переменная не будет принимать значения больше 32 767.

Конечно в небольшой программе, которая будет работать на мощном современном компьютере, выбор не соответствующего типа (большего по размеру), ни как не скажется на работе этой программы, однако в больших программах эта оплошность может сказаться на быстродействии программы в целом. Например, пользователь будет ждать результата не 3 секунды, а 10. Конечно, если он его ждёт один раз в день то особо он не расстроится, а если он  в течение всего дня должен получать результаты, то представьте, на сколько больше результатов он получить, если вы правильно выберите тип данных. То же самое относится и к типам данных, которые будут изучены позже.

С переменными целых типов можно осуществлять любые арифметические операции, рассмотренные в параграфе 3. Однако значение этой операции не всегда можно присвоить переменной целого типа. Например, если мы поделим 10 на 3, то мы получим дробное число. Поэтому будьте внимательны при выборе типов данных.

Вместо операции деления, с целыми числами можно осуществлять следующие две операции:

div целочисленное деление. (Получаем значение от деления как бы без дробной части);

mod получение остатка от целочисленного деления.

Все мы умеем делить столбиком. Для понимания этих двух операций можно привести следующий рисунок:



Если использовать запись как в обычной математике, то:

9 div 4 = 2;

9 mod 4 =1.

Далее пример программы:


Var

  i,f:Integer;

begin

  Writeln('Введите два целых числа');

  Read(i,f);

  Writeln(i,'/',f,'=',i div f,' остаток ' ,i mod f);

end.

____________________________________________________

Введите два целых числа

13

5

13/5=2 остаток 3

Так же есть ещё одна функция для работы с целыми типами Odd, которая возвращает True, если число нечётное и False, если число чётное. Пример:


var i:integer;

begin

  i:=10;

  If odd(i) then writeln('Число ',i,' - нечётное.')

    else writeln('Число ',i,' - чётное.');

end.

___________________________________________________

Число 10 - чётное.


Стоит отметить следующий нюанс: если переменная целого типа имеет последнее значение диапазона, то при увеличении этой переменной на единицу она примет первое значение диапазона. И наоборот если  первое значение, то при уменьшении на единицу последнее. Например, если переменная А типа Byte имеет значение 255, тогда А+1 будет равно 0. Или если увеличить на два, то А+2=1. Ещё пример: если А=250, то А+20=14. Ещё пример, если А=0, то А-1=255. В таких ситуациях компилятор ошибку не выдаёт. При выполнении программы ошибки тоже не будет. Просто вы получите не правильное значение. Это обстоятельство так же должно быть критерием выбора правильного типа.

Как уже было сказано, в цикле For to do можно использовать переменную любого порядкового типа. Однако есть один нюанс. Если вы укажете после слова to число, выходящее за рамки возможных значений типа переменной, стоящей после слова For, то этот цикло не будет выполнен ни разу вообще. В данной ситуации только будет выполнен оператор присваивания находящийся после слова For, причём никаких сообщений об ошибках вы не получите. Например:


Var

  b:byte;

begin

  b:=2;

  writeln(b);

  For b:=-5 to 5 do Writeln(b);

  Writeln(b);

end.

______________________________

2

251


Обратите внимание, что код цикла выполнен не был, а переменной b было присвоено значение 251. Что произошло? В цикле For to do мы попытались присвоить переменной b значение, выходящее за рамки «рабочего» диапазона типа byte. Что сделал компьютер? Он, как бы, выполнил следующее арифметическое выражение: b=0-5. И произошло то, что было описано в предыдущем абзаце. Т.е. b стало равно 251, как это видно из результата работы программы.

Теперь должно быть понятно, почему код цикла не был выполнен ни разу. Прежде чем выполнять код цикла происходит сравнение значения переменной с тем, что стоит после слова to. В данной ситуации переменная b оказалась больше числа 5.


Вывод целых чисел в виде таблицы.

Рассмотрим задачу, которая сформулирована следующим образом: необходимо вывести на экран таблицу чисел от 1 до 100. В каждой строчке должно находиться по 10 чисел, соответственно должно получиться 10 столбиков.

Для решения задачи будем рассуждать следующим образом: мы можем с помощью процедур write и writeln вывести каждое число в отдельности в нужной последовательности. Однако нам необходимо, автоматизировать этот процесс, и что бы код занимал, как можно меньше строчек. Поэтому нам необходимо использовать цикл. В данной ситуации, при работе с целыми числами, наилучшим образом подходит цикл For to do.

Попробуем с помощью этого цикла вывести десять чисел от 1 до 10 в одну строчку:


var i:integer;

begin

  for i:=1 to 10 do

    write(i:4);

end.

________________________________________

   1   2   3   4   5   6   7   8   9  10


Обратите внимание, что для вывода переменной i на экран задано 4 символа. Это для того, что бы последнее число 100 было отделено от предыдущего 99 одним пробелом.

Мы организовали автоматический вывод 10 чисел в одну строчку. Теперь надо подумать, как вывести все 100 чисел. Для этого нам необходимо после вывода каждых новых десяти чисел переходить на новую строчку. Сделаем это по следующему условию: если число делиться без остатка на 10, то вызываем процедуру Writeln:


var i:integer;

begin

  for i:=1 to 100 do

    begin

      write(i:4);

      if (i mod 10) = 0 then writeln;

    end;

end.

_________________________________________

   1   2   3   4   5   6   7   8   9  10

  11  12  13  14  15  16  17  18  19  20

  21  22  23  24  25  26  27  28  29  30

  31  32  33  34  35  36  37  38  39  40

  41  42  43  44  45  46  47  48  49  50

  51  52  53  54  55  56  57  58  59  60

  61  62  63  64  65  66  67  68  69  70

  71  72  73  74  75  76  77  78  79  80

  81  82  83  84  85  86  87  88  89  90

  91  92  93  94  95  96  97  98  99 100


Для чего я привёл пример этой программы. Во-первых, вам придётся часто выводить различные списки в виде таблиц, и эта программа является примером того, как это делается. Во-вторых, я хотел показать, как происходит процесс разработки программ. Вначале мы написали программу вывода одной строчки и убедились, что она работает правильно. Затем мы усовершенствовали программу, и она стала выводить весь список целиком. Именно таким образом и происходи процесс разработки программ. В начале, реализуется какое-то элементарное действие, затем оно усложняется и добавляются новые. И каждый раз программа проверяется на работоспособность.


В данном параграфе мы разобрали, что такое типы данных. Узнали, какие типы существуют в Pascal. Изучили целые типы и научились автоматически выводить список на экран.


Задачи.

1. Пользователь вводит целое число, не используя функцию Odd, определить, является число чётным или нет.

2. Имеем 4 числа. В первой строчке вывести числа, которые делятся на 3 без остатка, во второй которые делятся на три с остатком. Если чисел, которые делятся без остатка или делятся с остатком, нет, то вывести соответствующее сообщение. В третьей строчке под числом, которое делится с остатком вывести остаток от деления на 3.

3. Составьте свою функцию определения чётное число или нет на основе операции mod, а так же программу, демонстрирующую пример использования этой функции.

4. Вывести на экран только чётные числа от 1 до 100 в виде таблицы. В таблице должно быть 9 столбиков.


Решение.

1.

var i:integer;

begin

  writeln('Введите целое число.');

  read(i);

  if (i mod 2)=0 then writeln('Число ',i,' - чётное.')

   else writeln('Число ',i,' - нечётное.');

end.

______________________________________________________

Введите целое число.

57

Число 57 - нечётное.


2.

var i,k,l,m:integer;

    s1,s2:longint;

begin

  i:=3;k:=45;l:=21;m:=1;

  Writeln('Имеем следующие числа: ',i,' ',k,' ',l,' ',m);

  s1:=0;s2:=0;

  if (i mod 3) = 0 then s1:=s1+1 else s2:=s2+1;

  if (k mod 3) = 0 then s1:=s1+1 else s2:=s2+1;

  if (l mod 3) = 0 then s1:=s1+1 else s2:=s2+1;

  if (m mod 3) = 0 then s1:=s1+1 else s2:=s2+1;

  if s1 = 0 then write('Чисел, которые делятся на 3 без остатка нет.')

    else write('Делятся на 3 без остатка: ');

  if (i mod 3) = 0 then write(i,' ');

  if (k mod 3) = 0 then write(k,' ');

  if (l mod 3) = 0 then write(l,' ');

  if (m mod 3) = 0 then write(m,' ');

  writeln;

  if s2 = 0 then write('Чисел, которые делятся на 3 с остатком нет.')

    else write('Делятся на 3 с остатком: ');

  if (i mod 3) <> 0 then write(i:4);

  if (k mod 3) <> 0 then write(k:4);

  if (l mod 3) <> 0 then write(l:4);

  if (m mod 3) <> 0 then write(m:4);

  writeln;

  write('                остаток: ');

  if (i mod 3) <> 0 then write((i mod 3):4);

  if (k mod 3) <> 0 then write((k mod 3):4);

  if (l mod 3) <> 0 then write((l mod 3):4);

  if (m mod 3) <> 0 then write((m mod 3):4);

end.

_________________________________________________________________________

Имеем следующие числа: 3 45 21 1

Делятся на 3 без остатка: 3 45 21

Делятся на 3 с остатком:    1

                остаток:    1


3.

Function chetnost(i:integer):boolean;

begin

If (i mod 2)=0 then chetnost:=True

  else chetnost:=False;

end;

Var i:integer; b:boolean;

begin

  writeln('Введите целое число');

  read(i);

  b:=chetnost(i);

  if b then writeln('Число ',i,' - чётное.')

    else writeln('Число ',i,' - нечётное.');

end.

_____________________________________________

Введите целое число

3

Число 3 - нечётное.


4.

var i:integer;

begin

  for i:=1 to 100 do

    begin

      if not odd(i) then write(i:4);

      if (i mod 18) = 0 then writeln;

    end;

end.

_______________________________________

   2   4   6   8  10  12  14  16  18

  20  22  24  26  28  30  32  34  36

  38  40  42  44  46  48  50  52  54

  56  58  60  62  64  66  68  70  72

  74  76  78  80  82  84  86  88  90

  92  94  96  98 100




Предыдущий параграф Назад в содержание Следующий параграф