ДЛИННАЯ ЗАПИСЬ СМЫСЛ СОКРАЩАЕТСЯ ДО
Группа «А»
Группа «Б»
Главный судья соревнований: /М.В.Максимов/ Int означает сокращение от слова integer - "целый".
ПРОГРАММА
Программа состоит из ОПЕРАТОРОВ, то есть действий. Операторы выполняются последовательно в том порядке, в котором они записаны.
/* ОБЪЯВЛЯЕМ ДВЕ ПЕРЕМЕННЫЕ */ int x, y; /* 0 */
/* Это еще не операторы, хотя при этом создаются 2 ящика для целых чисел */
/* А ТЕПЕРЬ - ОПЕРАТОРЫ. */ /* Мы начнем с простых операторов присваивания и арифметики */
x = 3; /* 1 */ y = 4; /* 2 */ x = x + y; /* 3 */ y = y - 1; /* 4 */ x = y; /* 5 */
Значения переменных (то, что лежит в ящиках) меняются таким образом:
x y /* 0 */ мусор мусор
/* после 1 */ 3 мусор /* после 2 */ 3 4 /* после 3 */ 7 4 /* после 4 */ 7 3 /* после 5 */ 3 3
Как вы видите, переменные, которые не участвуют в левой части оператора присваивания, этим оператором НЕ МЕНЯЮТСЯ.
Последняя операция x = y; НЕ делает имена x и y синонимами. Такой вещи, как "перевешивание табличек с именами с ящика на ящик" не происходит. Вместо этого, два ящика с именами x и y содержат одинаковые значения, то есть две копии одного и того же числа.
----- ----- / x / / y / --------------- --------------- | 3 *<--|--------<----|-- 3 | --------------- 1) --------------- 2), 3) 4)
1) Из ящика y берется КОПИЯ числа 3 (безымянное значение). 2) Старое содержимое ящика x уничтожается. 3) Число 3 кладется в ящик x. 4) В исходном ящике y попрежнему осталось 3.
Значение целой переменной можно вывести на экран оператором печати:
printf("%d\n", x);
Пока будем рассматривать его как "магический".
Над целыми числами можно производить такие арифметические операции:
x + y сложение x - y вычитание x * y умножение x / y деление нацело (то есть с остатком; результат - целое) x % y вычислить остаток от деления нацело
5 / 2 даст 2 5 % 2 даст 1
В операторах присваивания используются такие сокращения:
ДЛИННАЯ ЗАПИСЬ СМЫСЛ СОКРАЩАЕТСЯ ДО x = x + 1; "увеличить на 1" x++; (или ++x;) x = x - 1; "уменьшить на 1" x--; (или --x;) x = x + y; "прибавить y" x += y; x = x * y; "умножить на y" x *= y; x = x / y; "поделить на y" x /= y;
В том числе x++; можно записать как x += 1;
* СТРУКТУРЫ УПРАВЛЕНИЯ *
Обычно операторы выполняются последовательно, в том порядке, в котором они записаны в программе.
оператор1; | оператор2; | оператор3; | оператор4; V
УСЛОВНЫЙ ОПЕРАТОР
if(условие) оператор;
...продолжение...
Работает так:
Вычисляется условие.
Если оно истинно, то выполняется оператор, затем выполняется продолжение.
Если оно ложно, то сразу выполняется продолжение, а оператор не выполняется.
Если нам надо выполнить при истинности условия несколько операторов, мы должны заключить их в скобки {... } - это так называемый "составной оператор".
if(условие) { оператор1; оператор2; ... } продолжение
После } точка с запятой НЕ СТАВИТСЯ (можно и поставить, но не нужно).
Условный оператор изображают на схемах так:
| | | ---------------- ---| ЕСЛИ условие |---- | ---------------- | | | V V истинно ложно | | V | ------------ | | оператор | | ------------ | | | ------->-------<------- | | V продолжение |
Имеется вторая форма, с частью "иначе":
if(условие) оператор_если_истинно; else оператор_если_ложно;
"или то, или другое" (но не оба сразу)
| | | ---------------- ---| ЕСЛИ условие |----------- | ---------------- | | | V V истинно ложно | | V | ------------------------- ----------------------- | оператор_если_истинно | | оператор_если_ложно | ------------------------- ----------------------- | | ------->-------<-------------- | | V продолжение |
Пример1: if(x > 10) printf("Икс больше десяти\n");
Пример2:
int x, y, z;
if(x < y) z = 1; else z = 2;
Условия:
В качестве условий могут использоваться операторы СРАВНЕНИЯ (сравнивать можно переменные, выражения, константы)
x < y меньше x > y больше x <= y меньше или равно x >= y больше или равно x == y равно x!= y не равно
Все эти операторы в качестве результата операции сравнения выдают 1, если сравнение истинно 0, если оно ложно.
Таким образом, на самом деле условный оператор работает так:
if(условие)....
Если условие есть НОЛЬ - то условие считается ложным. Если условие есть НЕ НОЛЬ а... -2, -1, 1, 2, 3,... - то условие истинно.
Это определение.
Из него в частности вытекает, что сравнение с целым нулем можно опускать:
if(x!= 0)...; сокращается до if(x)...; if(x == 0)...; сокращается до if(!x)...; ---------------------------------------------------------------------------
Пример: int x, y, z; if(x == 1){ y = 2; z = x + y; } else { y = 1; z = x - y; }
---------------------------------------------------------------------------
Пример со вложенными условными операторами:
if(x == 1){ printf("Икс равен 1\n"); if(y == 2){ printf("Игрек равен 2\n"); } } else { printf("Икс не равен 1\n"); } ---------------------------------------------------------------------------
Часто применяется последовательность условных операторов, перебирающая различные варианты:
if(x == 1) printf("Икс равен 1\n"); else if(x == 2) printf("Икс равен 2\n"); else if(x == 3){ printf("Икс равен 3\n"); y = 1; } else printf("Непредусмотренное значение икс\n"); ---------------------------------------------------------------------------
Самое сложное - привыкнуть к тому, что сравнение обозначается знаком ==, а не = Знак = означает "присвоить значение", а не "сравнить на равенство".
ЦИКЛ while ("до тех пор, пока истинно")
while(условие) оператор; ...продолжение...
или
while(условие){ операторы; ... } ...продолжение...
| V | +------>--+ | | | V П | --------------------- о | | проверить УСЛОВИЕ |-------> если ложно (нуль) в A --------------------- | т | | | о | V | р | если истинно (не нуль) | и | | | т | V | ь | оператор V | | | | | | +-----<---+ | | +-------<---------------------+ | V продолжение
Пример: int x; x = 10; while(x > 0){ printf("x=%d\n", x); x = x - 1; } printf("Конец.\n"); printf("x стало равно %d.\n", x); /* печатает 0 */
"Цикл" он потому, что его тело повторяется несколько раз.
Чтобы цикл окончился, оператор-тело цикла должен менять какую-то переменную, от которой зависит истинность условия повторений.
ОПЕРАТОРЫ "И, ИЛИ, НЕ"
Условия могут быть сложными.
ЕСЛИ красный И вес < 10 ТО...; ЕСЛИ красный ИЛИ синий ТО...; ЕСЛИ НЕ красный ТО...;
На языке Си такие условия записываются так:
if(условие1 && условие2)...; /* "И" */ if(условие1 || условие2)...; /* "ИЛИ" */ if(! условие1)...; /* "НЕ" */
Например:
if(4 < x && x <= 12)...;
Было бы неправильно записать
if(4 < x <= 12)...;
ибо язык программирования Си НЕ ПОНИМАЕТ двойное сравнение!
Еще примеры:
if(x < 3 || y > 4)...;
if(! (x < 3 || y > 4))...;
ЦИКЛ for ("для каждого")
Этот цикл является просто иной записью одного из вариантов цикла while. Он служит обычно для выполнения опеределенного действия несколько раз, не "пока истинно условие", а "выполнить N-раз".
У такого цикла есть "переменная цикла" или "счетчик повторений".
int i;
i = a; /* начальная инициализация */
while(i < b){
тело_цикла;
i += c; /* увеличение счетчика */ } ...продолжение...
переписывается в виде
int i; for(i=a; i < b; i += c) тело_цикла;
тело_цикла будет выполнено для значений i a a+c a+c+c ...
пока i < b
В простейшем случае
for(i=1; i <= N; i++) printf("i=%d\n", i);
i означает "номер повторения".
Такой цикл служит для повторения СХОЖИХ действий НЕСКОЛЬКО раз с разным значением параметра.
ОПЕРАТОР break ("вывалиться из цикла")
Оператор break заставляет прервать выполнение тела цикла и сразу перейти к продолжению программы.
while(условие1){ операторы1;
if(условие2) break; ------->----+ | операторы2; | } | ...продолжение...<--------<---------+
и
for(i=0; условие1; i++){ операторы1;
if(условие2) break; ------->----+ | операторы2; | } | ...продолжение...<--------<---------+
Этот оператор позволяет организовывать дополнительные точки выхода из цикла (при дополнительных условиях).
Пример:
for(i=0; i < 20; i++){ printf("i=%d\n", i); if(i == 7){ printf("break loop!\n"); break; /* вывалиться из цикла */ } printf("more\n"); } printf("finished, i=%d\n", i); /* печатает 7 */
В частности, с его помощью можно организовывать бесконечный цикл:
for(;;){ /* заголовок бесконечного цикла */ операторы1;
if(условие2) break; ------->----+ | операторы2; | } | ...продолжение...<--------<---------+
Здесь в самом заголовке цикла НЕ ПРОВЕРЯЕТСЯ НИКАКИХ УСЛОВИЙ, такой цикл продолжается бесконечно. Условие продолжения считается всегда истинным.
Единственный способ выйти из него - это сделать break (при каком-то условии) в теле цикла, что и написано.
Бесконечный цикл можно также организовать при помощи while(1){ ... }
ОПЕРАТОР ВЫВОДА (ПЕЧАТИ)
printf("текст");
Печатает на экран текст.
printf("текст\n");
Печатает на экран текст и переходит к новой строке.
printf("слово1 слово2 "); printf("слово3\n");
печатает
слово1 слово2 слово3 и переходит на новую строку.
Если переход на новую строку не задан явно, символом \n, то текст продолжает печататься в текущей строке.
printf("%d", x);
Печатает в текстовом виде ЗНАЧЕНИЕ переменной x. Специальная конструкция %d означает "взять переменную из списка после запятой и напечатать ее значение в ивде целого числа".
printf("икс равен %d - ого-го\n", x);
Печатает сначала текст
икс равен
затем значение переменной x как целое число, затем текст - ого-го
и переходит на новую строку (поскольку указан символ \n).
Этот оператор может печатать и несколько значений переменных:
int x, y;
x = 12; y = 15; printf("икс есть %d, игрек есть %d, все.\n", x, y); ~~~~~~
Данный оператор работает так. Строка "икс есть %d, игрек есть %d\n" называется ФОРМАТОМ. Компьютер читает формат слева направо и печатает текст до тех пор, пока не встретит символ %d. Курсор изображен символом _
икс есть _
Далее он берет ПЕРВУЮ переменную из списка ~~~~ и печатает ее как целое число.
икс есть 12_
далее он снова печатает текст пока не встретит %d
икс есть 12, игрек есть _
Теперь он берет ВТОРУЮ переменную из списка и печатает ее:
икс есть 12, игрек есть 15_
Снова печатает текст, включая перевод строки \n. Как только строка формата кончилась, оператор printf завершен.
икс есть 12, игрек есть 15, все. _
Печатать можно не только значения переменных, но и значения арифметических выражений:
printf("равно: %d\n", 12 + 3 * 5);
Контрольный вопрос, что печатается:
int x, y, z;
x = 13; y = 23; z = 34;
printf("x=%d xx=%d\nzzz=%d\n", x, y - 1, z * 2 + 1);
Тут в формате есть ДВА перевода строки, поэтому будет напечатано:
x=13 xx=22 zzz=69 _
Заметьте, что перед тем как быть напечатанными, выражения в списке после формата ВЫЧИСЛЯЮТСЯ.
Что напечатает
printf("x=%d\n y=%d\n", x, y);
x=13 y=23 _
Пробел перед y возник потому, что он СОДЕРЖИТСЯ в строке формата после символа \n!!! Будьте внимательны.
ФУНКЦИИ
Функцией называется фрагмент программы, в который передаются ПАРАМЕТРЫ, и который ВОЗВРАЩАЕТ значение (или ничего).
Прелесть функции в том, что ее можно выполнить много раз из разных точек программы.
Функция состоит из
ОБЪЯВЛЕНИЯ - описания того, как она что-то вычисляет Объявление бывает ровно одно.
ВЫЗОВОВ - с конкретными значениями параметров, что именно она должна на этот раз вычислить. Вызовов может быть сколько угодно.
Объявление простейшей функции выглядит так:
int func(int x){
/* Один или несколько операторов, завершающихся оператором return(нечто); */
return x+1; }
---------------------------------------------------------------------------
int func(...
задает функцию с именем func (имя выдумывает программист, как и имена переменных).
int означает, что функция возвращает целое значение. ---------------------------------------------------------------------------
...(int x)...
задает список аргументов (или параметров) функции. ---------------------------------------------------------------------------
...){ ... }
задает тело функции - некую последовательность объявлений переменных и операторов. ---------------------------------------------------------------------------
return выражение;
задает оператор выхода из функции в точку ее вызова с возвратом значения выражения. ---------------------------------------------------------------------------
Покажем простой пример ВЫЗОВА этой функции:
int y; ... y = func(5); /* a */ ...продолжение... /* b */
Этот фрагмент работает следующим образом:
y = func(5);
В этой точке мы 1) "записываем на бумажке", что вызов произошел в такой-то строке, таком-то месте нашей программы.
2) Смотрим на ОПРЕДЕЛЕНИЕ функции func.
int func(int x){...
Мы вызвали функцию как func(5). Это значит, что в теле функции x получает начальное значение 5.
То есть ДЛЯ ДАННОГО ВЫЗОВА наша функция (ее тело) превращается в
int x;
x = 5; return x+1;
3) x+1 есть 6.
Далее должен выполниться оператор return.
Он выполняется так:
Мы "читаем с бумажки" - откуда была вызвана функция func, и смотрим на это место. Это было
y = func(5);
Вычеркиваем func(5) и заменяем его ЗНАЧЕНИЕМ выражения, вычисленного в операторе return;
y = 6;
4) Выполняем этот оператор и переходим к продолжению.
---------------------------------------------------------------------------
int y, z, w;
y = func(5); z = func(6); w = func(7) + func(8) + 1;
Превратится в
y = 6; z = 7; w = 8 + 9 + 1;
При этом мы четыре раза "прыгнем" на определение функции func(), пройдем все ее операторы с разными значениями параметра x и вернемся обратно в точку вызова.
ПРОГРАММА В ЦЕЛОМ
Программа в целом состоит из функций. Одна из функций должна иметь имя main(),
С ФУНКЦИИ main НАЧИНАЕТСЯ ВЫПОЛНЕНИЕ ПРОГРАММЫ.
(на самом деле этому предшествует отведение и инициализация глобальных переменных; смотри последующие лекции).
|