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

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

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


§8. Логический, символьный, перечисляемый типы и тип-диапазон.

Логический тип.

Переменная логического типа может содержать в себе два значения True (правда) или False (ложь). Переменной данного типа можно присвоить значение логического выражения. Так же данную переменную можно использовать в условиях. С логическими переменными можно применять логические операции. Для объявления логической переменной используется слово Boolean. Пример программы:


var a,b,c:boolean;


begin

  a:=true;

  b:=false;

  c:=a and b;

  if a then writeln('a = правда') else writeln('а = ложь');

  if b then writeln('b = правда') else writeln('b = ложь');

  if b then writeln('a и b = правда') else writeln('a и b = ложь');

end.

___________________________________________________________________

a = правда

b = ложь

a и b = ложь


Поскольку логический тип относится к порядковым типам, то его можно использовать в цикле For to do:


var a:boolean;

begin

  for a:=false to true do writeln(a);

end.

_____________________________________

False

True


Как было сказано, переменные какого-либо порядкового типа можно упорядочить по порядку. Это возможно потому, что у каждого значения порядкового типа есть свой порядковый номер. Так значению false соответствует порядковый номер 0, а значению true порядковый номер 1. Соответственно логические переменные можно сравнивать друг с другом:


var a,b,c:boolean;

begin

  a:=false;

  b:=true;

  c:=a<b;

  writeln('a<b=',c);

end.

____________________

a<b=True


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

Например, такая задача: если нажали кнопку и температура меньше заданного значения, то включить нагреватель. Примем, что переменная knopka будет логического типа и будет равна true, если кнопка нажата, и false если не нажата. Переменная t обозначает температуру, а tz обозначает заданную температуру. Составим логическое выражение:

knopka AND (t<tz)

Если случайно вместо слова AND появится знак сравнения, то результат будет другим. Например, переменные могут иметь следующие значения: Knopka = True; t = 10; tz = 21.

Тогда:                          knopka AND (t<tz) = True,

knopka < (t<tz) = False.

Как видно, результаты получились различные.


Символьный тип.

Переменная символьного типа может содержать в себе любой символ. Для объявления данной переменной используется слово Char. Для того, что бы переменной символьного типа присвоить какой-либо символ, его необходимо заключить в одинарные кавычки, например: c:=h.

Занимает переменная типа Char 1 байт (8 бит). Так как символьный тип относится к порядковым типам, то каждому символу соответствует свой порядковый номер. Всего в 8-ми битной переменной может содержаться 256 символов с порядковыми номерами 0 до 255. Номера символов от 0 до 127 соответствуют стандарту ASCII (American Standard Code for Information Interchange американский стандартный код для обмена информацией). Остальная часть символов зависит от особенностей компьютера.

К переменной символьного типа можно применить встроенную функцию chr(i), которая возвращает символ, порядковый номер которого указан в скобках.

Запоминать какой символ, какому порядковому номеру соответствует необязательно. Для этого рекомендую следующую программу, которую вы всегда можете воспроизвести:


var c:char;

    i:byte;

begin

for i:=32 to 255 do

  begin

   c:=chr(i);

   Write(i:3);

   write(c:2,' | ');

   if ((i-1) mod 10)=0 then writeln;

  end;

end.

________________________________________________________________________

32   |  33 ! |  34 " |  35 # |  36 $ |  37 % |  38 & |  39 ' |  40 ( |  41 ) |

42 * |  43 + |  44 , |  45 - |  46 . |  47 / |  48 0 |  49 1 |  50 2 |  51 3 |

52 4 |  53 5 |  54 6 |  55 7 |  56 8 |  57 9 |  58 : |  59 ; |  60 < |  61 = |

62 > |  63 ? |  64 @ |  65 A |  66 B |  67 C |  68 D |  69 E |  70 F |  71 G |

72 H |  73 I |  74 J |  75 K |  76 L |  77 M |  78 N |  79 O |  80 P |  81 Q |

82 R |  83 S |  84 T |  85 U |  86 V |  87 W |  88 X |  89 Y |  90 Z |  91 [ |

92 \ |  93 ] |  94 ^ |  95 _ |  96 ` |  97 a |  98 b |  99 c | 100 d | 101 e |

102 f | 103 g | 104 h | 105 i | 106 j | 107 k | 108 l | 109 m | 110 n | 111 o |

112 p | 113 q | 114 r | 115 s | 116 t | 117 u | 118 v | 119 w | 120 x | 121 y |

122 z | 123 { | 124 | | 125 } | 126 ~ | 127  | 128 Ђ | 129 Ѓ | 130 ‚ | 131 ѓ |

132 „ | 133 … | 134 † | 135 ‡ | 136 € | 137 ‰ | 138 Љ | 139 ‹ | 140 Њ | 141 Ќ |

142 Ћ | 143 Џ | 144 ђ | 145 | 146 | 147 “ | 148 ” | 149 | 150 | 151 |

152 ˜ | 153 ™ | 154 љ | 155 › | 156 њ | 157 ќ | 158 ћ | 159 џ | 160   | 161 Ў |

162 ў | 163 Ј | 164 ¤ | 165 Ґ | 166 ¦ | 167 § | 168 Ё | 169 © | 170 Є | 171 « |

172 ¬ | 173 ­ | 174 ® | 175 Ї | 176 ° | 177 ± | 178 І | 179 і | 180 ґ | 181 µ |

182 ¶ | 183 · | 184 ё | 185 № | 186 є | 187 » | 188 ј | 189 Ѕ | 190 ѕ | 191 ї |

192 А | 193 Б | 194 В | 195 Г | 196 Д | 197 Е | 198 Ж | 199 З | 200 И | 201 Й |

202 К | 203 Л | 204 М | 205 Н | 206 О | 207 П | 208 Р | 209 С | 210 Т | 211 У |

212 Ф | 213 Х | 214 Ц | 215 Ч | 216 Ш | 217 Щ | 218 Ъ | 219 Ы | 220 Ь | 221 Э |

222 Ю | 223 Я | 224 а | 225 б | 226 в | 227 г | 228 д | 229 е | 230 ж | 231 з |

232 и | 233 й | 234 к | 235 л | 236 м | 237 н | 238 о | 239 п | 240 р | 241 с |

242 т | 243 у | 244 ф | 245 х | 246 ц | 247 ч | 248 ш | 249 щ | 250 ъ | 251 ы |

252 ь | 253 э | 254 ю | 255 я |


Обратите внимание, что символы в таблице начинаются с порядкового номера 32, это потому, что первые 32 символа от 0 до 31 являются служебными и имеют специфические назначения. Об этих назначениях можно почитать в Википедии. Они были актуальны довольно давно и сейчас вряд ли вы будете ими пользоваться, поэтому писать о них я не буду.


Так же для работы с символами существуют ещё две функции:

  • UpCase(сh) если переменная сh является маленькой буквой, то функция возвращает такую же большую букву, если сh большая буква, то возвращает её же, если сh символ, то возвращает этот символ;
  • LowCase(сh) если переменная сh является большой буквой, то функция возвращает такую же маленькую букву, если сh маленькая буква или символ, то возвращает маленькую букву или символ соответственно.

К символам, которые являются буквами, применяют такое понятие как регистр. Если буква большая, то говорят верхний регистр, если буква маленькая, то говорят нижний регистр. Если говорить о данных функциях, то функция UpCase преобразует символ в верхний регистр, LowCase в нижний. Пример


Var c1,c2,c3:char;

begin

c1:='М'; c2:='в'; c3:='.';

writeln('          ',c1,' ',c2,' ',c3);

writeln('LowCase - ',LowCase(c1),' ',LowCase(c2),' ',LowCase(c3));

write  ('UpCase  - ',UpCase(c1),' ',UpCase(c2),' ',UpCase(c3));

end.

__________________________________________________________________

          М в .

LowCase - м в .

UpCase  - М В .


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


var c,d:char;

begin

  c:='А';

  d:='Б';

  if c<d then writeln('А<Б')

   else writeln('А>Б');

end.

____________________________

А<Б


Так же можно использовать переменные символьного типа в цикле For to do, например:


var c:char;

begin

  for c:='А' to 'Я' do

    begin

      write(c:2);

    end

end.

_______________________________________________________________

А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я




Сортировка символов.

Рассмотрим следующую задачу: есть 4 буквы, необходимо расположить их по алфавиту.

Расположение данных в каком-либо порядке называется сортировкой. В данном случае нам необходимо отсортировать 4 буквы. Существует множество алгоритмов сортировок. Сейчас мы рассмотрим один из них. Для интереса вы можете придумать и свой.

Предположим, буквы будут содержаться в четырёх переменных a, b, c, d. После сортировки они будут выведены по порядку, в начале a, затем b, c и d. Соответственно и отсортировать буквы мы должны таким образом, что бы они находились по алфавиту в этих переменных. Как будем это делать? Войдём в цикл и будем менять местами буквы до тех пор, пока они не встанут по алфавиту. Менять местами будем только в том случае, если они находятся не по алфавиту. Например, если в переменной a находится буква п, а в переменной b буква б, тогда буквы меняем местами. Затем будем сравнивать буквы в переменных b и c. Затем в c и d.

Поменять буквы местами можно через дополнительную переменную следующим образом:


  temp:=a;

  a:=b;

  b:=temp;


Цикла будем использовать While to do, т.к. изначально буквы уже могут оказаться расположены по порядку, соответственно первый проход цикла будет не нужен. Условие, при котором все буквы рассоложены по алфавиту, должно выглядеть следующим образом: (a<b) and (b<c) and (c<d).

Далее код программы реализующей всё вышесказанное:


program SortirovkaBookv;

var a,b,c,d,temp:char;


begin

  a:='к';

  b:='ф';

  c:='в';

  d:='а';

  while not((a<=b)and(b<=c)and(c<=d)) do

   begin

    if not(a<=b) then

      begin

        temp:=a;

        a:=b;

        b:=temp;

      end;

    if not(b<=c) then

      begin

        temp:=b;

        b:=c;

        c:=temp;

      end;

    if not(c<=d) then

      begin

        temp:=c;

        c:=d;

        d:=temp;

      end;

   end;

  writeln(a:2,b:2,c:2,d:2);

end.

_________________________________________

а в к ф


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


Перечисляемый тип.

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

Что бы программа была наглядной, существует перечисляемый тип. В случае с кнопкой мы можем заранее объявить, что эта переменная будет принимать два значения и каждому значению дать словесную форму. Например, если кнопка нажата, то переменная будет равна слову najata, если нет nenajata.

Как это делается? В разделе объявления переменных пишется название переменной, затем после двоеточия (в скобках через запятую перечисляются значения, которые может принимать данная переменная). Далее в тексте программы после оператора присваивания может писаться любое значение, которое было указано в скобках. Пример:


var knopka:(najata,nenajata);

begin

  knopka:=najata;

  case knopka of

    najata:writeln('Кнопка - нажата.');

    nenajata:writeln('Кнопка не нажата.');

  end

end.

___________________________________________

Кнопка - нажата.


Теперь представьте себе, что у вас кнопок много. Для того, что бы в разделе объявления переменных не писать для каждой кнопки возможные значения, можно перечислить их имена через запятую. А можно вначале создать свой тип в разделе объявления типов, а затем создать переменные этого типа. Раздел объявления типов начинается со слова Type. Для того, что бы создать свой тип необходимо написать название типа затем знак равно, а потом в скобках через запятую перечислить необходимые значения. Например:


Type knopka = (najata,nenajata);

var knopka_1,knopka_2:knopka;

begin

  knopka_1:=najata;

  knopka_2:=nenajata;

  case knopka_1 of

    najata:writeln('Кнопка 1 - нажата.');

    nenajata:writeln('Кнопка 1 не нажата.');

  end

  case knopka_2 of

    najata:writeln('Кнопка 2 - нажата.');

    nenajata:writeln('Кнопка 2 не нажата.');

  end

end.

_____________________________________________

Кнопка 1 - нажата.

Кнопка 2 не нажата.


Так как перечисляемый тип является порядковым, у каждого значения существует свой порядковый номер. Порядковый номер 0 присваивается тому значению, которое в скобках написано первым, порядковый номер 1 тому, которое написано вторым, и т.д. Всего в перечисляемом типе можно вписать 65536 значений.

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


knopka_1:=knopka(0);


Однако тут есть нюанс, если вы тип не создали, а вписали возможные значения прямо в разделе объявления переменных, то по порядковому номеру значение присвоить не удастся.

Ещё, стоит отметить, что при выводе на экран переменной перечисляемого типа будет выведен не порядковый номер значения, а само значение, например:


var x:(v,b);

begin

x:=v;

writeln(x);

end.

____________

V


Тип-диапазон.

Тип-диапазон может быть подмножеством любого базового порядкового типа. При объявлении типа-диапазон указывается минимальное и максимальное значения. Переменная данного типа наследует все свойства своего базового типа, однако она сможет принимать значения только, входящие в указанный диапазон. Главная цель использования данного типа это контроль данных. Программа не сможет присвоить значение, выходящее за рамки, выбранного диапазона.

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


Type

  cifry = 25..30;

Var

  c:cifry;

begin

  c:=30;

  Writeln(c);

end.

_______________

30


Так же как и в случае с перечисляемым типом, объявлять тип-диапазон в разделе объявления типов необязательно. Можно при объявлении переменной, после двоеточия в скобках указать минимальное и максимальное значения, например:


Var

  alfavit:'А'..'Я';

begin

  alfavit:='Ю';

  Writeln(alfavit);

end.

___________________

Ю


Ещё один пример с базовым перечисляемым типом:


Type

  DniNedely = (Pn,Vt,Sr,Cht,Pt,Sb,Vs);

Var

  Rabochie:Pn..Pt;

  Vihodnie:Sb..Vs;

begin

  Rabochie:=Sr;

  Write(Rabochie,' ');

  Vihodnie:=Vs;

  Write(Vihodnie,' ');

end.

______________________________________

Sr Vs


Теперь сделаю небольшое отступление. Выше было сказано, что цель использования типа-диапазон это контроль данных. Переменная данного типа не может принимать значения выходящие за рамки указанного диапазона. Однако в PascalABC.NET (версия 2.0, сборка 550(16.04.2013)  версия, в которой я пишу примеры для этой книги) этого контроля не происходит. Переменная типа-диапазон здесь может принимать любые значения своего базового типа.

Дело в том, что система PascalABC.NET была написана для обучения и не предназначена для реализации настоящих рабочих программ. Так же стоит заметить, если вы читали лицензионное соглашение, которое выходит при установке, то вы должны были обратить внимание на следующие строки:


4. Система PascalABC.NET поставляется по принципу "as is".

Никаких гарантий не прилагается и не предусматривается.

Вы используете это программное обеспечение на свой риск.

Авторы не будут отвечать ни за какие потери или искажения

данных, любую упущенную выгоду в процессе использования

или неправильного использования этого программного обеспечения.


Как видите, ни каких гарантий за этот программный продукт вам никто не даёт.

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

High(x)  возвращает максимальное значение которое может принимать переменная типа-диапазон, указанная в скобках;

Low(x) возвращает минимальное значение которое может принимать переменная типа-диапазон, указанная в скобках.

В той версии PascalABC.NET, в которой я пишу примеры для этой книги, этих функций нет.

Есть ещё один нюанс. В Pascal есть две процедуры Read и Readln. Обе они осуществляют считывание данных с клавиатуры. Однако у них есть разница. Процедура Read считывает данные и оставляет курсор на том же месте. Процедура Readln после считывания данных переводит курсор на новую строчку. В PascalABC.NET обе процедуры действуют аналогично и переводят курсор на новую строчку. Далее приведу пример программы и два варианта результата работы программы. В первом случае вариант работы тот, который выдаёт PascalABC.NET, а во втором случае, как должно быть:


var i,k:integer;

begin

write('Введите два числа: ');

read(i);

readln(k);

write('Вы ввели: ',i,' ',k);

end.

________________________________

Введите два числа: 3

4

Вы ввели: 3 4

________________________________

Введите два числа: 34

Вы ввели: 3 4


Как видно результаты работы различные.

Тем не менее, не думайте, что я ошибся с выбором системы для обучения. Это действительно отличная система, т.к. здесь от ученика скрыты многие нюансы, которые на первых порах будут только отвлекать, и не давать сосредоточиться на нужном. Здесь в полной мере можно детально изучить язык Pascal и научиться программировать. Аналогов данной системы я не встречал. К тому же, на тот момент, когда вы будете читать эту книгу, скорее всего, выйдет новая версия, в которой эти недочёты будут устранены.

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


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


Задачи.

1. Вывести на экран русский алфавит, вначале большие буквы, в следующей строчке маленькие.

2. Вывести на экран латинский алфавит, большие и маленькие буквы должны быть рядом.

3. Вывести на экран символы, не являющиеся буквами.

4. В параграфе была приведена программа SortirovkaBookv. Необходимо составить блок-схему алгоритма самой сортировки и усовершенствовать программу так, что бы буквы вводились с клавиатуры.

5. Придумать программы, демонстрирующие использование переменных логического и перечисляемого типов.


Решение.

1.

var c:char;

begin

  for c:='А' to 'Я' do write(c,' ');

  writeln;

  for c:='а' to 'я' do write(c,' ');

end.

_________________________________________________________________________

А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я

а б в г д е ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ы ь э ю я


2.

var i:byte;

begin

  for i:=65 to 90 do write(char(i),char(i+32),'  ');

end.

_________________________________________________________________________

Aa  Bb  Cc  Dd  Ee  Ff  Gg  Hh  Ii  Jj  Kk  Ll  Mm  Nn  Oo  Pp  Qq  Rr  Ss  Tt  Uu  Vv  Ww  Xx  Yy  Zz 


3.

var i:byte;

begin

  for i:=32 to 64 do write(chr(i),' ');

  for i:=91 to 96 do write(chr(i),' ');

  for i:=123 to 191 do write(chr(i),' ');

end.

_________________________________________________________________________

  ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ [ \ ] ^ _ ` { | } ~  Ђ Ѓ ‚ ѓ „ … † ‡ € ‰ Љ ‹ Њ Ќ Ћ Џ ђ “ ” ˜ ™ љ › њ ќ ћ џ   Ў ў Ј ¤ Ґ ¦ § Ё © Є « ¬ ­ ® Ї ° ± І і ґ µ ¶ · ё № є » ј Ѕ ѕ ї


4. 5. Данные задачи решите самостоятельно.




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