Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
программирование лекция 2.doc
Скачиваний:
14
Добавлен:
08.03.2016
Размер:
162.82 Кб
Скачать

Правила формального описания синтаксиса языка программирования

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

  • символы в кавычках переносятся в конструкцию языка так, как они записаны. Кавычки при этом отбрасываются. Например, "while" означает, что в конструкции языка присутствует while;

  • имена, записанные слитно русскими и латинскими буквами, обозначают различные конструкции языка. Например, оператор_цикла;

  • квадратные скобки охватывают элементы языка, которые могут повторяться 0 или 1 раз. Например, "AB"["C"] означает, что в конструкции языка может присутствовать или AB или ABC;

  • фигурные скобки охватывают элементы языка, которые могут повторяться 0 или много раз. Например, "AB"{"C"} означает, что в конструкции языка может присутствовать или AB, или ABC, или ABCC и т.д.;

  • символ | обозначает или, то есть используется для задания альтернативных значений из списка элементов, разделенных знаком |. Например, "AB"|"C"|"ff" означает, что в конструкции языка может присутствовать или AB или C или ff;

  • круглые скобки используются для группировки. Например, "A"("B"|"C")"D" означает, что в конструкции языка может присутствовать или ABD или ACD;

  • многоточие используется для обозначения очевидных пропущенных значений в перечислении;

  • символ = обозначает присвоить. Например, буква = "A"|"B"|"C".

В дальнейшем, синтаксис языка Си будет описываться либо с помощью примеров, либо с помощью расширенной формы Бэкуса-Наура. В последнем случае это будет помечаться аббревиатурой БНФ.

Идентификаторы или имена служат для обозначения различных объектов программ: переменных (ячеек памяти), адресов, функций, файлов и т.д., иначе говоря – данных и действий над данными.

Имена должны начинаться с букв латинского алфавита или знака подчеркивания, далее допускается использовать и арабские цифры:

БНФ:

имя = ( буква | "_" ) { буква | цифра | "_" }

буква = |"A"|"B"|...|"Y"|"Z"|"a"|"b"|...|"y"|"z"

цифра = "0"|"1"|...|"9"

При этом прописные и строчные буквы считаются разными.

Длина имени в ANSI стандарте языка Си не ограничена. В Турбо Си имя не может быть длиннее 32 символов. Например: a, a1, _a, a_b.

Выбор имен должен производиться так, чтобы имя как можно точнее соответствовало смыслу объекта или действия, которое оно обозначает. Например: speed_of_body, SpeedOfBody, BodySpeed.

Экономия на длине имен – плохой стиль программирования.

Системы счисления. Представление данных в эвм.

В современном мире для записи числовой информации используют позиционные системы счисления, в которых числа записываются с помощью ограниченного количества цифр, а фактический вес цифры в результирующем числе определяется не только ее значением, но и позицией, которую она занимает в записи числа. Вес соседних позиций отличается в M раз, где M – основание системы счисления.

Например, имеем запись числа

an ... a3 a2 a1 a0

тогда его значение можно вычислить по следующей формуле

an*Mn + ... + a3*M3 + a2*M2 + a1*M1 + a0*M0 ,

где an...a0 - цифры из записи числа.

Максимальное значение числа без знака, которое может быть представлено N разрядами позиционной системы счисления определяется как

MN - 1 .

В общепринятой десятичной системе счисления для записи чисел используются десять цифр 0,1,2,3,4,5,6,7,8,9. Основание системы счисления – 10. Значение числа определяется так:

9721 (10) = 9*103 + 7*102 + 2*101 + 1*100

В вычислительной технике, кроме десятичной, широко используются двоичная, восьмеричная и шестнадцатеричная системы счисления.

Все данные внутри ЭВМ представлены в двоичной системе, поскольку в этом случае достаточно всего двух цифр, а электронные схемы, как правило, тоже имеют два различных состояния. Десятичная, восьмеричная и шестнадцатеричная системы используются при выводе информации для пользователя, недостающие цифры шестнадцатеричной системы счисления заменяются буквами A,B,C,D,E,F.

Приведем несколько примеров:

1010 (2) = 1*23 + 0*22 + 1*21 + 0*20 = 10 (10)

2701 (8) = 2*83 + 7*82 + 0*81 + 1*80 = 1473 (10)

F4A (16) = 15*162 + 4*161 + 10*160 = 3914 (10)

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

1473 : 8 = 184 остаток 1

184 : 8 = 23 остаток 0

23 : 8 = 2 остаток 7 8

2 : 8 = 0 остаток 2

---------------------------

1473 (10) = 2701 (8)

Для перевода чисел из десятичной системы счисления в двоичную используют так называемый "алгоритм замещения", состоящий из следующей последовательности действий:

  1. Делим десятичное число А на 2. Частное Q запоминаем для следующего шага, а остаток a записываем как младший бит двоичного числа.

  2. Если частное q не равно 0, принимаем его за новое делимое и повторяем процедуру, описанную в шаге 1. Каждый новый остаток (0 или1) записывается в разряды двоичного числа в направлении от младшего бита к старшему.

  3. Алгоритм продолжается до тех пор, пока в результате выполнения шагов 1 и 2 не получится частное Q = 0 и остаток a = 1.

Например, требуется перевести десятичное число 247 в двоичное. В соответствии с приведенным алгоритмом получим: 

24710 : 2 = 12310

24710 - 24610 = 1, остаток 1 записываем в МБ двоичного числа.

12310 : 2 = 6110

12310 - 12210 = 1, остаток 1 записываем в следующий после МБ разряд двоичного числа.

6110 : 2 = 3010

6110 - 6010 = 1, остаток 1 записываем в старший разряд двоичного числа.

3010 : 2 = 1510

3010 - 3010 = 0, остаток 0 записываем в старший разряд двоичного числа.

1510 : 2 = 710

1510 - 1410 = 1, остаток 1 записываем в старший разряд двоичного числа.

710 : 2 = 310

710 - 610 = 1, остаток 1 записываем в старший разряд двоичного числа.

310 : 2 = 110

310 - 210 = 1, остаток 1 записываем в старший разряд двоичного числа.

110 : 2 = 010, остаток 1 записываем в старший разряд двоичного числа.

Таким образом, искомое двоичное число равно 111101112

Для перевода чисел из десятичной системы счисления в шестнадцатеричную используют тот же "алгоритм замещения", что и при переводе из десятичной системы счисления в двоичную и восьмеричную, только в качестве делителя используют 16, основание шестнадцатеричной системы счисления:

  1. Делим десятичное число А на 16. Частное Q запоминаем для следующего шага, а остаток a записываем как младший бит шестнадцатеричного числа.

  2. Если частное q не равно 0, принимаем его за новое делимое и повторяем процедуру, описанную в шаге 1. Каждый новый остаток записывается в разряды шестнадцатеричного числа в направлении от младшего бита к старшему.

  3. Алгоритм продолжается до тех пор, пока в результате выполнения шагов 1 и 2 не получится частное Q = 0 и остаток a меньше 16.

Например, требуется перевести десятичное число 32767 в шестнадцатеричное. В соответствии с приведенным алгоритмом получим: 

3276710 : 16 = 204710

3276710 - 3275210 = 15, остаток 15 в виде F записываем в МБ шестнадцатеричного числа.

204710 : 16 = 12710

204710 - 203210 = 15, остаток 15 в виде F записываем в следующий после МБ разряд шестнадцатеричного числа.

12710 : 16 = 710

12710 - 11210 = 15, остаток 15 в виде F записываем в старший разряд шестнадцатеричного числа.

710 : 16 = 010, остаток 7 записываем в старший разряд шестнадцатеричного числа.

Таким образом, искомое шестнадцатеричное число равно 7FFF16

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

0101 1011 1111 1100 (2) = 5BCF (16)

5 11=B 15=F 12=C

0 101 101 111 111 100 (2) = 55774 (8)

5 5 7 7 4

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

0101101111111100(2)=(0·215)+(1·214)+(0·213)+(1·212)+(1·211)+(0·210)+(1·29)+(1·28)+(1·27)+(1·26)+(1·25)+(1·24)+(1·23)+(1·22)+(0·21)+(0·20)= =0+16384+0+4096+2048+0+512+256+128+64+32+16+8+4+0+0=23548 (10)

Из этого примера видно, что десятичная система счисления более компактно отображает числа – 5 цифр (т.е. бит) вместо 16 цифр в двоичной системе счисления.

В любой системе счисления нужно уметь представлять не только целые числа, но и дробные. С математической точки зрения это ординарная задача, которая давно решена. Однако с точки зрения компьютерной техники это далеко не тривиальная проблема, во многом связанная с архитектурой компьютера. Ресурсы компьютеров не бесконечны, и основной трудностью является представление периодических и непериодических дробей. Следовательно, такие дроби следует округлять, задавать класс точности участвующих (и могущих появиться в результате вычислений!) чисел без потери точности вычислений, а также следить за тем, чтобы потеря точности не произошла при переводе чисел из одной системы счисления в другую. Особенно важно аккуратно производить вычисления при операциях с плавающей точкой.

Запишем формулу представления дробного числа в позиционной системе счисления: 

Ap = an-1·pn-1+an-2·pn-2 +...+ a1·p1+a0·p0 +a-1·p-1+a-2·p-2 + ... + a-m·p-m.

В случае десятичной системы счисления получим: 

24,732 = 2·101+4·100+7·10-1+3·10-2

Перевод дробного числа из двоичной системы счисления в десятичную производится по следующей схеме: 

101101,1012 = 1·25+0·24+1·23+1·22+0·21+1·20+1·2-1+0·2-2+1·2-3=45,625

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

 Сначала переводится целая часть десятичной дроби в двоичную систему счисления;

 Затем дробная часть десятичной дроби умножается на основание двоичной системы счисления;

 В полученном произведении выделяется целая часть, которая принимается в качестве значения первого после запятой разряда числа в двоичной системе счисления;

 Алгоритм завершается, если дробная часть полученного произведения равна нулю или если достигнута требуемая точность вычислений. В противном случае вычисления продолжаются с предыдущего шага.

Пример: Требуется перевести дробное десятичное число 206,116 в дробное двоичное число.

Перевод целой части дает 20610=110011102 по ранее описанным алгоритмам; дробную часть умножаем на основание 2, занося целые части произведения в разряды после запятой искомого дробного двоичного числа: 

.116 • 2 = 0.232

.232 • 2 = 0.464

.464 • 2 = 0.928

.928 • 2 = 1.856

.856 • 2 = 1.712

.712 • 2 = 1.424

.424 • 2 = 0.848

.848 • 2 = 1.696

.696 • 2 = 1.392

.784 • 2 = 0.784

и т.д.

Получим: 20610=11001110,00011101102

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

Пусть требуется перевести двоичное число 101011011001101101111001010110010112 в восьмеричную систему счисления. Для этого следует разбить это двоичное число на триады, начиная с младшего бита (МБ). Получим: 

010 101 101 100 110 110 111 100 101 011 001 0112

2 5 5 4 6 6 7 4 5 3 1 38

Если старшая триада не заполнена до конца, следует дописать в ее старшие разряды нули, как в нашем случае. После этого необходимо заменить двоичные триады, начиная с младшей, на числа, равные им в восьмеричной системе: 

000 – 0

001 – 1

010 – 2

011 – 3

100 – 4

101 – 5

110 – 6

111 – 7 Таким образом, 101011011001101101111001010110010112=2554667453138

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

0101 0110 1100 1101 1011 1100 1010 1100 10112

5 6 C D B C A C B16

0000 – 0

0001 – 1

0010 – 2

0011 – 3

0100 – 4

0101 – 5

0110 – 6

0111 – 7

1000 – 8

1001 – 9

1010 – A

1011 – B

1100 – C

1101 – D

1110 – E

1111 – F

Заменяя двоичные тетрады на их шестнадцатеричные значения, получим искомое шестнадцатеричное число: 101011011001101101111001010110010112=56CDBCACB16

Пусть требуется перевести восьмеричное число 24738 в двоичное число. Поскольку 28 = 010248 = 100278 = 1112... Таким образом, 24738 = 101001110112

Двоичная система

Восьмеричная система

Десятичная система

Шестнадцатеричная система

0

0

0

0

1

1

1

1

10

2

2

2

11

3

3

3

100

4

4

4

101

5

5

5

110

6

6

6

111

7

7

7

1000

10

8

8

1001

11

9

9

1010

12

10

A

1011

13

11

B

1100

14

12

C

1101

15

13

D

1110

16

14

E

1111

17

15

F

10000

20

16

10

Следует помнить, что восьмеричное число кодируется тремя битами, и выписывать триады нужно полностью. Исключением из этого правила может служить только старшая триада, в которой старший бит (СБ) равен нулю.

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

24738 = 101001110112 = 0101 0011 10112 = 53B16

Алгоритм перевода чисел из шестнадцатеричной системы счисления двоичную крайне прост. Необходимо только заменить каждую цифру шестнадцатеричного числа ее эквивалентом в двоичной системе счисления (в случае положительных чисел). Отметим только, что каждое шестнадцатеричное число следует заменять двоичным, дополняя его до 4 разрядов (в сторону старших разрядов).

Пусть требуется перевести шестнадцатеричное число F116 в двоичное число. Воспользовавшись таблицей соответствия, получим: 

F116 = 111100012.

Этот пример иллюстрирует тот факт, что следует дополнять младшие разряды до 4 разряда в двоичном числе. Естественно, дополнять старший разряд двоичного числа до 4 старших битов нулями не имеет смысла, другими словами пишут 

1F16 = 111112, а не 000111112

При переводе чисел из шестнадцатеричной в восьмеричную систему счисления:

  • шестнадцатеричное число переводят в двоичное;

  • разбивают его на триады, начиная с младшего бита;

  • заменяют триады соответствующими им эквивалентами в восьмеричной системе.

1F16 = 111112 = 011 1112 = 378

F116 = 111100012 = 011 110 0012 = 3618

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

Целые беззнаковые числа хранятся в памяти ЭВМ в виде двоичных чисел, занимающих N двоичных разрядов. Диапазон чисел в этом случае от 0 до 2N-1. Целые числа со знаком, записанные в те же N двоичных разрядов будут иметь диапазон от -2(N-1) до 2(N-1)-1 .

Действительные числа хранятся в памяти ЭВМ в специальном формате с плавающей точкой. При этом часть двоичных разрядов ячейки хранит мантиссу числа со знаком, а другая часть – порядок числа. Диапазон действительных чисел определяется количеством двоичных разрядов, отведенных под порядок, а их точность – количеством разрядов под мантиссу.

Символы представлены в ЭВМ в виде соответствующих целочисленных кодов, хранимых в двоичной форме. Обычно под символ отводится один байт памяти, поэтому количество различных символов равно 28-1=255.