Программирование на языке Си 1. 2. 3. 4. 5. 6. 7. Введение Переменные Ветвления Сложные условия Циклы Циклы с переменной Оператор выбора К. Поляков, 2006-2012 8. 9. 10. 11. 12. 13. 14. Отладка программ Графика Графики функций Процедуры Анимация Функции Случайные числа http://kpolyakov.narod.ru Программирование на языке Си Тема 1. Введение К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 3 Алгоритм Алгоритм – это четко определенный план действий для исполнителя. Свойства алгоритма • дискретность: состоит из отдельных шагов (команд) • понятность: должен включать только команды, известные исполнителю (входящие в СКИ) • определенность: при одинаковых исходных данных всегда выдает один и тот же результат • конечность: заканчивается за конечное число шагов • массовость: может применяться многократно при различных исходных данных • корректность: дает верное решение при любых допустимых исходных данных К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 4 Программа Программа – это • алгоритм, записанный на каком-либо языке программирования • набор команд для компьютера Команда – это описание действий, которые должен выполнить компьютер. • откуда взять исходные данные? • что нужно с ними сделать? • куда поместить результат? К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 5 Языки программирования • Машинно-ориентированные (низкого уровня) каждая команда соответствует одной команде процессора (ассемблер) • Языки высокого уровня – приближены к естественному (английскому) языку, легче воспринимаются человеком, не зависят от конкретного компьютера • для обучения: Бейсик, ЛОГО, Паскаль • профессиональные: Си, Фортран, Паскаль • для задач искусственного интеллекта: Пролог, ЛИСП • для Интернета: JavaScript, Java, Perl, PHP, ASP К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 6 Язык Си 1972-1974 – Б. Керниган, Д. Ритчи • высокая скорость работы программ • много возможностей • стал основой многих современных языков (С++, С#, Javascript, Java, ActionScript, PHP) • много шансов сделать ошибку, которая не обнаруживается автоматически К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 7 Простейшая программа главная (основная) программа всегда имеет имя main main() { «тело» программы (основная часть) ? К. Поляков, 2006-2012 начало программы } конец программы Что делает эта программа? http://kpolyakov.narod.ru Программирование на языке Си 8 Что происходит дальше? текст программы на Си или Си++ first.cpp транслятор main() { } исходный файл ! • по исходному файлу можно восстановить остальные • исполняемый файл можно запустить К. Поляков, 2006-2012 first.o ЪБzЦ2?|ё3БКа n/36ШпIC+ИЦЗ_5МyРЧб s6bд^:/@:лЖ1_ стандартные функции объектный файл first.exe MZPо:ЄPэ_еЗ"!_ `кn,ЦbЄ-Щр1 G_БАC, _Ощях¤9жФ редактор связей (компоновка) исполняемый файл http://kpolyakov.narod.ru Программирование на языке Си 9 Вывод текста на экран include = включить #include <stdio.h> main() { printf("Привет!"); } вызов стандартной функции printf = print format (форматный вывод) К. Поляков, 2006-2012 файл stdio.h: описание стандартных функций ввода и вывода этот текст будет на экране http://kpolyakov.narod.ru Программирование на языке Си 10 Как начать работу? Открыть Новый Сохранить Закрыть здесь мы набираем программу сообщения об ошибках К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 11 Оболочка Dev C ++ 4.9 IDE = Integrated Development Environment • • • • интегрированная среда разработки: текстовый редактор для создания и редактирования текстов программ транслятор для перевода текстов программ на Си и Си++ в команды процессора компоновщик для создания исполняемого файла (EXE-файла), подключаются стандартные функции отладчик для поиска ошибок в программах К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 12 Управление клавишами Новый файл (Создать) Ctrl+N Открыть файл Ctrl+O Сохранить файл Ctrl+S Закрыть окно с программой Ctrl-F4 Запуск программы Отменить Восстановить отмененное К. Поляков, 2006-2012 F9 Ctrl-Z Shift-Ctrl-Z http://kpolyakov.narod.ru Программирование на языке Си 13 Где ошибки? эта ошибка обнаружена здесь! 2 x ЛКМ ! Ошибка может быть в конце предыдущей строки! К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 14 Наиболее «популярные» ошибки xxx.h: No such file or directory не найден заголовочный файл 'xxx.h' (неверно указано его имя, он удален или т.п.) 'xxx‘ undeclared (first use this function) функция или переменная 'xxx' неизвестна missing terminating " character не закрыты кавычки " expected ; нет точки с запятой в конце оператора в предыдущей строке expected } не закрыта фигурная скобка К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 15 Ждем нажатия любой клавиши файл conio.h: описание функций для работы с клавиатурой и монитором #include <stdio.h> #include <conio.h> комментарий до main() конца строки { printf("Привет!"); // вывод на экран getch(); /* ждать нажатия клавиши */ } ждать нажатия на любую клавишу К. Поляков, 2006-2012 комментарий между /* и */ http://kpolyakov.narod.ru Программирование на языке Си 16 Переход на новую строку последовательность #include <stdio.h> #include <conio.h> \n (код 10) переход на новую строку main() { \n Вася!"); printf("Привет,\n getch(); } на экране: Привет, Вася! К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Задания 17 «4»: Вывести на экран текст "лесенкой" Вася пошел гулять «5»: Вывести на экран рисунок из букв Ж ЖЖЖ ЖЖЖЖЖ ЖЖЖЖЖЖЖ HH HH ZZZZZ К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Тема 2. Переменные К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 19 Что такое переменная? Переменная – это ячейка в памяти компьютера, которая имеет имя и хранит некоторое значение. • Значение переменной может меняться во время выполнения программы. • При записи в ячейку нового значения старое стирается. Типы переменных • int – целое число (4 байта) • float – вещественное число, floating point (4 байта) • char – символ, character (1 байт) К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 20 Имена переменных Могут включать • латинские буквы (A-Z, a-z) • знак подчеркивания _ • цифры 0-9 ! Имя не может начинаться с цифры! НЕ могут включать • русские буквы • пробелы • скобки, знаки +, =, !, ? и др. Какие имена правильные? AXby R&B 4Wheel Вася “PesBarbos” TU154 [QuQu] _ABBA A+B К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 21 Объявление переменных Объявить переменную = определить ее имя, тип, начальное значение, и выделить ей место в памяти. main() целая переменная a { вещественные переменные b и c переменные целые intцелая a; и дробная части отделяются точкой float b, c; Tu104, Il86 и Yak42 Il86 = 23 вещественные int Tu104, Il86=23, Yak42; переменные x, y и z x = 4,56 float x=4.56, y, z; · char c, c2='A', m; } ! символьные переменные c, c2 и m c2 = 'A' Если начальное значение не задано, в этой ячейке находится «мусор»! К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 22 Оператор присваивания Оператор – это команда языка программирования высокого уровня. Оператор присваивания служит для изменения значения переменной. Пример a = 5; x = a + 20; a 5 ? 5 x 25 ? y = (a + x) * (x – a); К. Поляков, 2006-2012 5+20 y 600 ? 30*20 http://kpolyakov.narod.ru Программирование на языке Си 23 Оператор присваивания Общая структура: куда записать что имя переменной = выражение; Арифметическое выражение может включать • константы (постоянные) • имена переменных • знаки арифметических операций: + * / % умножение деление • вызовы функций • круглые скобки ( ) К. Поляков, 2006-2012 остаток от деления ? Для чего служат круглые скобки? http://kpolyakov.narod.ru Программирование на языке Си 24 Сложение двух чисел Задача. Ввести два целых числа и вывести на экран их сумму. Простейшее решение: #include <stdio.h> #include <conio.h> подсказка для main() ввода { int a, b, c; ввод двух printf("Введите два целых числа\n"); чисел с scanf ("%d%d", &a, &b); клавиатуры c = a + b; printf("%d", c); getch(); вывод результата } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 25 Ввод чисел с клавиатуры scanf – форматный ввод формат ввода адреса ячеек, куда записать введенные числа scanf ("%d%d", &a, &b); Формат – символьная строка, которая показывает, какие числа вводятся (выводятся). %d – целое число &a – адрес %f – вещественное число переменной a %c – 1 символ 7652 %s – символьная строка ждать ввода с клавиатуры двух целых чисел (через пробел или Enter), первое из них записать в переменную a, второе – в b К. Поляков, 2006-2012 12 a – значение переменной a http://kpolyakov.narod.ru Программирование на языке Си 26 Что неправильно? &a int a, b; %d%d scanf ("%d", a); scanf ("%d", &a, &b); &a, &b scanf ("%d%d", &a); убрать пробел scanf ("%d %d", &a, &b); scanf ("%f%f", &a, &b); %d%d К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 27 Вывод чисел на экран здесь вывести целое число это число взять из ячейки c printf ("%d", c); printf ("Результат: %d", c); printf ("%d+%d=%d", a, b, c ); формат вывода список значений printf ("%d+%d=%d", a, b, a+b ); арифметическое выражение К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 28 Вывод целых чисел int x = 1234; printf ("%d", x); 1234 или "%i" минимальное число позиций или "%9i" printf ("%9d", x); 1234 5 К. Поляков, 2006-2012 всего 9 позиций 4 http://kpolyakov.narod.ru Программирование на языке Си 29 Вывод вещественных чисел float x = 123.4567; printf ("%f", x); 123.456700 printf ("%9.3f", x); 123.456 минимальное число позиций, 6 цифр в дробной части всего 9 позиций, 3 цифры в дробной части printf ("%e", x); 1.234560e+02 printf ("%10.2e", x); 1.23e+02 К. Поляков, 2006-2012 стандартный вид: 1,23456·102 всего 10 позиций, 2 цифры в дробной части мантиссы http://kpolyakov.narod.ru Программирование на языке Си 30 Полное решение #include <stdio.h> #include <conio.h> main() { int a, b, c; printf("Введите два целых числа\n"); scanf("%d%d", &a, &b); c = a + b; printf("%d+%d=%d", a, b, c); getch(); } это выводит компьютер Протокол: Введите два целых числа 25 30 это вводит пользователь 25+30=55 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 31 Блок-схема линейного алгоритма начало блок «начало» ввод a, b блок «ввод» c = a + b; вывод c конец К. Поляков, 2006-2012 блок «процесс» блок «вывод» блок «конец» http://kpolyakov.narod.ru Программирование на языке Си Задания 32 «3»: Ввести три числа, найти их сумму. Пример: Введите три числа: 4 5 7 4+5+7=16 «4»: Ввести три числа, найти их сумму и произведение. Пример: Введите три числа: 4 5 7 4+5+7=16 4*5*7=140 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 33 Задания «5»: Ввести три числа, найти их сумму, произведение и среднее арифметическое. Пример: Введите три числа: 4 5 7 4+5+7=16 4*5*7=140 (4+5+7)/3=5.33 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 34 Какие операторы неправильные? main() { имя переменной int a, b; должно быть слева float x, y; от знака = a = 5; целая и дробная часть 10 = x; отделяются точкой y = 7,8; при записи вещественного b = 2.5; значения в целую x = 2*(a + y); переменную дробная часть будет отброшена a = b + x; } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 35 Особенность деления в Си ! При делении целых чисел остаток отбрасывается! main() { int a = 7; float x; 1 0 x = a / 4; x = 4 / a; 1.75 x = float(a) / 4; x = 1.*a / 4; } К. Поляков, 2006-2012 1.75 http://kpolyakov.narod.ru Программирование на языке Си Сокращенная запись операций в Си полная запись a = a + 1; инкремент сокращенная запись a++; a = a + b; a += b; a = a - 1; декремент a--; a = a – b; a -= b; a = a * b; a *= b; a = a / b; a /= b; a = a % b; a %= b; К. Поляков, 2006-2012 36 http://kpolyakov.narod.ru Программирование на языке Си 37 Порядок выполнения операций 1) вычисление выражений в скобках 2) умножение, деление и %(остаток от деления) слева направо 3) сложение и вычитание слева направо 1 2 4 5 3 6 z = (5*a+c)/a*(b-c)/ b; 5c 2 d (a b) x (c d )( d 2a) 5a c z (b c) ab 2 3 5 4 1 10 6 9 8 7 x =(5*c*c-d*(a+b))/((c+d)*(d-2*a)) К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 38 Ручная прокрутка программы main() { int a, b; a = 5; b = a + 2; a = (a + 2)*(b – 3); b = a / 5; a = a % b; a++; b = (a + 14) % 7; } К. Поляков, 2006-2012 a b ? ? 5 7 28 5 3 4 4 http://kpolyakov.narod.ru Программирование на языке Си 39 Вывод на экран int a = 1, b = 3; printf("%d+%d=%d", a, b, a+b); формат вывода список вывода • элементы списка разделяются запятыми • форматы вывода начинаются с % • выражения (элементы без кавычек) вычисляются и выводится их результат ? Что будет выведено? 1+3=4 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 40 Что будет выведено? int a = 1, b = 3; printf("a+%d=a+b", b); int a = 1, b = 3; printf("%d=F(%d)", a, b); int a = 1, b = 3; printf("a=F(%d);", b); int a = 1, b = 3; printf("%d>%d!", a+b, b); int a = 1, b = 3; printf("F(%d)=X(%d)", b, a); К. Поляков, 2006-2012 a+3=a+b 1=F(3) a=F(3); 4>3! F(3)=X(1) http://kpolyakov.narod.ru Программирование на языке Си 41 Как записать оператор вывода? int a = 1, b = 3 printf("X(%d)=%d", b, a); int a = 1, b = 3 printf("%d=%d+%d",a+b,a,b); X(3)=1 4=1+3 int a = 1, b = 3 printf("f(%d)>f(%d)", a, b); f(1)>f(3) int a = 1, b = 3 printf("<%d<>%d>", a, b); <1<>3> int a = 1, b = 3 printf("%d+%d=?", a, b); К. Поляков, 2006-2012 1+3=? http://kpolyakov.narod.ru Программирование на языке Си Тема 3. Ветвления К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 43 Разветвляющиеся алгоритмы Задача. Ввести два целых числа и вывести на экран наибольшее из них. Идея решения: надо вывести на экран первое число, если оно больше второго, или второе, если оно больше первого. Особенность: действия исполнителя зависят от некоторых условий (если … иначе …). Алгоритмы, в которых последовательность шагов зависит от выполнения некоторых условий, называются разветвляющимися. К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 44 Вариант 1. Блок-схема начало ввод a,b да a > b? max = a; блок «решение» нет полная форма ветвления max = b; вывод max конец К. Поляков, 2006-2012 ? Если a = b? http://kpolyakov.narod.ru Программирование на языке Си 45 Вариант 1. Программа main() { int a, b, max; printf("Введите два целых числа\n"); scanf("%d%d", &a, &b ); if (a > b) { полная форма max = a; условного } оператора else { max = b; } printf("Наибольшее число %d", max); } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 46 Условный оператор if ( условие ) { // что делать, если условие верно } else { // что делать, если условие неверно } Особенности: • вторая часть (else …) может отсутствовать (неполная форма) • если в блоке один оператор, можно убрать { } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 47 Что неправильно? if ( a > b ) { a = b; } else b = a; if ( a > b ) a = b; else b = a; К. Поляков, 2006-2012 if ( a > b ) { a = b; } else b = a; if ( a = c = else b = a > b ){ b; 2*a; } a; http://kpolyakov.narod.ru Программирование на языке Си 48 Вариант 2. Блок-схема начало ввод a,b max = a; да b > a? нет неполная форма ветвления max = b; вывод max конец К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 49 Вариант 2. Программа main() { int a, b, max; printf("Введите два целых числа\n"); scanf("%d%d", &a, &b ); max = a; неполная форма if (b > a) условного оператора max = b; printf("Наибольшее число %d", max); } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 50 Вариант 2Б. Программа main() { int a, b, max; printf("Введите два целых числа\n"); scanf("%d%d", &a, &b ); max = b; if ( a ??? > b ) ???= a; max printf("Наибольшее число %d", max); } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 51 Задания «3»: Ввести два числа и вывести их в порядке возрастания. Пример: Введите два числа: 15 9 Ответ: 9 15 «4»: Ввести три числа и найти наибольшее из них. Пример: Введите три числа: 4 15 9 Наибольшее число 15 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 52 Задания «5»: Ввести пять чисел и найти наибольшее из них. Пример: Введите пять чисел: 4 15 9 56 Наибольшее число 56 К. Поляков, 2006-2012 4 http://kpolyakov.narod.ru Программирование на языке Си Тема 4. Сложные условия К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 54 Сложные условия Задача. Фирма набирает сотрудников от 25 до 40 лет включительно. Ввести возраст человека и определить, подходит ли он фирме (вывести ответ «подходит» или «не подходит»). Особенность: надо проверить, выполняются ли два условия одновременно. ? Можно ли решить известными методами? К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 55 Вариант 1. Алгоритм начало ввод x да да 'подходит' x <= 40? x >= 25? нет нет 'не подходит' 'не подходит' конец К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Вариант 1. Программа 56 main() { int x; printf("Введите возраст\n"); scanf("%d", &x); if (x >= 25) if (x <= 40) printf("Подходит"); else printf("Не подходит"); else printf("Не подходит"); } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 57 Вариант 2. Алгоритм начало ввод x да x >= 25 и x <= 40? нет 'не подходит' 'подходит' конец К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 58 Вариант 2. Программа main() { int x; printf("Введите возраст\n"); scanf("%d", &x); if ( x >= 25 && x <= 40 ) printf("Подходит"); else printf("Не подходит"); } К. Поляков, 2006-2012 сложное условие http://kpolyakov.narod.ru Программирование на языке Си 59 Сложные условия Сложное условие – это условие, состоящее из нескольких простых условий (отношений), связанных с помощью логических операций: ! – НЕ (not, отрицание, инверсия) && – И (and, логическое умножение, конъюнкция, одновременное выполнение условий) || – ИЛИ (or, логическое сложение, дизъюнкция, выполнение хотя бы одного из условий) Простые условия (отношения) < <= > >= == равно К. Поляков, 2006-2012 != не равно http://kpolyakov.narod.ru Программирование на языке Си 60 Сложные условия Порядок выполнения сложных условий: • выражения в скобках • ! (НЕ, отрицание) • <, <=, >, >= • ==, != • && (И) • || (ИЛИ) Пример: 2 1 6 3 5 4 if ( !(a > b) || c != d && b == a) { ... } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 61 Сложные условия Истинно или ложно при a = 2; b = 3; c = 4; 1 !(a > b) 1 a < b && b < c !(a >= b) || c == d a < c || b < c && b < a 0 a > b || !(b < c) Для каких значений x x x x x x x x < < > > < < > > 6 6 6 6 6 6 6 6 К. Поляков, 2006-2012 && && && && || || || || x x x x x x x x < > < > < > < > 1 1 x истинны условия: 10 10 10 10 10 10 10 10 (-, 6) (6, 10) (10, ) (-, 10) (-, 6) (10,) (-, ) (6, ) x<6 x > 10 x < 10 x>6 http://kpolyakov.narod.ru Программирование на языке Си 62 Задания «3»: Ввести три числа и определить, верно ли, что они вводились в порядке возрастания. Пример: Введите три числа: 4 5 17 да «4»: Ввести номер месяца и вывести название времени года. Пример: Введите номер месяца: 4 весна К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 63 Задания «5»: Ввести возраст человека (от 1 до 150 лет) и вывести его вместе с последующим словом «год», «года» или «лет». Пример: Введите возраст: 24 Вам 24 года К. Поляков, 2006-2012 Введите возраст: 57 Вам 57 лет http://kpolyakov.narod.ru Программирование на языке Си Тема 5. Циклы К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 65 Циклы Цикл – это многократное выполнение одинаковых действий. • цикл с известным числом шагов • цикл с неизвестным числом шагов (цикл с условием) Задача. Вывести на экран 5 раз слово «Привет». Особенность: одинаковые действия выполняются 5 раз. ? Можно ли решить известными методами? К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 66 Циклы #include <stdio.h> main() { printf("Привет!\n"); printf("Привет!\n"); printf("Привет!\n"); printf("Привет!\n"); printf("Привет!\n"); } ? К. Поляков, 2006-2012 Что плохо? http://kpolyakov.narod.ru Программирование на языке Си 67 Циклы Блок-схема: начало сделали 5 раз? да конец нет printf("Привет!\n"); тело цикла К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 68 Циклы ? Как отсчитать ровно 5 раз? ? Как запоминать, сколько раз уже сделали? N := N + 1 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 69 Циклы начало еще не сделали ни одного раза N = 0; всё ли сделали N == 5? цикл да конец нет printf("Привет!\n"); N = N + 1; N++; К. Поляков, 2006-2012 считаем очередной шаг http://kpolyakov.narod.ru Программирование на языке Си 70 Циклы с условием main() { int N; N = 0; while ( N != 5 ) { printf("Привет!\n"); N ++; } } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 71 Цикл с условием Вместо знаков вопроса добавьте числа и операторы так, чтобы цикл выполнился ровно 5 раз: main() { int N; N = 5; 0 ) while ( N != ??? { printf("Привет!\n"); ???; N = N - 1; N --; } } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 72 Что получим? // Пример 1 main() { int N; N = 1; while ( N <= 5 ) { printf("%d\n", N); N ++; } } К. Поляков, 2006-2012 1 2 3 4 5 http://kpolyakov.narod.ru Программирование на языке Си 73 Что получим? // Пример 2 main() { int N; N = 1; while ( N <= 5 ) { printf("%d\n", N); N = N + 2; } N += 2; } К. Поляков, 2006-2012 1 3 5 http://kpolyakov.narod.ru Программирование на языке Си 74 Что получим? // Пример 3 2 main() 4 { 6 int N; 8 N = 2; 10 while ( N != 5 ) 12 { 14 printf("%d\n", N); 16 N += 2; ... } } ! Условие цикла никогда не станет ложным – это зацикливание! К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 75 Что получим? // Пример 4 main() { int N; N = 1; while ( N != 5 ) { printf("%d\n", N*N*N); N = N + 1; } } К. Поляков, 2006-2012 1 8 27 64 125 http://kpolyakov.narod.ru Программирование на языке Си 76 Что получим? // Пример 4 main() { int N; N = 5; while ( N >= 1 ) { printf("%d\n", N*N*N); N = N - 1; } } К. Поляков, 2006-2012 125 64 27 8 1 http://kpolyakov.narod.ru Программирование на языке Си 77 Задания «3»: Ввести натуральное число вывести квадраты и кубы всех чисел от 1 до этого числа. Пример: Введите натуральное число: 3 1: 1 1 2: 4 8 3: 9 27 «4»: Ввести два целых числа a и b (a ≤ b) и вывести квадраты все чисел от a до b. Пример: Введите два числа: 4 5 4*4=16 5*5=25 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 78 Задания «5»: Ввести два целых числа a и b (a ≤ b) и вывести сумму квадратов всех чисел от a до b. Пример: Введите два числа: 4 10 Сумма квадратов 371 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Цикл с неизвестным числом шагов 79 Пример: Отпилить полено от бревна. Сколько раз надо сделать движения пилой? Задача: Ввести целое число (<2000000) и определить число цифр в нем. Идея решения: Отсекаем последовательно последнюю цифру, увеличиваем счетчик. n count 123 0 12 1 1 2 0 3 Проблема: Неизвестно, сколько шагов надо сделать. Решение: Надо остановиться, когда n = 0, т.е. надо делать «пока n != 0». К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 80 Алгоритм начало обнулить счетчик цифр ввод n count = 0; выполнять «пока n != 0» n != 0? нет да count = count + 1; n = n / 10; count конец К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 81 Программа main() { int n, count; , n1; printf("Введите целое число\n"); scanf("%d", &n); count = 0; n1 = n; while (n != 0) выполнять { «пока n != 0» count ++; n = n / 10; } Что плохо? ? printf("В числе %d нашли %d цифр", n1, n, count); } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 82 Цикл с условием while ( условие ) { // т ело цикла } Особенности: • можно использовать сложные условия: while ( a < b && b < c ) { ... } • если в теле цикла только один оператор, скобки {} можно не писать: while ( a < b ) a ++; К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 83 Цикл с условием Особенности: • условие пересчитывается каждый раз при входе в цикл • если условие на входе в цикл ложно, цикл не выполняется ни разу a = 4; b = 6; while ( a > b ) a = a– b; • если условие никогда не станет ложным, программа зацикливается a = 4; b = 6; while ( a < b ) d = a + b; К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 84 Сколько раз выполняется цикл? a = 4; b = 6; while ( a < b ) a ++; 2 раза a =6 a = 4; b = 6; while ( a < b ) a += b; 1 раз a = 10 a = 4; b = 6; while ( a > b ) a ++; 0 раз a =4 a = 4; b = 6; while ( a < b ) b = a - b; 1 раз b = -2 a = 4; b = 6; while ( a < b ) a --; К. Поляков, 2006-2012 зацикливание http://kpolyakov.narod.ru Программирование на языке Си 85 Задания «3»: Ввести целое число и определить, верно ли, что в нём ровно 3 цифры. Пример: Введите число: 123 Да. Введите число: 1234 Нет. «4»: Ввести целое число и найти сумму его цифр. Пример: Введите целое число: 1234 Сумма цифр числа 1234 равна 10. К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 86 Задания «5»: Ввести целое число и определить, верно ли, что в его записи есть две одинаковые цифры, стоящие рядом. Пример: Введите целое число: 1232 Нет. Введите целое число: 1224 Да. «6»: Ввести целое число и определить, верно ли, что в его записи есть две одинаковые цифры, НЕ обязательно стоящие рядом. Пример: Введите целое число: 1234 Нет. К. Поляков, 2006-2012 Введите целое число: 1242 Да. http://kpolyakov.narod.ru Программирование на языке Си 87 Задания-2 «3»: Ввести целое число и определить, верно ли, что в нём ровно 1 цифра «9». Пример: Введите число: 193 Да. Введите число: 1994 Нет. «4»: Ввести целое число и определить, верно ли, что все его цифры четные. Пример: Введите число: 2684 Да. К. Поляков, 2006-2012 Введите число: 2994 Нет. http://kpolyakov.narod.ru Программирование на языке Си 88 Задания-2 «5»: Ввести целое число и определить, верно ли, что все его цифры расположены в порядке возрастания. Пример: Введите целое число: 1238 Да. Введите целое число: 1274 Нет. «6»: Ввести целое число и «перевернуть» его, так чтобы первая цифра стала последней и т.д. Пример: Введите целое число: 1234 4321 К. Поляков, 2006-2012 Введите целое число: 782 287 http://kpolyakov.narod.ru Программирование на языке Си 89 Вычисление НОД НОД = наибольший общий делитель двух натуральных чисел – это наибольшее число, на которое оба исходных числа делятся без остатка. Перебор: 1. Записать в переменную k минимальное из двух чисел. 2. Если a и b без остатка делятся на k, то стоп. 3. Уменьшить k на 1. 4. Перейти к шагу 2. ? ? Где будет НОД? это цикл с условием! Почему алгоритм обязательно закончится? К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 90 Алгоритм Евклида Надо: вычислить наибольший общий делитель (НОД) чисел a и b. Заменяем большее из двух чисел разностью большего и меньшего до тех пор, пока они не станут равны. Это и есть НОД. НОД(a,b)= НОД(a-b, b) = НОД(a, b-a) Евклид (365-300 до. н. э.) Пример: НОД (14, 21) = НОД (14, 21-14) = НОД (14, 7) = НОД (7, 7) = 7 много шагов при большой разнице чисел: НОД (1998, 2) = НОД (1996, 2) = … = 2 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 91 Блок-схема алгоритма начало a = b? да нет нет b=b-a К. Поляков, 2006-2012 a > b? конец да a=a-b http://kpolyakov.narod.ru Программирование на языке Си 92 Алгоритм Евклида while ( a != b ) { if ( a > b ) a = a – b; else b = b – a; } ? ? ? Где будет НОД? Как его вывести? Как вывести НОД в формате НОД(14,21) = 7? А без дополнительных переменных? К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 93 Модифицированный алгоритм Евклида Заменяем большее из двух чисел остатком от деления большего на меньшее до тех пор, пока меньшее не станет равно нулю. Тогда большее — это НОД. НОД(a,b)= НОД(a % b, b) = НОД(a, b % a) Пример: НОД (14, 21) = НОД (14, 7) = НОД (0, 7) = 7 Еще один вариант: НОД(2·a,2·b)= 2·НОД(a, b) НОД(2·a,b)= НОД(a, b) | при нечетном b К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 94 Алгоритм Евклида «3»: Составить программу для вычисления НОД с помощью алгоритма Евклида. «4»: Составить программу для вычисления НОД с помощью модифицированного алгоритма Евклида и заполнить таблицу: a 64168 358853 6365133 17905514 549868978 b 82678 691042 11494962 23108855 298294835 НОД(a,b) К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 95 Алгоритм Евклида «5»: Выполнить задание на «4» и подсчитать число шагов алгоритма для каждого случая. a 64168 358853 6365133 17905514 549868978 b 82678 691042 11494962 23108855 298294835 НОД(a,b) шагов К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 96 Последовательности Примеры: • 1, 2, 3, 4, 5, … an = n a1 = 1, an+1 = an + n • 1, 2, 4, 7, 11, 16, … • 1, 2, 4, 8, 16, 32, … 1 1 3 1 5 , , , , , ... • 2 2 8 4 32 bn an cn К. Поляков, 2006-2012 a1 = 1, an+1 = an+1 an = 2n-1 a1 = 1, an+1 = 2an 1 2 3 4 5 , , , , , ... 2 4 8 16 32 b1 = 1, bn+1 = bn+1 c1 = 2, cn+1 = 2cn http://kpolyakov.narod.ru Программирование на языке Си 97 Последовательности Задача: найти сумму всех элементов последовательности, 1 2 3 4 5 1, , , , , , ... 2 4 8 16 32 которые по модулю больше 0,001: 1 2 3 4 5 S 1 ... 2 4 8 16 32 Элемент последовательности (начиная с №2): b a z c К. Поляков, 2006-2012 n 1 2 3 4 5 ... b 1 2 3 4 5 ... c 2 4 8 16 32 ... z -1 1 -1 1 -1 ... b = b+1; c = 2*c; z = -z; http://kpolyakov.narod.ru Программирование на языке Си 98 Алгоритм начальные значения начало SS == 0; 0; b = 1; c = 2; z = -1; a = 1; |a| > 0.001? новый элемент изменение К. Поляков, 2006-2012 первый элемент нет да S S = S + a; конец a = z*b/c; b = b + 1; c = 2*c; z = -z; ? Перестановка? http://kpolyakov.narod.ru Программирование на языке Си 99 Программа #include <math.h> математические функции main() чтобы не было { fabs – модуль округления при вещественного int b, c, z; делении начальные float S, a;, b; значения числа S = 0; z = -1; b = 1; c = 2; a = 1; while (fabs(a) > 0.001) { S += a; увеличение a = z * b / c; суммы переход к расчет элемента z = - z; следующему последовательности слагаемому b ++; c *= 2; } printf ("S = %10.3f", S); } К. Поляков, 2006-2012 ? Что плохо? http://kpolyakov.narod.ru Программирование на языке Си 100 Задания «4»: Найти сумму элементов последовательности с точностью 0,001: 2 4 6 8 S 1 ... 3 3 5 9 7 27 9 81 Ответ: S = 1.157 «5»: Найти сумму элементов последовательности с точностью 0,001: 2 4 6 8 10 S 1 ... 2 3 3 9 5 27 8 81 13 243 Ответ: S = 1.220 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 101 Цикл с постусловием Задача: Ввести целое положительное число (<2000000) и определить число цифр в нем. Проблема: Как не дать ввести отрицательное число или ноль? Решение: Если вводится неверное число, вернуться назад к вводу данных (цикл!). Особенность: Один раз тело цикла надо сделать в любом случае проверку условия цикла надо делать в конце цикла (цикл с постусловием). Цикл с постусловием – это цикл, в котором проверка условия выполняется в конце цикла. К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 102 Цикл с постусловием: алгоритм начало ввод n тело цикла да n <= 0? нет основной алгоритм условие блок «типовой процесс» конец К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 103 Программа main() { int n; do { printf("Введите положительное число\n"); scanf("%d", &n); } условие while ( n <= 0 ); ... // основной алгоритм } Особенности: • тело цикла всегда выполняется хотя бы один раз • после слова while («пока…» ) ставится условие продолжения цикла К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 104 Сколько раз выполняется цикл? a = 4; b = 6; do { a ++; } while (a <= b); 3 раза a =7 a = 4; b = 6; do { a += b; } while ( a <= b ); 1 раз a = 10 a = 4; b = 6; do { a += b; } while ( a >= b ); зацикливание a = 4; b = 6; do b = a - b; while ( a >= b ); a = 4; b = 6; do a += 2; while ( a >= b ); К. Поляков, 2006-2012 2 раза b =6 зацикливание http://kpolyakov.narod.ru Программирование на языке Си Задания (с защитой от неверного ввода) 105 «4»: Ввести натуральное число и определить, верно ли, что сумма его цифр равна 10. Пример: Введите число >= 0: -234 Нужно положительное число. Введите число >= 0: 1234 Да Введите число >= 0: 1233 Нет «5»: Ввести натуральное число и определить, какие цифры встречаются несколько раз. Пример: Введите число >= 0: 2323 Повторяются: 2, 3 К. Поляков, 2006-2012 Введите число >= 0: 1234 Нет повторов. http://kpolyakov.narod.ru Программирование на языке Си Тема 6. Циклы с переменной К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 107 Цикл c переменной Цикл – это многократное выполнение одинаковой последовательности действий. • цикл с известным числом шагов • цикл с неизвестным числом шагов (цикл с условием) Задача. Вывести на экран кубы целых чисел от 1 до 8 (от a до b). Особенность: одинаковые действия выполняются 8 раз. ? Можно ли решить известными методами? К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 108 Алгоритм начало N = 1; N <= 8? нет конец да cubeN = N*N*N; вывод cubeN N ++; К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 109 Цикл с переменной Задача: вывести кубы натуральных чисел от 1 до 8. main() { int N, cubeN; 3 действия с N N = 1; while ( N <= 8 ) { cubeN = N*N*N; printf("%4d\n", cubeN); N++; } } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 110 Алгоритм (с блоком «цикл») начало N = 1,8 блок «цикл» конец cubeN = N*N*N; N, cubeN К. Поляков, 2006-2012 тело цикла http://kpolyakov.narod.ru Программирование на языке Си 111 Программа main() { int N, cubeN; переменная цикла начальное значение заголовок цикла конечное значение цикл изменение на for (N=1; (N=1; N<=8; N<=8; N++) N++) (i=1; i<=8; i++) for каждом шаге: начало цикла i=i+1 цикл работает, пока это { тело цикла условие верно cubeN = N*N*N;; N*N*N; printf("%4d %4d\n", N, cubeN); } конец цикла ровные } столбики К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 112 Цикл с уменьшением переменной Задача. Вывести на экран кубы целых чисел от 8 до 1 (в обратном порядке). Особенность: переменная цикла должна уменьшаться. Решение: for ( N = 8; N >= 1; N -- ) { cubeN = N*N*N; printf("%4d %4d\n", N, cubeN); } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 113 Цикл с переменной for (начальные значения; условие продолжения цикла; изменение на каждом шаге) { // тело цикла } Примеры: for (a = 2; a < b; a+=2) { ... } for (a = 2, b = 4; a < b; a+=2) { ... } for (a = 1; c < d; x++) { ... } for (; c < d; x++) { ... } for (; c < d; ) { ... } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 114 Цикл с переменной Особенности: • условие проверяется в начале очередного шага цикла, если оно ложно цикл не выполняется; • изменения (третья часть в заголовке) выполняются в конце очередного шага цикла; • если условие никогда не станет ложным, цикл может продолжаться бесконечно (зацикливание) for(i=1; i<8; i++) { i--; } ! Не рекомендуется менять переменную цикла в теле цикла! • если в теле цикла один оператор, скобки {} можно не ставить: for (i = 1; i < 8; i++) a += b; К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 115 Цикл с переменной Особенности: • после выполнения цикла во многих системах устанавливается первое значение переменной цикла, при котором нарушено условие: for (i=1; i<=8; i++) printf("Привет"); printf("i=%d", i); for (i=8; i>=1; i--) printf("Привет"); printf("i=%d", i); К. Поляков, 2006-2012 i=9 i=0 http://kpolyakov.narod.ru Программирование на языке Си 116 Сколько раз выполняется цикл? a = 1; for(i=1; i<4; i++) a++; a= 4 a = 1; for(i=1; i<4; i++) a = a+i; a= 7 a = 1; b=2; for(i=3; i >= 1; i--)a += b; a= 7 a = 1; for(i=1; i >= 3; i--)a = a+1; a = 1; for(i=1; i<= 4; i--)a ++; К. Поляков, 2006-2012 a= 1 зацикливание http://kpolyakov.narod.ru Программирование на языке Си 117 Замена for на while и наоборот for( i=1; i<=10; i++) { // тело цикла } i = 1; while ( i <= 10 ) { // тело цикла i ++; } for ( i=a; i>=b; i--) { // тело цикла } i = a; while ( i >= b ) { // тело цикла i --; } ! В языке Си замена цикла for на while и наоборот возможна всегда! К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 118 Задания «3»: Ввести натуральное число N и вывести числа от N до 1 (через одно) в порядке убывания. Пример: Введите натуральное число: 8 Ответ: 8 6 4 2 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 119 Задания «4»: Ввести два целых числа a и b (a ≤ b) и вывести кубы всех чисел от a до b. Пример: Введите два числа: 4 6 4*4*4=64 5*5*5=125 6*6*6=216 «5»: Ввести целое число a и вывести сумму квадратов всех чисел от 1 до a с шагом 0.1. Пример: Введите последнее число: 3 Сумма 91.7 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 120 Задания «3»: Ввести натуральное число вывести квадраты и кубы всех чисел от 1 до этого числа. Пример: Введите натуральное число: 3 1: 1 1 2: 4 8 3: 9 27 «4»: Ввести два целых числа a и b (a ≤ b) и вывести квадраты все чисел от a до b. Пример: Введите два числа: 4 5 4*4=16 5*5=25 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 121 Задания «5»: Ввести два целых числа a и b (a ≤ b) и вывести сумму квадратов всех чисел от a до b. Пример: Введите два числа: 4 10 Сумма квадратов 371 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Тема 7. Оператор выбора К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 123 Оператор выбора Задача: Ввести номер месяца и вывести количество дней в этом месяце. Решение: Число дней по месяцам: 28 дней – 2 (февраль) 30 дней – 4 (апрель), 6 (июнь), 9 (сентябрь), 11 (ноябрь) 31 день – 1 (январь), 3 (март), 5 (май), 7 (июль), 8 (август), 10 (октябрь), 12 (декабрь) Особенность: Выбор не из двух, а из нескольких вариантов в зависимости от номера месяца. ? Можно ли решить известными методами? К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 124 Алгоритм начало ввод M M = 1? нет M = 2? да D = 31; да D = 28; оператор выбора нет M = 12? нет ни один вариант не подошел ошибка да D = 31; вывод D конец К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 125 Программа main() { int M, D; printf("Введите номер месяца:\n"); выйти из scanf("%d", &M); switch switch ( M ) { case 2: D = 28; break; case 4: case 6: case 9: case 11: D = 30; break; case 1: case 3: case 5: case 7: case 8: case 10: case 12: D = 31; break; ни один default: D = -1; } вариант не подошел if (D > 0) printf("В этом месяце %d дней.", D); else printf("Неверный номер месяца"); } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 126 Оператор выбора Задача: Ввести букву и вывести название животного на эту букву. Особенность: выбор по символьной величине. main() { char c; printf("Введите первую букву названия животного:\n"); scanf("%c", &c); switch ( c ) { case 'а': printf("Антилопа"); break; case 'б': printf("Бизон"); break; case 'в': printf("Волк"); break; default: printf("Я не знаю!"); } } ? Что будет, если везде убрать break? К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 127 Оператор выбора Особенности: • после switch может быть имя переменной или арифметическое выражение целого типа (int) switch ( i+3 ) { case 1: a = b; break; case 2: a = c; } или символьного типа (char) • нельзя ставить два одинаковых значения: switch ( x ) { case 1: a = b; break; case 1: a = c; } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Задания (с защитой от неверного ввода) 128 «4»: Ввести номер месяца и вывести количество дней в нем, а также число ошибок при вводе. Пример: Введите номер месяца: Введите номер месяца: -2 2 Введите номер месяца: В этом месяце 28 дней. 11 Вы вводили неверно 0 раз. В этом месяце 30 дней. Вы вводили неверно 1 раз. «5»: Ввести номер месяца и номер дня, вывести число дней, оставшихся до Нового года. Пример: Введите номер месяца: 12 Введите день: 25 До Нового года осталось 6 дней. К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Тема 8. Отладка программ К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Отладка программ 130 Отладка – поиск и исправление ошибок в программе. Англ. debugging, bug = моль, жучок Методы: • трассировка – вывод сигнальных сообщений • отключение части кода (в комментарии) • пошаговое выполнение – выполнить одну строчку программы и остановиться • точки останова – выполнение программы останавливается при достижении отмеченных строк (переход в пошаговый режим) • просмотр и изменение значений переменных в пошаговом режиме К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 131 Трассировка main() { int i, X; printf("Введите целое число:\n"); scanf("%d", &X); printf("Введено X=%d\n", X); for(i=1; i<10; i++) { printf("В цикле: i=%d, X=%d\n", i, X); ... } printf("После цикла: X=%d\n", X); ... } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Отключение части кода (комментарии) 132 main() комментарий до { конца строки // int i, X; printf("Введите целое число:\n"); scanf("%d", &X); X *= X +X 2; // X *= + 2; закомментированны for(i=1; i<10; i++) X *= i; й блок /* … */ while ( X( >X 5> )5 {) { /* while ... } } */ ... } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 133 Точки останова ЛКМ или Ctrl+F5 это точка останова F8 – запустить и выполнить до следующей точки останова F7 – выполнить одну строку Shift+F7 – войти в процедуру (функцию) Ctrl-F7 – выполнять дальше Ctrl-Alt-F2 – остановить программу К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Просмотр значений переменных ПКМ К. Поляков, 2006-2012 134 навести мышь на имя переменной http://kpolyakov.narod.ru Программирование на языке Си Тема 9. Графика К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 136 Система координат (0,0) X y x Y К. Поляков, 2006-2012 (x,y) http://kpolyakov.narod.ru Программирование на языке Си 137 Принцип сэндвича открыть окно для графики рисование в графическом режиме закрыть окно для графики К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Структура графической программы #include <graphics.h> 138 библиотека для работы с графикой #include <conio.h> main() { ширина высота initwindow ( 400, 300 ); открыть окно для графики ... // рисуем на экране getch(); closegraph(); } К. Поляков, 2006-2012 чтобы посмотреть результат закрыть окно http://kpolyakov.narod.ru Программирование на языке Си 139 Цвета Код Название Код Название 0 BLACK 8 DARKGRAY 1 BLUE 9 LIGHTBLUE 2 GREEN 10 LIGHTGREEN 3 CYAN 11 LIGHTCYAN 4 RED 12 LIGHTRED 5 MAGENTA 13 LIGHTMAGENTA 6 BROWN 14 YELLOW 7 LIGHTGRAY 15 WHITE К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 140 Полная палитра цветов цвет = R + G + B Red Green Blue красный зеленый синий 0..255 0..255 0..255 R = 218 G = 164 B = 32 ? R = 135 G = 206 B = 250 Сколько разных цветов? 256·256·256 = 16 777 216 (True Color) К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 141 Управление цветом Цвет линий и текста: set color = установить цвет номер цвета G B setcolor ( 12 ); R setcolor ( COLOR(255,255,0) ); Цвет и стиль заливки: set fill style = установить стиль заливки setfillstyle ( стиль, цвет ); 0 – выключить 3..6 – наклонные линии 1 – сплошная 7..8 – сетка 9..11 – точечная К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 142 Точки, отрезки и ломаные цвет (x, y) putpixel (x, y, 9); (x1, y1) (x2, y2) (x2, y2) (x1, y1) (x3, y3) (x5, y5) setcolor ( 10 ); line (x1, y1, x2, y2); setcolor ( 12 ); moveto (x1, y1); lineto (x2, y2); lineto (x3, y3); lineto (x4, y4); lineto (x5, y5); (x4, y4) К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 143 Прямоугольники (x1, y1) setcolor ( 9 ); rectangle (x1, y1, x2, y2); (x2, y2) (x1, y1) (x2, y2) (x1, y1) (x2, y2) К. Поляков, 2006-2012 стиль (1 - сплошная) цвет setfillstyle ( 1, 12 ); bar (x1, y1, x2, y2); setfillstyle ( 1, 12 ); bar (x1, y1, x2, y2); setcolor ( 9 ); rectangle (x1, y1, x2, y2); http://kpolyakov.narod.ru Программирование на языке Си 144 Окружность, заливка, текст R (x, y) setcolor ( COLOR(255,0,0) ); circle ( x, y, R ); стиль (1 - сплошная) (x, y) цвет заливки setfillstyle ( 1, 11 ); floodfill ( x, y, 0); цвет границы (x, y) Вася К. Поляков, 2006-2012 setcolor ( 9 ); outtextxy ( x, y, "Вася" ); http://kpolyakov.narod.ru Программирование на языке Си 145 Пример setfillstyle (1, 9); bar (100,100,300,200); setcolor (13); (200, 50) rectangle (100,100,300,200); moveto (100,100); (100, 100) lineto (200, 50); lineto (300,100); setfillstyle (1, 14); floodfill (200, 75, 13); setcolor (15); (300, 200) circle (200, 150,50); Sharik's house setfillstyle (1, 10); floodfill (200,150, 15); setcolor (12); outtextxy (100, 230, "Sharik's house."); К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 146 Задания «5»: «Корона» К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 147 Задания «3»: «Домик» «4»: «Лягушка» К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 148 Штриховка N линий (N=5) x2 x1 h N 1 (x1, y1) h (x2, y2) rectangle (x1, line( x1+h, line( x1+2*h, line( x1+3*h, ... x2, y2); x1+h, y2); x1+2*h, y2); x1+3*h, y2); x x rectangle(x1, y1, x2, y2); h = (x2 – x1) / (N + 1.); for (x = x1+h; x < x2; x += h) line(x, y1, x, y2); К. Поляков, 2006-2012 y1, y1, y1, y1, результат – дробное число ! float x, h; дробная часть x отбрасывается http://kpolyakov.narod.ru Программирование на языке Си 149 Штриховка (программа) N #include <graphics.h> #include <conio.h> main() { int N = 10, x1 = 100, x2 = 300, y1 = 100, y2 = 200; float h, x; h (x2, y2) initwindow(800,600); rectangle (x1, y1, x2, y2); прямоугольник h = (x2 – x1) / (N + 1.); for (x = x1+h; x < x2; x += h) line(x, y1, x, y2); штриховка getch(); closegraph(); } (x1, y1) К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 150 Штриховка a (x1, y1) (x2, y2) (x3+a, y1) (x3, y2) h a x1 x2 x3 x2 h N 1 line( x1+h, y1, x1+h-a, y2); line( x1+2*h, y1, x1+2*h-a, y2); line( x1+3*h, y1, x1+3*h-a, y2); ... x x-a после каждого h = (x3 – x2) / (N + 1.); шага выполняются a = x2 – x1; две команды x = x1 + h; for (i = 1; i <= N; i ++, x += h ) Плюсы и минусы? line(x, y1, x-a, y2); ? К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 151 Штриховка hx (x1, y1) hx hy x2 x1 N 1 К. Поляков, 2006-2012 y2 y1 N 1 line( x1, y1+hy, x1+hx, y1+hy ); line( x1, y1+2*hy, x1+2*hx, y1+2*hy); line( x1, y1+3*hy, x1+3*hx, y1+3*hy); ... y (x2, y2) hy y x hx = (x2 – x1) / (N + 1.); hy = (y2 – y1) / (N + 1.); x = x1 + hx; y = y1 + hy; for (i=1; i <= N; i++) { line( x1, y, x, y ); x += hx; y += hy; } http://kpolyakov.narod.ru Программирование на языке Си 152 Задания «3»: Ввести с клавиатуры количество линий, построить фигуру и выполнить штриховку: «4»: Ввести с клавиатуры количество линий, построить фигуру и выполнить штриховку: или К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 153 Задание «5»: Ввести с клавиатуры количество линий и построить фигуру: К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 154 Как менять цвет? (x1, y1) серый: R = G = B Цвет: COLOR(c, c, c) Изменение c: 0, ..., 255 N (x2, y2) Шаг изменения c: 255 hc N hc = 255 / N; c = 0; for ( i=1; i<=N+1; i++ ) { setfillstyle ( 1, COLOR(c,c,c) ); floodfill( ???, ???, 15 ); цвет c += hc; границы } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 155 Как менять цвет? setfillstyle( 1, COLOR(c,c,c) ); floodfill ( ???, ???, 15 ); правая hc = 255 / N; (x1, y1) x граница c = 0; полосы x = x1 + h; (x-1, y1+1) for ( i=1; i <= N+1; i++ ) { setfillstyle(1,COLOR(c,c,c)); COLOR(c,c,c) floodfill ( x-1, y1+1, 15 ); (x2, y2) x += h; c += hc; } ? Как объединить циклы штриховки и заливки? К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 156 Задания «4»: Ввести с клавиатуры число линий штриховки и построить фигуру, залив все области разным цветом. «5»: Ввести с клавиатуры число окружностей и построить фигуру, залив все области разным цветом. К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Тема 10. Графики функций (только с 9 класса) К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 158 Построение графиков функций Задача: построить график функции y = 3 sin(x) на интервале от 0 до 2π. Анализ: максимальное значение ymax = 3 при x = π/2 минимальное значение ymin = -3 при x = 3π/2 Проблема: функция задана в математической системе координат, строить надо на экране, указывая координаты в пикселях. К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 159 Преобразование координат Математическая система координат Экранная система координат (пиксели) Y (0,0) x (0,0) (x,y) y b X k – масштаб (длина изображения единичного отрезка на экране) К. Поляков, 2006-2012 a xэ yэ (xэ,yэ) xэ = a + kx yэ = b - ky http://kpolyakov.narod.ru Программирование на языке Си 160 Программа 2π const a = 50, b = 200, k = 50; const float xmin = 0, xmax =2*M_PI; float x, y, h = 0.01; h – шаг изменения x int xe, ye, w; w – длина оси ОХ в пикселях w = (xmax - xmin)*k; оси координат line(a-10, b, a+w, b); line(a, 0, a, 2*b); for (x = xmin; x < xmax; x += h) обязательно { #include <math.h> y = 3*sin(x); xe = a + k*x; координаты точки на ye = b - k*y; экране putpixel (xe, ye, 12); } Что плохо? К. Поляков, 2006-2012 ? http://kpolyakov.narod.ru Программирование на языке Си 161 Как соединить точки? Алгоритм: Если первая точка перейти в точку (xэ,yэ) иначе отрезок в точку (xэ,yэ) выбор варианта действий К. Поляков, 2006-2012 Программа: переменнаяфлаг (1 или 0) int first; ... начальное значение first = 1; for (x = xmin; x < xmax; x += h) { ... if ( first ) { moveto(xe, ye); first = 0; } else lineto(xe, ye); ... } http://kpolyakov.narod.ru Программирование на языке Си Задания 162 «4»: Построить график функции y = x2 на интервале [-3,3]. «5»: Построить график функции (эллипс) x2 y2 1 16 9 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Тема 11. Процедуры К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 164 Процедуры Задача: Построить фигуру: ? Можно ли решить известными методами? Особенность: Три похожие фигуры. общее: размеры, угол поворота отличия: координаты, цвет ? Сколько координат надо задать? К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 165 Процедуры Процедура – это вспомогательный алгоритм, который предназначен для выполнения некоторых действий. Применение: • выполнение одинаковых действий в разных местах программы • разбивка программы (или другой процедуры) на подзадачи для лучшего восприятия Задача Подзадача1 1.1 К. Поляков, 2006-2012 1.2 1.3 Подзадача2 2.1 2.2 Подзадача3 2.3 3.1 3.2 3.3 http://kpolyakov.narod.ru Программирование на языке Си 166 Процедуры Порядок разработки: • выделить одинаковое или похожее (три фигуры) • найти в них общее (размеры, форма, угол поворота) и отличия (координаты, цвет) • отличия записать в виде неизвестных переменных, они будут параметрами процедуры (x, y-60) 60 (x, y) 100 (x+100, y) имя процедуры параметры void Tr( int x, int y, int c ) { цвет ... тело } координаты void – «пустой» (некоторые действия) К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Процедуры 167 формальные параметры void Tr( int x, int y, int c ) { 60 moveto ( x, y ); lineto ( x, y-60 ); 100 (x+100, y) (x, y) lineto ( x+100, y ); lineto ( x, y ); тело процедуры setfillstyle ( 1, c ); floodfill ( x+20, y-20, 15); } (x, y-60) «Формальные параметры» могут изменяться, заранее неизвестны (обозначаются именами, как переменные). К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Программа 60 (100,100) 100 вызовы процедуры К. Поляков, 2006-2012 168 формальные параметры #include <conio.h> #include <graphics.h> void Tr( int x, int y, int c) { ... } main() процедура { initwindow (400, 300); Tr (100, 100, COLOR(0,0,255)); Tr (200, 100, COLOR(0,255,0)); Tr (200, 160, COLOR(255,0,0)); getch(); closegraph(); } фактические параметры http://kpolyakov.narod.ru Программирование на языке Си 169 Процедуры Особенности: • обычно процедуры расположены выше основной программы • в заголовке процедуры перечисляются формальные параметры, они обозначаются именами, поскольку могут меняться void Tr( int x, int y, int c ) • при вызове процедуры в скобках указывают фактические параметры (числа или арифметические выражения) в том же порядке Tr ( 200, 100, COLOR(255,0,0)); x К. Поляков, 2006-2012 y c http://kpolyakov.narod.ru Программирование на языке Си 170 Процедуры Особенности: • для каждого формального параметра в заголовке процедуры указывают его тип void A ( int x, float y, char z ) { ... } • внутри процедуры параметры используются так же, как и переменные • в процедуре можно объявлять дополнительные локальные переменные, остальные процедуры не имеют к ним доступа void A ( int x, float y, char z ) { локальные int a2, bbc = 345; int a2, bbc = 345; переменные ... } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 171 Как поменять местами? Задача: поменять местами содержимое двух чашек. 2 Задача: поменять местами содержимое двух ячеек памяти. y x x = y; y = x; ? c = x; x = y; y = c; 4 6 Можно ли обойтись без c? К. Поляков, 2006-2012 2 ? 4 c 6 4 http://kpolyakov.narod.ru Программирование на языке Си 172 Параметры-переменные Задача: составить процедуру, которая меняет местами значения двух переменных. Особенности: надо, чтобы изменения, сделанные в процедуре, стали известны вызывающей программе. void Swap ( int a, int b ) эта процедура { работает с int c; копиями c = a; a = b; b = c; параметров } main() { x = 1, y = 2 int x = 1, y = 2; Swap ( x, y ); printf ( "x = %d, y = %d", x, y ); } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 173 Параметры-переменные void Swap ( int && a, int && b ) { int c; параметры могут изменяться c = a; a = b; b = c; } Применение: таким образом процедура (и функция) может возвращать несколько значений Запрещенные варианты вызова Swap ( 2, 3 ); // числа Swap ( x+z, y+2 ); // выражения К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 174 Задания «3»: Используя одну процедуру, построить фигуру. «4»: Используя одну процедуру, построить фигуру. К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 175 Задания «5»: Используя одну процедуру, построить фигуру. К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Тема 12. Анимация К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 177 Анимация Анимация (англ. animation) – оживление изображения на экране. Задача: внутри синего квадрата 400 на 400 пикселей слева направо двигается желтый квадрат 20 на 20 пикселей. Программа останавливается, если нажата клавиша Esc или квадрат дошел до границы синей области. Проблема: как изобразить перемещение объекта на экране? Привязка: состояние объекта задается координатами (x,y) Принцип анимации: 1. рисуем объект в точке (x,y) 2. задержка на несколько миллисекунд 3. стираем объект 4. изменяем координаты (x,y) 5. переходим к шагу 1 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 178 Как «поймать» нажатие клавиши? kbhit() – функция, определяет, было ли нажатие на (любую!) клавишу (0 – не было, не 0 – было). if ( kbhit() != 0 ) if ( kbhit() ) printf("Нажата какая-то клавиша..."); else printf("Нет нажатия..."); getch() – функция, которая определяет код нажатой клавиши: 27 = Esc, 13 = Enter, 32 = пробел, … int c; if ( kbhit() ) { printf("Нажата какая-то клавиша..."); c = getch(); printf("Код клавиши %d", c); } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 179 Как выйти из цикла? ? Как не допустить выход за границу поля? x + 20 < 400 для kbhit() и getch() #include <conio.h> main() пока не вышли за границу синего квадрата { ... while ( x + 20 < 400 ) если нажата клавиша ... { if ( kbhit() ) if ( getch() == 27 ) break; ... } если нажата клавиша ... с кодом 27 (Esc), } выйти из цикла К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Процедура (рисование и стирание) (x, y) (x+20, y+20) 180 Идеи • одна процедура рисует и стирает • стереть = нарисовать цветом фона • границу квадрата отключить (в основной программе) цвет: желтым рисуем, синим стираем void Draw( int x, int y, int color ) { сплошная заливка setfillstyle ( 1, color ); цветом color bar ( x, y, x+20, y+20 ); } залитый прямоугольник К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 181 Полная программа #include <conio.h> #include <graphics.h> void Draw ( int x, int y, int color ) { ... } main() процедура { int x, y; initwindow (500, 500); setfillstyle(1, COLOR(0,0,255)); bar (0, 0, 399, 399); синий фон x = 0; y = 240; начальные /* анимация */ координаты closegraph(); } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 182 Цикл анимации пока не вышли из синего квадрата while ( x + 20 < 400 ) { выход по клавише Esc if ( kbhit() ) if ( getch() == 27 ) break; Draw ( x, y, COLOR(255,255,0) ); delay ( 20 ); ждем 20 мс Draw ( x, y, COLOR(0,0,255) ); x ++; } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 183 Задания «3»: Квадрат двигается справа налево: «4»: Два квадрата двигаются в противоположных направлениях: К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 184 Задания «5»: Два квадрата двигаются в противоположных направлениях и отталкиваются от стенок синего квадрата: К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 185 Управление клавишами Задача: жёлтый квадрат внутри синего квадрата управляется клавишами-стрелками. Коды клавиш: влево – 75 вверх – 72 Esc – 27 вправо – 77 вниз – 80 если было нажатие Проблема: как изменять направление движения? на клавишу, … Решение: if нажата клавиша ( kbhit() ) { получить код клавиши - code code = getch(); if (code == 27) break; выход по Esc получить if (code 75) код switch ( == code ) x { --; клавиши if case (code == x77) ++; 75: --;x break; 77: ++;y break; if case (code == x72) --; 72: --;y break; if case (code == y80) ++; } case 80: y ++; перемещение } } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 186 Программа void Draw (int x, int y, int color) { ... процедура } main() { основной цикл int x, y, code; ... обработка while ( 1 ) { Draw(x, y, COLOR(255,255,0)); нажатия на клавишу delay(20); Draw(x, y, COLOR(0,0,255)); if ( kbhit() ) { ... } } } К. Поляков, 2006-2012 ? ? Что плохо? Как убрать мигание? http://kpolyakov.narod.ru Программирование на языке Си 187 Задания «3»: Квадрат в самом начале стоит в правом нижнем углу, и двигается при нажатии стрелок только вверх или влево: «4»: Квадрат двигается при нажатии стрелок, однако не может выйти за границы синего квадрата: К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 188 Задания «5»: Квадрат непрерывно двигается, при нажатии стрелок меняет направление и отталкивается от стенок синего квадрата: К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 189 Вращение (для 8-11 класса) Задача: изобразить модель вращения Земли вокруг Солнца. Проблема: движение по окружности, как изменять координаты? Решение: использовать в качестве независимой переменной (менять в цикле) угол поворота α (x, y) L α x = x0 + L·cos(α) y = y0 – L·sin(α) (x0, y0) К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 190 Процедура цвет: желтый – рисуем, черный – стираем void Draw( int x, int y, int color ) { постоянная const int r = 10; радиус Земли setcolor ( color ); установили цвет линий circle ( x, y, r ); } (x,y) r К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 191 Константы и переменные #include <math.h> // математические функции void Draw ( int x, int y, int color ) { ... } main() { const int rSun = 60, // радиус Солнца L = 150, // радиус орбиты Земли x0 = 200, // координаты центра Солнца y0 = 200; int x, y, // координаты Земли code; // код нажатой клавиши float a, ha; // угол поворота, шаг initwindow( 500, 500 ); ... } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Основной цикл 192 рисуем Солнце: белый контур, желтая заливка circle ( x0, y0, rSun ); setfillstyle(1, COLOR(255,255,0)); floodfill(x0, y0, COLOR(255,255,255)); a = 0; // начальный угол ha = M_PI/180; // шаг 1o за 20 мс while(1) { новые x = x0 + L*cos(a); координаты y = y0 - L*sin(a); Draw ( x, y, COLOR(0,255,255) ); delay ( 20 ); ждем 20 мс выход по Esc Draw(x, y, 0); if ( kbhit() ) if ( 27 == getch() ) break; a = a + ha; поворот на ha } #include<math.h> // sin, cos, M_PI closegraph(); К. Поляков, 2006-2012 ! http://kpolyakov.narod.ru Программирование на языке Си Задания 193 «4»: Изобразить модель Солнца с двумя планетами, которые вращаются в противоположные стороны: «5»: Изобразить модель системы Солнце-ЗемляЛуна: К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Тема 13. Функции К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 195 Функции Функция – это вспомогательный алгоритм (подпрограмма), результатом работы которого является некоторое значение. Примеры: • вычисление модуля числа, x • расчет значений по сложным формулам • ответ на вопрос (простое число или нет?) Зачем? • для выполнения одинаковых расчетов в различных местах программы • для создания общедоступных библиотек функций ? К. Поляков, 2006-2012 В чем отличие от процедур? http://kpolyakov.narod.ru Программирование на языке Си 196 Функции Задача: составить функцию, которая вычисляет наибольшее из двух значений, и привести пример ее использования Функция: тип результата формальные параметры int Max ( int a, int b ) { if ( a > b ) return a ; else return - вернуть результат функции return b ; } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 197 Функции Особенности: • в начале заголовка ставится тип результата int Max ( int a, int b ) • формальные параметры описываются так же, как и для процедур float qq ( int a, float x, char c ) • можно использовать параметры-переменные int Vasya (int & a, int & b ) • функции обычно располагаются до основной программы К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 198 Функции Особенности: • можно объявлять и использовать локальные переменные float qq ( int a, int b) { float x, y; ... } ! локальные переменные Локальные переменные недоступны в основной программе и других процедурах и функциях. К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 199 Программа int Max ( int a, int b ) { формальные ... параметры } main() фактические { параметры int a, b, с; printf ( "Введите два числа\n" ); scanf ( "%d%d", &a, &b ); вызов функции c = Max ( a, b ); printf ( "Наибольшее число %d", c ); } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 200 Задания «4»: Составить функцию, которая определяет сумму всех чисел от 1 до N и привести пример ее использования. Пример: Введите число: 100 сумма чисел от 1 до 100 = 5050 «5»: Составить функцию, которая определяет, сколько зерен попросил положить на N-ую клетку изобретатель шахмат (на 1-ую – 1 зерно, на 2-ую – 2 зерна, на 3-ю – 4 зерна, …) Пример: Введите номер клетки: 28 На 28-ой клетке 134217728 зерен. К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Задания (вариант 2 для 9-11 класса) 201 «4»: Составить функцию, которая определяет наибольший общий делитель двух натуральных и привести пример ее использования. Пример: Введите два числа: 14 21 НОД(14,21)=7 «5»: Составить функцию, которая вычисляет функцию синус как сумму ряда (с точностью 0.001) x3 x5 x7 sin x x 3! 5! 7! x в радианах! Пример: Введите угол в градусах: 45 sin(45) = 0.707 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 202 Логические функции Задача: составить функцию, которая определяет, верно ли, что заданное число – простое. Особенности: • ответ – логическое значение: «да» (1) или «нет» (0) • результат функции можно использовать как логическую величину в условиях (if, while) Алгоритм: считаем число делителей в интервале от 2 до N-1, если оно не равно нулю – число составное. count = 0; for (i = 2; i < N; i ++) if ( N % i == 0) count ++; if ( count == 0 ) // число N простое} else // число N составное К. Поляков, 2006-2012 ? Как улучшить? http://kpolyakov.narod.ru Программирование на языке Си 203 Функция: простое число или нет int Prime ( int N ) перебор только до { int count = 0, i; for (i = 2; i*i <= N; i++) if (N % i == 0) count ++; return (count == 0); } N if (count == 0) return 1; else return 0; К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 204 Логические функции #include <stdio.h> int Prime ( int N ) { ... } функция main() { int N; printf ( "Введите целое число\n" ); scanf ( "%d", &N ); if ( Prime( Prime( NN )) ) printf ("%d - простое число", N); else printf ("%d - составное число", N); } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 205 Задания «4»: Составить функцию, которая определяет, верно ли, что сумма его цифр – четное число. Пример: Введите число: Введите число: 136 245 Сумма цифр четная. Сумма цифр нечетная. «5»: Составить функцию, которая определяет, верно ли, что в заданном числе все цифры стоят по возрастанию. Пример: Введите число: 258 Верно. К. Поляков, 2006-2012 Введите число: 528 Неверно. http://kpolyakov.narod.ru Программирование на языке Си Тема 14. Случайные числа К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 207 Случайные числа Случайные явления: везде… • бросание монеты («орел» или «решка») • падение снега • броуновское движение • помехи при телефонной связи • шум радиоэфира Случайные числа – это такая последовательность чисел, для которой невозможно предсказать следующее даже зная все предыдущие. Проблема: как получить на компьютере? Возможные решения: • использовать внешний источник шумовых помех • с помощью математических преобразований К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 208 Псевдослучайные числа Псевдослучайные числа – это такая последовательность чисел, которая обладает свойствами случайных чисел, но каждое следующее число вычисляется по заданной формуле. a, c, m - целые числа Примеры: 1. Случайные целые числа [0,m) (линейный конгруэнтный метод) 230-1 xn (a xn1 c) mod m xn (16807 xn1 12345) mod 1073741823 остаток от деления простое число 2. Случайные вещественные числа [0,1] xn ( xn 1 ) k дробная часть числа Литература: например, k = 5 Д. Кнут, Искусство программирования для ЭВМ, т.2. К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 209 Распределение случайных чисел Модель: снежинки падают на отрезок [a,b] распределение равномерное a ? b неравномерное a b Сколько может быть разных распределений? К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 210 Распределение случайных чисел Особенности: • распределение – это характеристика всей последовательности, а не одного числа • равномерное распределение одно, компьютерные датчики (псевдо)случайных чисел дают равномерное распределение • неравномерных – много • любое неравномерное можно получить с помощью равномерного a b x1 x2 x 2 равномерное распределение К. Поляков, 2006-2012 a b x1 x2 x12 x 12 равномерное распределение http://kpolyakov.narod.ru Программирование на языке Си 211 Генератор случайных чисел в Си #include <stdlib.h> // случайные числа RAND_MAX – максимальное случайное целое число (обычно RAND_MAX = 32767) rand() – случайное целое число в интервале [0,RAND_MAX] int x, y; x = rand(); // первое число [0,RAND_MAX] y = rand(); // уже другое число srand(N) – установить начальное значение последовательности случайных чисел N: srand ( 345 ); // начнем с 345 К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си Целые числа в заданном интервале 212 Целые числа в интервале [0,N-1]: int random(int N) { return rand()% N; } Примеры: x = random ( 100 ); x = random ( z ); // интервал [0,99] // интервал [0,z-1] Целые числа в интервале [a,b]: x = random ( z ) + a; // интервал [a,z-1+a] x = random (b – a + 1) + a; // интервал [a,b] К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 213 Генератор случайных чисел в Си Вещественные числа в интервале [0,1] float x; [0,RAND_MAX] = [0,32767] x = 1.*rand() / RAND_MAX; // интервал [0,1] Вещественные числа в интервале [0,z] x = 1.*z*rand() / RAND_MAX; Вещественные числа в интервале [a,z+a] x = 1.*z*rand() / RAND_MAX + a; Вещественные числа в интервале [a,b] x = 1.*(b-a)*rand() / RAND_MAX + a; К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 214 Случайные числа Задача: заполнить прямоугольник 400 на 300 пикселей равномерно точками случайного цвета Как получить случайные координаты точки? x = random ( 400 ); y = random ( 300 ); Как добиться равномерности? обеспечивается автоматически при использовании функции random Как получить случайный цвет? R = random( 256 ); G = random ( 256 ); B = random( 256 ); COLOR(R,G,B) К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 215 Программа #include <graphics.h> #include <conio.h> #include <stdlib.h> функция для получения случайного числа от 0 до N-1 int random(int N) { return rand() % N; } main() { int x, y, R, G, B; initwindow ( 500, 500 ); // цикл до нажатия на Esc closegraph(); } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 216 Основной цикл бесконечный цикл??? выход по Esc while ( 1 ) { if ( kbhit() ) if ( 27 == getch() ) break; x = random(400); случайные y = random(300); координаты R = random(256); G = random(256); случайный цвет B = random(256); putpixel ( x, y, COLOR(R,G,B)); } К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 217 Задания «3»: Заполнить квадрат точками случайного цвета. размер квадрата ввести с клавиатуры: Пример: Введите размер квадрата: 150 «4»: Заполнить область точками случайного цвета: К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 218 Залания «5»: Заполнить область точками случайного цвета: или К. Поляков, 2006-2012 http://kpolyakov.narod.ru Программирование на языке Си 219 Конец фильма ПОЛЯКОВ Константин Юрьевич д.т.н., учитель информатики высшей категории, ГОУ СОШ № 163, г. Санкт-Петербург kpolyakov@mail.ru К. Поляков, 2006-2012 http://kpolyakov.narod.ru