WWW.DISSERS.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА

   Добро пожаловать!


Pages:     | 1 | 2 || 4 | 5 |   ...   | 13 |

(логич_выражение) выражение1 : выражениеПереводится это так. Если логич_выражение вернуло истину, то все выражение возвращает выражение1; если логич_выражение вернуло ложь, то все выражение возвращает выражение2. Например:

x = 12;

y = 16;

z = (x > y) x - 1 : y - 1;

Здесь z получит значение 15. Такое условное выражение бывает очень удобно, однако область его применения ограничена простейшими случаями ветвления, т.к. невозможно создавать сложные "тела" в такой конструкции.

Задание Напишите программу, в которой бы использовалось условное выражение.

Операторы И (&&) и ИЛИ (||) Как известно логическое выражение может быть сложным. Логические операторы И и ИЛИ в языке программирования C обозначаются соответственно парными знаками амперсанда (&&) и вертикальной черты (||). Их приоритет меньше, чем у простых логических операторов, поэтому простые логические операции при их объединении в сложные логические выражения можно не заключать в скобки. Пример сложного логического выражения на языке C:

a > 100 && b != Задания 1. Напишите программу, в которой при if использовалось бы сложное логическое выражение.

2. Проверьте и объясните, что выводит функция printf(), если ей передать простые или сложные логические выражения. Например:

printf("%d\n", a == b && c < d);

printf("%d\n", c < d);

Оператор switch При организации множественного выбора бывает удобно использовать не вложенные ifelse, а оператор switch. Его синтаксис можно описать так:

switch (целая_переменная) { case константа1:

операции;

case константа2:

операции;

….

default:

опрации;

} Это приблизительное, а не точное описание. В скобках после слова switch может стоять не только переменная, но и выражение, результат выполнения которого возвращает целое значение (может быть символ). Константы при case также могут быть результатом выполнения выражений. Константы можно группировать в одном case (например, case 12, 13, 18). Ветка default не обязательна.

При выполнении оператора switch, заданное значение в круглых скобках сравнивается с константами. Как только совпадение будет найдено, все последующие вложенные во все case операции начинают выполняться. Т.е. происходит нечто странное: выполняются операции веток case (и default тоже), константы которых не совпадают со значением при switch. Например, в результате выполнения вот такой программы:

int a=1;

switch (a) { case 0:

printf("%d ", 0);

case 1:

printf("%d ", 1);

case 2:

printf("%d ", 2);

default:

printf("%d ", -1);

} printf("\n");

на экране будет выведено:

1 2 -, т.к. как только совпадение было обнаружено, все нижеследующие инструкции были выполнены.

Чтобы этого не происходило, в конце операций, принадлежащих определенному case, дописывают оператор break, который осуществляет принудительный выход из всей конструкции (в данном случае switch). Например:

int a=1;

switch (a) { case 0:

printf("%d\n", 0);

break;

case 1:

printf("%d\n", 1);

break;

case 2:

printf("%d\n", 2);

break;

default:

printf("%d\n", -1);

} выведет только единицу, т.к. выполнение всей инструкции switch прервется после выполнения инструкции break при case 1.

Задание Придумайте свою программу с использованием оператора switch.

Урок 4. Циклы в языке C Инкремент и декремент Прежде, чем изучать циклы, следует познакомиться с часто используемым в языке C способом увеличения/уменьшения значений переменных на единицу. Конечно, в C работают такие формы изменения значений как, например, a += 1 или a -= 1. Однако чаще используют операции инкрементирования (оператор инкремента "++") и декрементирования (оператор декремента "--"): i++ или ++i, i-- или --i. В результате этих операций переменные увеличиваются или уменьшаются на единицу.

Запомните, когда вы видите выражения типа++i или i++, то в результате их выполнения значение i меняется. Не надо делать вот так: i = ++i. Это совершенно лишнее.

Когда знак инкремента или декремента стоит перед переменной, то перед нами префиксная форма операции (++i, --i), а когда после переменной, то постфиксная форма (i++, i--).

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

Например, код:

int a, b, c, d;

a=b=c=d=0; // выражение означает, что всем переменным присваивается printf("a=%d, b=%d, c=%d, d=%d\n", a, b, c, d);

c = ++a;

d = b++;

printf("a=%d, b=%d, c=%d, d=%d\n", a, b, c, d);

, выведет на экране:

a=0, b=0, c=0, d=a=1, b=1, c=1, d=Объясняется такой результат так:

• значение переменной a было увеличено на единицу, после чего это значение было присвоено переменной c;

• значение переменной b было сначала присвоено переменной d и только потом увеличено на единицу.

Еще один пример:

int x, y;

x = y = 0;

printf("%d\n", x++ > 0);

printf("%d\n", ++y > 0);

На экране будет выведено:

Это результат логических выражений, где 0 означает ложь, а 1 — истину. В данном случае, когда x сравнивается с нулем, то его значение еще не увеличено, а когда сравнивается у, то его значение уже больше нуля.

Применять операторы инкремента и декремента можно также к переменным вещественного типа.

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

while Цикл while в языке программирования C работает также как и в других языках программирования. По аналогии с условным выражением в инструкции if, условное выражение при while заключается в круглые скобки. Если тело цикла включает несколько выражений разделяемых точкой с запятой, то все тело заключается в фигурные скобки.

Задание 1. Присвойте переменной star значение 0. Пока значение star не достигнет 55 выводите на экран в строку по одной звездочке (*).

2. С помощью цикла while запрограммируйте вывод на экран цифровых кодов и значений таблицы символов ASCII от 31 до 127 включительно. При этом после каждого десятого символа осуществляйте переход на новую строку. (Подсказка: чтобы переходить на новую строку, в циклеwhile надо использовать инструкцию if, в условии которой остаток1 от деления на 10 сравнивается с нулем.) 3. Используя внешний и вложенный циклы while организуйте вывод таблицы умножения на экран.

Операция нахождения остатка от деления в языке C обозначается знаком процента (%).

do-while Цикл do-while отличается от while лишь тем, что его тело будет выполнено хотя бы один раз независимо от условия выполнения цикла. Синтаксис цикла do-while можно описать так (фигурные скобки можно опустить, если законченное выражение только одно):

do { выражение1;

…;

} while (логич_выражение);

Этот цикл называют циклом с постусловием. Его используют намного реже обычного while.

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

Любое число состоит хотя бы из одной цифры, даже число 0. Можно решить эту задачу с использованием цикла while:

while (a > 0) { printf("%d\n", a % 10);

a = a / 10;

} Но в этом случае, если a равно 0, то цикл не выполнится ни разу. Пришлось бы перед циклом использовать инструкцию if, в которой сравнивать переменную с 0. Использование же цикла do-while решает эту проблему, т.к. его тело один раз выполнится даже при нулевом значении переменной:

do { printf("%d\n", a % 10);

a = a / 10;

} while (a > 0);

Задание Придумайте и напишите любую программу, в которой бы использовался цикл do-while.

for Представим синтаксис заголовка цикла for языка программирования C так:

for (часть1; часть2; часть3) Заголовок цикла for включает три части, разделенных точкой с запятой; причем каждая часть может быть сложной, т.е. состоять из нескольких выражений, разделенных простой запятой. В первой части обычно указываются переменные и часто их начальные значения; во второй - с помощью логического(их) выражения(й) задаются условия, при которых выполняется тело цикла; в третью часть помещаются выражения, которые выполняются в конце каждой итерации цикла (чаще всего здесь изменяется значение переменной, заданной в первой части заголовка).

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

unsigned char a;

for (a = 31; a < 128; a++) { if (a % 10 == 0) printf("\n");

printf("%4d-%c", a, a);

} printf("\n");

Задание Напишите программу с использованием цикла for, выводящую на экран таблицу умножения (Подсказка: как и в случае с while следует использовать два цикла — внешний и вложенный.) break и continue Оператор break позволяет прервать выполнение цикла, а continue — прервать текущую итерацию (проход) цикла. Почти всегда можно обойтись без этих операторов, но иногда их использование позволяет упростить программный код и сделать его более понятным.

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

Второй пример. Требуется из одного массива скопировать в другой только числа, которые больше 0. Можно с помощью continue прерывать итерацию цикла, если очередной элемент меньше либо равен нулю.

#define N int arr[N] = {6, 5, -4, 3, -7, 2, 7, 0, 3, 9};

int new_arr[N], i, j;

for (i=0; i

break;

} } printf("\n");

for(i=0, j=0; i

new_arr[j] = arr[i];

printf("%d ", new_arr[j]); // проверка j++;

} printf("\n");

В данном случае использованиеcontinue совсем не очевидно с точки зрения надобности, т.к. легко можно обойтись без него, если изменить условие при if на противоположное, удалить continue, а оставшийся код поместить в тело оператора if.

Задание Придумайте пример, в котором уместно было бы использовать оператор break или continue.

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

В языке программирования C существуют следующие поразрядные операции: & (И), | (ИЛИ), ^ (исключающее ИЛИ), << (сдвиг влево), >> (сдвиг вправо), ~ (поразрядное дополнение до единицы). Рассмотрим на примерах, как они работают, но перед этим уделим внимание выводу в языке C чисел в отличных от десятичной системах счисления.

В С можно присваивать целочисленные значения в десятичной, восьмеричной и шестнадцатеричной системах счисления. Для того, чтобы присвоить переменной число в восьмеричной системе счисления, перед ним надо написать 0 (ноль), в шестнадцатеричной — 0x (ноль и икс), например:

int a, b;

a = 077; // записано восьмеричное число b = 0x1F; // присвоено шестнадцатеричное число Любые целые числа можно выводить на экран в десятичном, восьмеричном и шестнадцатеричном представлении. Пример кода для вывода определенных ранее двух переменных в различных системаъ счисления:

printf("%d %o %x %X\n", a,a,a,a);

printf("%d %o %x %X\n", b,b,b,b);

В результате на экране вы увидите:

63 77 3f 3F 31 37 1f 1F Восьмеричные и шестнадцатеричные числа используются из-за удобства при работе с двоичной системой счисления. Каждая цифра восьмеричного числа может быть заменена тремя цифрами двоичного. И каждая цифра шестнадцатеричного числа легко заменяет четыре разряда двоичного числа. Вот таблица соответствия цифр восьмеричной системы счисления числам двоичной системы:

0 1 2 3 4 5 6 7 Теперь допустим, что у нас есть восьмеричное число 037. По таблице легко понять, что в двоичном выражении оно будет выглядеть как 011 111.

Задание 1. Как будут выглядеть восьмеричные числа 04271 и 03566 в двоичном представлении.

2. Составьте на бумаге таблицу соответствия шестнадцатеричный цифр двоичным числам.

Переведите числа 7D, FFFF, 2C9 в двоичную систему счисления.

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

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

int a, b;

a = 017;

b = 036;

printf("0%o & 0%o = 0%o\n", a, b, a & b);

printf("0%o | 0%o = 0%o\n", a, b, a | b);

printf("0%o ^ 0%o = 0%o\n", a, b, a ^ b);

printf("0%o << 2 = 0%o\n", a, a << 2);

printf("0%o >> 2 = 0%o\n", a, a >> 2);

printf("~0%o = 0%o\n", a, ~a);

Результат ее работы будет выглядеть так:

017 & 036 = 017 | 036 = 017 ^ 036 = 017 << 2 = 017 >> 2 = ~017 = Этот результат будет проще понять с помощью рисунка:

В последнем случае получилось такое большое число потому, что под форматы вывода целых чисел (%d, %o, %X) выделяется по 4 байта.

Задание 1. Используя шестнадцатеричные числа, напишите аналогичную приведенной выше программу. Объясните результат.

2. Попробуйте составлять сложные битовые операции (в несколько действий) и оценивать их результат.

Теперь рассмотрим пример использования битовых операций. Допустим, у нас есть массив, требуется снять с него "маску", которая бы отражала, в какой позиции стоят отрицательные, а в какой положительные элементы. Пусть единица в бите обозначает соответствующий ей положительный элемент массива, а ноль — отрицательный. Другими словами, если у нас есть массив {4, -3, 2, 2, 8, -1}, то его "битовая маска" будет выглядеть как 101110, или в восьмеричном представлении как 056. Составим алгоритм решения этой задачи:

1. Будем считать, что массив состоит не более чем из 32 элементов. Поэтому для хранения его "маски" достаточно переменной типа int. Назовем ее mask и присвоим значение 0.

2. Перебрать элементы массива в цикле for. Если встречается положительный элемент, то установить соответствующий ему бит значения mask в 1.

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

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

20 = 0000 21 = 0000 22 = 0000 23 = 0000 24 = 0001 и т.д. Если для вас эта последовательность не очевидна, то пересчитайте. Теперь если применить к mask побитовую операцию | (ИЛИ), а в качестве второго операнда использовать определенную степень двойки, то один бит будет установлен в 1. Например:

(0) 0000 0000 | (25) 0010 0000 = 0010 (32) 0010 0000 | (27) 1000 0000 = 1010 При переборе первый элемент массива имеет индекс 0, но соответствующий ему бит в mask должен стоять впереди остальных. Если известно общее количество элементов массива (N), то можно определить степень двойки по формуле N - i - 1. Действительно, имея третий положительный элемент массива из 10 элементов, следует установить в единицу восьмой с конца бит, а это значит надо использовать вторым операндом битового ИЛИ 27, а 7 как раз будет 10(N) - 2(i) - 1.

Pages:     | 1 | 2 || 4 | 5 |   ...   | 13 |






















© 2011 www.dissers.ru - «Бесплатная электронная библиотека»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.