Электронный конспект по программированию часть 1. Программа на языке Си, так же как и на большинстве современных языков программирования, создается в два этапа
Скачать 32.35 Mb.
|
Оформление текста программы Необходимость оформления программы. Зачем же красиво и правильно оформлять тексты программ? На этот вопрос вы сможете ответить сами, сравнив две абсолютно одинаковые (с точки зрения транслятора) программы: То, что в них отличается и называется грамотным оформлением (очевидно, что оно присутствует в первой программе). Оформление текста программы необходимо для того, чтобы • отлаживать программу (искать и исправлять ошибки в ней) • разбираться в алгоритме работы программы Оформление процедур и функций При оформлении функций и процедур рекомендуется придерживаться следующих правил: • Одинаковые операции в разных частях программы оформляются в виде подпрограмм. • Имена функций и процедур должны быть информативными, то есть нести информацию о том, что делает эта подпрограмма. К сожалению, транслятор не понимает русские имена,поэтому приходится писать по-английски. Если вам сложно писать имена на английском языке, можно писать русские слова английскими буквами. Например, процедуру, рисующую квадрат, можно объявить так: void Square ( int x, int y, int a ); илитак void Kvadrat ( int x, int y, int a ); • Перед заголовком подпрограммы надо вставлять несколько строк с комментарием (здесь можно писать по-русски). В комментарий записывается самая важная информация: что означают параметры подпрограммы, что она делает, какое значение она возвращает (если это функция), её особенности. • Не рекомендуется делать подпрограммы длиной более 25-30 строк, так как при этом они становятся сложными и запутанными. Если подпрограмма получается длинной, ее надо разбить на более мелкие процедуры и функции. • Чтобы отделить одну часть подпрограммы от другой, используют пустые строки. Крупный смысловой блок функции можно выделять строкой знаков минус в комментариях. Приведем пример оформления на примере функции, которая рисует на экране закрашенный ромб с заданными параметрами, если весь ромб умещается на экран (при этом результат функции равен 1), или возвращает признак ошибки (число 0). Отступы Отступы используются для выделения структурных блоков программы (подпрограмм, циклов, условных операторов). Отступы позволяют легко искать лишние и недостающие скобки, понимать логику работы программы и находить в ней ошибки. При расстановке отступов рекомендуется соблюдать следующие правила: • Величина отступа равна 2-4 символа. • Дополнительным отступом выделяются oтелоцикловfor, while, do-while o тело условного оператора if и блока else o тело оператора множественного выбора switch Вот пример записи программы с отступами (запись «лесенкой»): Анимация Что такое анимация? Анимация – это оживление изображения на экране (от английского слова animate – оживлять).При этом объекты движутся, вращаются, сталкиваются, меняют форму и цвет и т.д.Чтобы сделать программу с эффектами анимации, надо решить две задачи: • двигать объект так, чтобы он мигал как можно меньше • обеспечить управление клавишами или мышкой во время движения В этом разделе рассматриваются самые простые задачи этого типа. Во всех программах предусмотрен выход по клавише Esc. Движение объекта Составим программу, которая передвигает по экрану какой-то объект (в нашем случае – квадрат) от левой границы экрана к правой. Программа заканчивает работу, когда объект вышел за границы экрана или была нажата клавиша Esc. Предварительный анализ Рассмотрим объект, который движется по экрану. Пусть это будет квадрат со стороной 20 пикселей. При движении координаты всех его точек будут меняться. Чтобы строить квадрат в любом месте экрана, мы выберем его левый верхний угол в качестве базовой (опорной) точки и обозначим ее координаты за (x,y). Координаты противоположного угла будут равны (x+20,y+20). Теперь надо придумать способ изобразить движение так, чтобы рисунок не мигал, и про- грамма работала одинаково на всех компьютерах независимо от быстродействия. Для этого применяют такой алгоритм: 1) рисуем фигуру на экране; 2) делаем небольшую задержку (обычно 10-20 мс); 3) стираем фигуру; 4) меняем ее координаты; 5) переходим к шагу 1. Эти действия повторяются до тех пор, пока не будет получена команда «закончить движение» (в нашем случае – нажата клавиша Esc или объект вышел за правую границу экрана). Пусть движение прямоугольника происходит на синем фоне. Тогда самый быстрый и простой способ стереть его – это нарисовать его же, но синим цветом. Поэтому удобно написать процедуру, параметрами которой являются координаты x и y, а также цвет color. Когда мы используем синий цвет, фигура стирается с экрана. Все действия, которые входят в алгоритм, надо выполнить много раз, поэтому применим цикл. Кроме того, мы заранее не знаем, сколько раз должен выполниться этот цикл, поэтому применяем цикл while (цикл с условием). Условие окончания цикла – выход фигуры за границы экрана или нажатие на клавишу Esc. Мы будем использовать окно размером 400 на 400 пикселей. При этом координата x может меняться от 0 до 399, поэтому нужное нам условие продолжения цикла выглядит так: x + 20 < 400 Когда это условие нарушается, квадрат «уехал» за границу окна и нужно закончить выполнение программы. Обработка событий клавиатуры Надо также обеспечить выход по клавише Esc. При этом объект должен двигаться и нельзя просто ждать нажатия на клавишу с помощью функции getch. В этом случае используют следующий алгоритм: 1. Проверяем, нажата ли какая-нибудь клавиша; это делает функция kbhit, которая воз- вращает результат 0 (ответ «нет»), если никакая клавиша не нажата, и ненулевое значе- ние, если нажали любую клавишцу. В программе проверка выполнена с помощью условного оператора if ( kbhit() ) { ... } 2. Если клавиша нажата, то • Определяем код этой клавиши, вызывая функцию getch. Код клавиши – это ее но- мер в таблице символов. Если на символ отводится 1 байт памяти, то всего можно использовать 256 разных символов и их коды изменяются в интервале от 0 до 255. • Если полученный код равен коду клавиши Esc (27), то выходим из цикла Для того, чтобы управлять программой с помощью клавиш, нужно знать их коды. Вот некоторые из них Esc 27 Enter 13 пробел 32 Программа Программа «в сборе» выглядит так: Осталось лишь дописать основной блок, который обозначен в программе комментарием /* анимация */ В нем нужно организовать цикл анимации, который заканчивается тогда, когда квадрат коснулся границ окна или нажата клавиша Esc. Цикл while выполняется до тех пор, пока фигура находится в пределах экрана. Нажатие на клавишу Esc обрабатывается внутри цикла. Сначала мы определяем, нажата ли какая нибудь клавиша (с помощью функции kbhit), затем определяем ее код (функция getch) и, если он равен коду клавиши Esc, выходим из цикла с помощью оператора break. В основной части цикла рисуем фигуру с помощью процедуры, затем делаем задержку на 20 мс, вызывая функцию delay с параметром 20, и затем стираем фигуру. После этого изменяем координату x и возвращаемся к началу цикла. • Чтобы определить нажата ли какая-нибудь клавиша, используется функция kbhit. Она возвращает 0, если никакая клавиша не нажата, и ненулевое значение, если была нажата какая-то клавиша. • Если клавиша уже была нажата, ее код можно получить (без дополнительного ожидания) с помощью функции getch. • Чтобы сделать задержку на заданное время, используется процедура delay. Параметром этой процедуры является величина задержки в миллисекундах. Если уменьшать задержку, фигура будет двигаться быстрее. Управление клавишами-стрелками Предварительный анализ Принцип работы программы очень простой: получив код клавиши, надо сдвинуть объект в соответствующую сторону. Если обозначить изменения координат фигуры x и y за 1 шаг цикла через dx и dy, для движения в четырех направлениях получаем: движение влево dx < 0, dy = 0 движение вправо dx > 0, dy = 0 движение вверх dx = 0, dy < 0 движение вниз dx = 0, dy > 0 Это значит, что надо сделать выбор одного из четырех вариантов в зависимости от кода нажатой клавиши. Для этого можно использовать несколько условных операторов if, но существует специальный оператор switch, который позволяет легко организовать выбор из нескольких вариантов. Еще одна проблема связана с тем, что клавиши управления курсором (стрелки) – не совсем обычные клавиши. Они относятся к группе функциональных клавиш, у которых нет кодов в таблице символов. Когда нажата одна из специальных клавиш, система реагирует на нее как на 2 нажатия, причем для первого код символа всегда равен нулю, а для второго мы получим специальный код (так называемый скан-код, номер клавиши на клавиатуре). Мы будем использовать упрощенный подход, когда анализируется только этот второй код: влево 75 вверх 72 вправо 77 вниз 80 У такого приема есть единственный недостаток: объект будет также реагировать на нажатие клавиш с кодами 75, 77, 72 и 80 в таблице символов, то есть на заглавные латинские буквы K, M, H и P. Простейший случай Составим программу, при выполнении которой фигура будет двигаться только тогда, ко-гда мы нажмем на клавишу-стрелку. В цикле мы сначала рисуем фигуру, ждем нажатия на клавишу и принимаем ее код с помощью функции getch. После этого стираем фигуру в том же месте (пока не изменились координаты) и, в зависимости от этого кода, меняем координаты фигуры нужным образом. Здесь используется бесконечный цикл while(1). Выйти из него можно только одним способом – черезоператорbreak (досрочный выход из цикла). В операторе switch значения координат меняются на единицу, хотя можно использовать любой шаг. В конце обработки каждого варианта надо ставить оператор break, чтобы не выполнялись строки, стоящие ниже. Обратите внимание, что целую переменную code нужно объявить в начале основной программы. Непрерывное движение Теперь рассмотрим более сложный случай, когда объект продолжает движение в выбран- ном направлении даже тогда, когда ни одни клавиша не нажата, а при нажатии клавишистрелки меняет направление. Здесь надо использовать переменные dx и dy, которые задают направление движения. Сначала мы определяем, нажата ли клавиша, а затем определяем ее код,записываем его в переменную code, и обрабатываем это нажатие с помощью оператора switch. 11. Случайные и псевдослучайные числа Что такое случайные числа? Представьте себе снег, падающий на землю. Допустим, что мы сфотографировали природу в какой-то момент. Сможем ли мы ответить на такой вопрос: куда точно упадет следующая снежинка? Навряд ли, потому что это зависит от многих причин — от того, какая снежинка ближе к земле, как подует ветер и т.п. Можно сказать, что снежинка упадет в случайное место, то есть в такое место, которое нельзя предсказать заранее. Для моделирования случайных процессов (типа падения снежинок, броуновского движения молекул вещества и т.п.) на компьютерах применяют случайные числа. Случайные числа – это такая последовательность чисел, в которой невозможно назвать следующее число, зная сколько угодно предыдущих. Получить случайные числа на компьютере достаточно сложно. Иногда для этого применяют различные источники радиошумов. Однако математики придумали более универсальный и удобный способ — псевдослучайные числа. Псевдослучайные числа – это последовательность чисел, обладающая свойствами, близкими к свойствам случайных чисел, в которой каждое следующее число вычисляется на основе предыдущих по некоторой математической формуле. Таким образом, эта последовательность ведет себя так же, как и последовательность случайных чисел, хотя, зная формулу, мы можем получить следующее число в последовательности. Распределение случайных чисел Обычно используют псевдослучайные числа (далее для краткости мы называем их просто случайными), находящиеся в некотором интервале. Например, представим себе, что снежинки падают не на всю поверхность земли, а на отрезок оси OX от a до b. При этом очень важно знать некоторые общие свойства этой последовательности. Если понаблюдать за снежинками в безветренную погоду, то слой снега во всех местах будет примерно одинаковый, а при ветре — разный. Про случайные числа в первом случае говорят, что они имеют равномерное распределение, а во втором случае — неравномерное. Большинство стандартных датчиков псевдослучайных чисел (то есть формул, по которым они вычисляются) дают равномерное распределение в некотором интервале.Поскольку случайные числа в компьютере вычисляются по формуле, то для того, чтобы повторить в точности какую-нибудь случайную последовательность достаточно просто взять то же самое начальное значение. Функции для работы со случайными числами В языке Си существуют следующие функции для работы со случайными числами (их описание находится в заголовочном файле stdlib.h — это значит, что его необходимо подключать в начале программы): n = rand(); получить случайное целое число в интервале от 0 до RAND_MAX (это очень большое целое число — 32767) srand ( m ); установить начальное значение случайной последовательности, равное m Случайные числа в заданном интервале Для практических задач надо получать случайные числа в заданном интервале [a,b]. Если интервал начинается с нуля (a=0), можно использовать свойство операции взятия остатка от деления: остаток от деления числа на некоторое N всегда больше или равен нуля, но меньше N, то есть находиться в интервале [0,N-1]. Можно написать такую функцию int random ( int N ) { return rand() % N; // случайное число в интервале [0,N-1] } С ее помощью (вызывая ее много раз подряд) можно получать последовательность случайных чисел в интервале [0,N-1] с равномерным распределением. Теперь попытаемся использовать эту функцию для интервала [a,b]. Очевидно, что формула k = random(N) + a; дает последовательность в интервале [a,a+N-1]. Поскольку нам нужно получить интервал [a,b], сразу имеем b=a+N-1, откуда N=b-a+1. Поэтому Для получения случайных целых чисел с равномерным распределением в интервале [a,b] надо использовать формулу k = random(b-a+1) + a; Более сложным оказывается вопрос о случайных вещественных числах. Если разделить результат функции rand() на RAND_MAX: x = (float) rand() / RAND_MAX; мы получим случайное вещественное число в интервале [0,1) (при этом надо не забыть привести одно из этих чисел к вещественному типу, иначе деление одного целого числа на большее целое число будет всегда давать ноль). Длина интервала [0,1) такой последовательности равна 1, а нам надо получить интер- вал длиной b-a. Если теперь это число умножить на b-a и добавить к результату a, мы получаем как раз нужный интервал. Для получения случайных вещественных чисел с равномерным распределением в интервале [a,b) надо использовать формулу x = rand()*(b-a)/RAND_MAX + a; До этого момента мы говорили только о получении случайных чисел с равномерным распределением. Как же получить неравномерное? На этот вопрос математика отвечает так: из равномерного распределения можно получить неравномерное, применив к этим данным некоторую математическую операцию. Например, чтобы основная часть чисел находилась в середине интервала, можно брать среднее арифметическое нескольких последовательных случайных чисел с равномерным распределением. |