Информатика, 10 класс К. Ю. Поляков, Е. А. Еремин
Скачать 0.95 Mb.
|
§ 57. Ветвления Условный оператор Возможности, описанные в предыдущих параграфах, позволяют писать линейные программы, в которых операторы выполняются последовательно друг за другом, и порядок их выполнения не зависит от входных данных. В большинстве реальных задач порядок действий может несколько изменяться, в зависимости оттого, какие данные поступили. Например, программа для системы пожарной сигнализации Информатика, 10 класс К.Ю. Поляков, Е.А. Еремин http://kpolyakov.spb.ru 13 должна выдавать сигнал тревоги, если данные сдатчиков показывают повышение температуры или задымленность. Для этой цели в языках программирования предусмотрены условные операторы. Например, для того, чтобы записать в переменную M максимальное из значений переменных a и b, можно использовать оператор if ( a > b ) M = a; else M = b; Здесь использованы да ключевых слова if означает если, а else – иначе. Если условие в скобках после if истинно, выполняется оператор, записанный после скобок, а если условие ложно, то выполняется оператор после слова else. Обратите внимание, что после слова else никакого условия нет. В приведенном примере условный оператор записан в полной форме в обоих случаях (истинно условие или ложно) нужно выполнить некоторые действия. Программа выбора максимального значения может быть написана иначе M = a; if (b > a) M = b; Здесь использован условный оператор в неполной форме, потому что в случае, когда условие ложно, ничего делать не требуется (нет слова else и операторов после него. Для того, чтобы сделать текст программы более понятным, всё тело условного оператора сдвинуто вправо. Вообще говоря, это необязательно вся программа на языках C и C++ может быть записана в одну строку. Тем не менее, запись с отступами значительно повышает читаемость программ, и мы далее будем её использовать 6 Часто при каком-то условии нужно выполнить сразу несколько действий. Например, в задаче сортировки значений переменных a и b по возрастанию нужно поменять местами значения этих переменных, если a > b: if ( a > b ) { c = a; a = b; b = c; } В этом случае нужно записать составной оператор, в котором между фигурными скобками может быть сколько угодно команд. Кроме знаков < ив условиях можно использовать другие знаки отношений <= (меньше или равно, >= (больше или равно, == (равно) и != (неравно. Внутри условного оператора могут находиться любые операторы, в том числе и другие условные операторы. Например, пусть возраст Андрея записан в переменной a, а возраст Бориса – в переменной b. Нужно определить, кто из них старше. Одним условным оператором тут не обойтись, потому что есть три возможных результата старше Андрей, старше Борис и оба одного возраста. Решение задачи можно записать так if ( a > b ) Андрей старше else if ( a == b ) Одного возраста else Борис старше if ( a > b ) cout << Андрей старше else if ( a == b ) cout << Одного возраста else cout << Борис старше 6 В некоторых языках, например, в языке Python, отступы обязательны, и все строки одного уровня вложенности должны иметь одинаковые отступы. Информатика, 10 класс К.Ю. Поляков, Е.А. Еремин http://kpolyakov.spb.ru 14 Условный оператор, проверяющий равенство, находится внутри блока else, поэтому он называется вложенным условным оператором. Как видно из этого примера, использование вложенных условных операторов позволяет выбрать один из нескольких (а не только из двух) вариантов. Нужно помнить правило любой блок else относится к ближайшему предыдущему оператору, у которого такого блока еще не было. Например, оператор if (a > b) А else if (a == b) printf( "=" ); else Б может быть записан с выделением структуры так if (a > b) А else if (a == b) printf( "=" ); else Б Здесь второй блок else относится к ближайшему (второму, вложенному) условному оператору, поэтому буква Б будет выведена только тогда, когда оба условия окажутся ложными. Сложные условия Предположим, что ООО Рога и Копыта набирает сотрудников, возраст которых от 25 до 40 лет включительно. Нужно написать программу, которая запрашивает возраст претендента и выдает ответ подходит он или не подходит поэтому признаку. На качестве условия в условном операторе можно указать любое логическое выражение, в том числе сложное условие, составленное из простых отношений с помощью логических операций (связок) И, ИЛИ и НЕ (см. главу 3). В языках C и C++ они записываются так И – &&, ИЛИ – || и НЕ – ! восклицательный знак. Пусть в переменной v записан возраст сотрудника. Тогда нужный фрагмент программы будет выглядеть следующим образом if ( v >= 25 && v <= 40 ) подходит else не подходит if ( v >= 25 && v <= 40 ) cout << подходит else cout << не подходит Обратите внимание, что каждое простое условие необязательно заключать в скобки. Это связано стем, что в языках C и C++ отношения имеют более высокий приоритет, чем логические операции, которые выполняются в таком порядке сначала все операции НЕ, затем – И, ив самом конце ИЛИ (во всех случаях – слева направо. Для изменения порядка действий используют круглые скобки. Множественный выбор Условный оператор предназначен, прежде всего, для выбора одного из двух вариантов простого ветвления. Иногда нужно сделать выбор из нескольких возможных вариантов. Пусть, например, в переменной m хранится номер месяца, и нужно вывести на экран его русское название. Конечно, в этом случае можно использовать 12 условных операторов if (m == 1 ) январь if (m == 2 ) февраль ... if (m == 12 ) декабрь if (m == 1 ) cout << январь if (m == 2 ) cout << февраль ... if (m == 12 ) cout << декабрь Вместо многоточия могут быть записаны аналогичные операторы для остальных значений m. Нов языках C и С+ для подобных случаев есть специальный оператор выбора switch ( m ) { case 1 : январь break ; case 2 : февраль break ; ... switch ( m ) { case 1 : cout << январь break ; case 2 : cout << февраль break ; ... Информатика, 10 класс К.Ю. Поляков, Е.А. Еремин http://kpolyakov.spb.ru 15 22.10.2015 case 12 : декабрь break ; default : ошибка } case 12 : cout << декабрь break ; default : cout << ошибка } Кроме очевидных 12 блоков здесь добавлен еще один, который сигнализирует об ошибочном номере месяца. Он начинается ключевым словом default . Обратите внимание, что каждый блок заканчивается оператором break (в переводе с английского прервать. Если его не поставить, программа перейдет наследующий блок. Поэтому программа switch ( m ) { case 1 : январь case 2 : февраль case 3 : март default : ошибка } switch ( m ) { case 1 : cout << январь case 2 : cout << февраль case 3 : cout << март default : cout << ошибка } для случая m = 2 выведет на экран текст февральмартошибка 1. Чем отличаются разветвляющиеся алгоритмы от линейных 2. Как выдумаете, почему не все задачи можно решить с помощью линейных алгоритмов 3. Как выдумаете, хватит ли линейных алгоритмов и ветвлений для разработки любой программы. Почему нельзя выполнить обмен значений двух переменных в два шага a = b; b = a? 5. Чем отличаются условные операторы в полной и неполной формах Как выдумаете, можно ли обойтись только неполной формой 6. Какие отношения вызнаете Как обозначаются отношения равно и неравно. Что такое сложное условие 8. Как определяется порядок вычислений в сложном условии 9. Зачем нужен оператор выбора Как можно обойтись без него 10. Как в операторе выбора определить, что нужно делать, если ни один вариант не подошёл? 11. Зачем в операторе выбора используется оператор break? 12. Как выполнить для какого-то варианта несколько операторов 1. Покажите, что приведенная программа не всегда верно определяет максимальное из трёх чисел, записанных в переменные a , b и c : if (a > b) M = a; else M = b; if (с > b) M = с else M = b; Приведите контрпример, то есть значения переменных, при котором в переменной M будет получен неверный ответ. Как нужно доработать программу, чтобы она всегда работала правильно. Напишите программу, которая выбирает максимальное и минимальное из пяти введённых чисел. 3. Напишите программу, которая определяет, верно ли, что введённое число – трёхзначное. 4. Напишите программу, которая вводит номер месяца и выводит название времени года. Оператор выбора использовать не разрешается. При вводе неверного номера месяца должно быть выведено сообщение об ошибке. 5. Решите предыдущую задачу с помощью оператора выбора. 6. Напишите программу, которая вводит с клавиатуры номер месяца и определяет, сколько дней в этом месяце. При вводе неверного номера месяца должно быть выведено сообщение об ошибке. Задачи и задания ? Контрольные вопросы Информатика, 10 класс К.Ю. Поляков, Е.А. Еремин http://kpolyakov.spb.ru 16 22.10.2015 7. Напишите программу, которая вводит с клавиатуры номер месяца и день, и определяет, сколько дней осталось до Нового года. При вводе неверных данных должно быть выведено сообщение об ошибке. 8. Напишите программу, которая вводит возраст человека (целое число, не превышающее 120) и выводит этот возраст со словом год, года или лет. Например, «21 год, «22 года, «25 лет. 9. Напишите программу, которая вводит целое число, не превышающее 100, и выводит его прописью, например, 21 → двадцать один. 10. Напишите программу, которая вводит координаты точки на плоскости и определяет, попала ли эта точка в заштрихованную область. 11. Напишите два варианта программы, которая вводит координаты точки на плоскости и определяет, попала ли эта точка в заштрихованную область. Один вариант программы должен использовать сложные условия, второй – обходиться без них. § 58. Циклические алгоритмы Как организовать цикл Цикл – это многократное выполнение одинаковых действий. Доказано, что любой алгоритм может быть записан с помощью трёх алгоритмических конструкций циклов, условных операторов и последовательного выполнения команд (линейных алгоритмов. Простейший цикл, который 10 раз выводит на экран слово привет, на псевдокоде записывается так ж) з) и) 1 2 2 = + y x 1 − = x y x y 1 2 2 = + y x 1 = y x y 1 = x 2 2x y = 1 = x x y − =1 где+ y x x y = x y x y − = x y 1 в) x y 2 г) б) а) 1 4 2 2 = + а) 5 , 0 = y x y ) sin(x y = б) в) 2 2 x y − = x y = x y x Информатика, 10 класс К.Ю. Поляков, Е.А. Еремин http://kpolyakov.spb.ru 17 сделай 10 раз вывод "привет" Подумаем, как можно организовать такой цикл. Вызнаете, что программа после запуска выполняется автоматически. И при этом на каждом шаге нужно знать, сколько раз уже выполнен цикли сколько ещё осталось выполнить. Для этого необходимо использовать ячейку памяти, в которой будет запоминаться количество выполненных шагов цикла (счётчик шагов. Сначала можно записать вне ноль (ни одного шага не сделано, а после каждого шага цикла увеличивать значение ячейки на единицу. На псевдокоде алгоритм можно записать так (здесь и далее операции, входящие в тело цикла, выделяются отступами счётчик = пока счётчик < 10 { вывод привет увеличить счётчик на 1 } Возможен и другой вариант сразу записать в счётчик нужное количество шагов, и после каждого шага цикла уменьшать счётчик на 1. Тогда цикл должен закончиться при нулевом значении счёт- чика: счётчик = пока счётчик > 0 { вывод привет уменьшить счётчик на 1 } Этот вариант несколько лучше, чем предыдущий, поскольку счётчик сравнивается с нулём, а такое сравнение выполняется в процессоре автоматически (см. главу 4). В этих примерах мы использовали цикл с условием, который выполняется до тех пор, пока некоторое условие не становится ложно. Циклы с условием Рассмотрим следующую задачу определить количество цифр в десятичной записи целого положительного числа. Будем предполагать, что исходное число записано в переменную n целого типа. Сначала составим алгоритм решения этой задачи. Чтобы считать что-то в программе, нужно использовать переменную, которую называют счётчиком. Для подсчёта количества цифр необходимо как-то отсекать эти цифры по одной, сначала или с конца, каждый раз увеличивая счётчик. Начальное значение счётчика должно быть равно нулю, так как до выполнения алгоритма ещё не найдено ни одно цифры. Для отсечения первой цифры необходимо заранее знать, сколько цифр в десятичной записи числа, то есть нужно заранее решить ту задачу, которую мы решаем. Следовательно, этот метод не подходит. Отсечь последнюю цифру проще – достаточно разделить число нацело на 10 (поскольку речь идет о десятичной системе. Операции отсечения и увеличения счётчика нужно выполнять столько раз, сколько цифр в числе. Как же поймать момент, когда цифры кончатся Несложно понять, что в этом случае результат очередного деления на 10 будет равен нулю, это и говорит о том, что отброшена последняя оставшаяся цифра. Изменение переменной и счётчика для начального значения 1234 можно записать в виде таблицы, показанной справа. Псевдокод выглядит так счётчик = пока n > 0 { отсечь последнюю цифру n увеличить счётчик на 1 } Запись такого цикла на языке C выглядит так n счётчик 1234 0 123 1 12 2 1 3 0 4 Информатика, 10 класс К.Ю. Поляков, Е.А. Еремин http://kpolyakov.spb.ru 18 22.10.2015 count = 0 ; while ( n > 0 ) { n = n / 10 ; count ++; } Здесь целочисленная переменная-счётчик имеет имя count. Слово while переводится с английского как показа ним в скобках записывается условие работы цикла (в данном случае – пока n > 0). Фигурные скобки ограничивают составной оператор. Если в теле цикла нужно выполнить только один оператор, эти скобки можно не ставить. Напомним, что операция деления для целых чисел всегда даёт целое число (остаток отбрасывается. Обратите внимание, что проверка условия выполняется вначале очередного шага цикла. Такой цикл называется циклом с предусловием (то есть с предварительной проверкой условия) или циклом пока. Если в начальный момент значение переменной n будет нулевой или отрицательное, цикл не выполнится ни одного раза. В данном случае количество шагов цикла пока неизвестно, оно равно количеству цифр введенного числа, то есть зависит от исходных данных. Кроме того, этот же цикл может быть использован ив том случае, когда число шагов известно заранее или может быть вычислено k = 0 ; while ( k < 10 ) { printf ( привет" ); k ++; } k = 0 ; while ( k < 10 ) { cout << привет k ++; } Если условие в заголовке цикла никогда не нарушится, цикл будет работать бесконечно долго. В этом случае говорят, что программа зациклилась. Например, если забыть увеличить переменную в предыдущем цикле, программа зациклится k = 0 ; while ( k < 10 ) { printf ( привет ); } k = 0 ; while ( k < 10 ) { cout << привет } Во многих языках программирования существует цикл с постусловием, в котором условие проверяется после завершения очередного шага цикла. Это полезно в том случае, когда нужно обязательно выполнить цикл хотя бы один раз. Например, пользователь должен ввести с клавиатуры положительное число. Для того, чтобы защитить программу от неверных входных данных, можно использовать такой цикл с постусловием do { Введите n > 0: " ); scanf ( "%d" , &n ); } while ( n <= 0 ); do { cout << Введите n > 0: " ; cin >> n; } while ( n <= 0 ); Этот цикл закончится тогда, когда условие n <= 0 нарушится, то есть станет истинным условие n > 0. А это значит, что пользователь ввел допустимое (положительное) значение. Обратите внимание на важную особенность этого вида цикла при входе в цикл условие не проверяется, поэтому цикл всегда выполняется хотя бы один раз. Цикл с переменной В информатике важную роль играют степени числа 2 (2, 4, 8, 16 и т.д.) Чтобы вывести все степени двойки от 2 1 до 2 10 мы уже можем написать такую программу с циклом пока k = 1 ; n = 2 ; while ( k <= 10 ) { printf ( "%d\n" , n ); k = 1 ; n = 2 ; while ( k <= 10 ) { cout << n << endl; Информатика, 10 класс К.Ю. Поляков, Е.А. Еремин http://kpolyakov.spb.ru 19 22.10.2015 n = n * 2 ; k ++; } n = n * 2 ; k ++; } Вы наверняка заметили, что переменная k используется трижды (см. выделенные блоки в операторе присваивания начального значения, в условии цикла ив теле цикла (увеличение на 1). Чтобы собрать все действия с ней в один оператор, во многие языки программирования введен особый вид цикла – цикл с переменной. В заголовке этого цикла задается начальное значение этой переменной, условие продолжения цикла и изменение переменной в конце каждого шага цикла n = 2 ; for ( k = 1; k <= 10 ; k++) { printf ( "%d\n" , n ); n *= 2 ; } n = 2 ; for ( k = 1; k <= 10 ; k++) { cout << n << endl; n *= 2 ; } С каждым шагом цикла переменная цикла может не только увеличиваться, но и уменьшаться. Следующая программа печатает квадраты натуральных чисел от 10 до 1 в порядке убывания for ( k = 10 ; k >= 1 ; k-- ) printf( "%d\n" , k*k); for ( k = 10 ; k >= 1 ; k-- ) cout << k*k << endl; Шаг изменения переменной цикла может быть любым числом. Например, следующий цикл выводит квадраты нечётных чисел for ( k = 1 ; k <= 10 ; k+= 2 ) printf( "%d\n" , k*k); for ( k = 1 ; k <= 10 ; k+= 2 ) cout << k*k << endl; Вложенные циклы В более сложных задачах часто бывает так, что на каждом шаге цикла нужно выполнять обработку данных, которая также представляет собой циклический алгоритм. В этом случае получается конструкция цикл в цикле или вложенный цикл. Предположим, что нужно найти все простые числа в интервале от 2 до 1000. Простейший ноне самый быстрый) алгоритм решения такой задачи на псевдокоде выглядит так сделать для n от 1 до 1000 если число n простое то вывод n Как же определить, что число простое Как известно, простое число делится только на 1 и само на себя. Если число n не имеет делителей в диапазоне от 2 до n-1, то оно простое, а если хотя бы один делитель в этом интервале найден, то составное. Чтобы проверить делимость числа n на некоторое число k, нужно взять остаток отделения на k. Если этот остаток равен нулю, то n делится на k. Таким образом, программу можно записать так (здесь n, k и count – целочисленные переменные, count обозначает счётчик делителей ++ ) if ( n % k == 0 ) count ++; if ( count == 0 ) printf( "%d\n" , n); } for (n = 2 ; n <= 1000 ; n ++) { count= 0 ; for ( k = 2 ; k < n; k ++ ) if ( n % k == 0 ) count ++; if ( count == 0 ) cout << n << endl; } Попробуем немного ускорить работу программы. Делители числа обязательно идут в парах, причём в любой паре меньший из делителей не превосходит n (иначе получается, что произведение двух делителей, каждый из которых больше n , будет больше, чем n). Поэтому внутренний цикл можно выполнять только до значения n вместо n-1. Для того, чтобы работать только с целыми числами (и таким образом избежать вычислительных ошибок, лучше заменить условие Информатика, 10 класс К.Ю. Поляков, Е.А. Еремин http://kpolyakov.spb.ru 20 22.10.2015 k ≤ n на равносильное ему условие k 2 ≤ n. При этом потребуется перейти к внутреннему циклу с условием count = 0 ; k = 2 ; while ( k*k <= n ) { if ( n % k == 0 ) count ++; k ++; } Чтобы еще ускорить работу цикла, заметим, что когда найден хотя бы один делитель, число уже заведомо составное, и искать другие делители в данной задаче не требуется. Поэтому можно закончить цикл. Для этого в условие работы цикла добавляется условие n % k != 0 , связанное с имеющимся условием с помощью операции И, при этом можно обойтись без переменной count: k = 2 ; while ( k*k <= n && n % k != 0 ) k ++; if ( k*k > n ) printf( "%d\n" , n); После выхода из цикла мы проверяем, какое условие было нарушено. Если k*k>n (нарушено первое условие в заголовке цикла, то число n простое. В любом вложенном цикле переменная внутреннего цикла изменяется быстрее, чем переменная внешнего цикла. Рассмотрим такой вложенный цикл for ( i = 1 ; i <= 4 ; i++ ) { for ( k = 1 ; k <= i; k++ ) { ... } } На первом шаге (при i=1) переменная k принимает единственное значение 1. Далее, при i=2 переменная k принимает последовательно значения 1 и 2. Наследующем шаге при i=3 переменная проходит значения 1, 2 и 3, и т.д. 1. Что такое цикл 2. Сравните цикл с переменной и цикл с условием. Какие преимущества и недостатки есть у каждого из них 3. Что означает выражение цикл с предусловием 4. В каком случае цикл с предусловием не выполняется ни разу 5. В каком случае программа, содержащая цикл с условием, может зациклиться 6. В каком случае цикл с переменной не выполняется ни разу 7. Верно ли, что любой цикл с переменной можно заменить циклом с условием Верно ли обратное утверждение 8. В каком случае можно заменить цикл с условием на цикл с переменной 9. Как будет работать приведенная программа, которая считает количество цифр введённого числа, при вводе отрицательного числа Если высчитаете, что она работает неправильно, укажите, как её нужно доработать. 1. Найдите ошибку в программе k = 0 ; while ( k < 10 ) printf ( привет" ); k = 0 ; while ( k < 10 ) cout << привет << endl; Задачи и задания ? Контрольные вопросы Информатика, 10 класс К.Ю. Поляков, Е.А. Еремин http://kpolyakov.spb.ru 21 Как её можно исправить 2. Напишите программу, которая вводит два целых числа и находит их произведение, не используя операцию умножения. Учтите, что числа могут быть отрицательными. 3. Напишите программу, которая вводит натуральное число N и находит сумму всех натуральных чисел от 1 до N. Используйте сначала цикл с условием, а потом – цикл с переменной. 4. Напишите программу, которая вводит натуральное число N и выводит первые N чётных натуральных чисел. 5. Напишите программу, которая вводит натуральные числа a и b, и выводит квадраты натуральных чисел в интервале от a до b. Например, если ввести 4 и 5, программа должна вывести. Напишите программу, которая вводит натуральные числа a и b, и выводит сумму квадратов натуральных чисел в интервале от a до b. 7. Напишите программу, которая вводит натуральное число N и выводит на экран N псевдослучайных чисел. Запустите её несколько раз, объясните результаты опыта. 8. Напишите программу, которая строит последовательность из N случайных чисел на отрезке от 0 дои определяет, сколько из них попадает в полуинтервалы [0; 0,25), [0,25; 0,5), [0,5; 0,75) и [0,75; 1). Сравните результаты, полученные при N = 10, 100, 1000, 10000. 9. Найдите все пятизначные числа, которые при делении надают в остатке 125, а при делении надают в остатке 111. 10. Напишите программу, которая вводит натуральное число N и выводит на экран все натуральные числа, не превосходящие N и делящиеся на каждую из своих цифр. 11. Числа Армстронга. Натуральное число называется числом Армстронга, если сумма цифр числа, возведенных в N-ную степень (где N – количество цифр в числе) равна самому числу. Например, 153 = 1 3 + 5 3 + 3 3 . Найдите все трёхзначные и четырёхзначные числа Армстронга. 12. Автоморфные числа. Натуральное число называется автоморфным, если оно равно последним цифрам своего квадрата. Например, 25 2 = 625. Напишите программу, которая вводит натуральное число N и выводит на экран все автоморфные числа, не превосходящие N. 13. Напишите программу, которая считает количество чётных цифр введённого числа. 14. Напишите программу, которая считает сумму цифр введённого числа. 15. Напишите программу, которая определяет, верно ли, что введённое число содержит две одинаковых цифры, стоящие рядом (как, например, 221). 16. Напишите программу, которая определяет, верно ли, что введённое число состоит из одинаковых цифр (как, например, 222). 17. Напишите программу, которая определяет, верно ли, что введённое число содержит по крайней мере две одинаковых цифры, возможно, нестоящие рядом (как, например, 212). 18. Используя сначала цикл с условием, а потом – цикл с переменной, напишите программу, которая выводит на экран чётные степени числа 2 от 2 10 до 2 2 в порядке убывания. 19. Алгоритм Евклида для вычисления наибольшего общего делителя двух натуральных чисел, формулируется так нужно заменять большее число на разность большего и меньшего до тех пор, пока одно из них не станет равно нулю тогда второе и есть НОД. Напишите программу, которая реализует этот алгоритм. Какой цикл тут нужно использовать 20. Напишите программу, использующую модифицированный алгоритм Евклида нужно заменять большее число на остаток отделения большего на меньшее до тех пор, пока этот остаток не станет равен нулю тогда второе число и есть НОД. 21. Добавьте в решение двух предыдущих задач вычисление количества шагов цикла. Заполните таблицу (шаги и шаги означают количество шагов двух версия алгоритма Евклида Информатика, 10 класс К.Ю. Поляков, Е.А. Еремин http://kpolyakov.spb.ru 22 22.10.2015 22. Напишите программу, которая вводит с клавиатуры 10 чисел и вычисляет их сумму и произведение. Напишите программу, которая вводит с клавиатуры числа до тех пор, пока не будет введено число 0. В конце работы программы на экран выводится сумма и произведение введенных чисел (не считая 0). 24. Напишите программу, которая вводит с клавиатуры числа до тех пор, пока не будет введено число 0. В конце работы программы на экран выводится минимальное и максимальное из введенных чисел (не считая 0). 25. Напишите программу, которая вводит с клавиатуры натуральное число N и определяет его факториал, то есть произведение натуральных чисел от 1 до N: N N ⋅ ⋅ ⋅ ⋅ = K 3 2 1 ! . Что будет, если ввести большое значение N (например, 20)? 26. Напишите программу, которая вводит натуральные числа A и N и вычисляет A N 27. Напишите программу, которая выводит на экран все цифры числа, начиная с первой. 28. Ряд чисел Фибоначчи задается следующим образом первые два числа равны 1 ( 1 2 1 = = F F ), а каждое следующее равно сумму двух предыдущих 2 1 − − + = n n n F F F . Напишите программу, которая вводит натуральное число N и выводит на экран первые N чисел Фибоначчи. 29. Напишите программу, которая вводит натуральные числа a и b и выводит все простые числа в диапазоне от a до b. 30. Совершенным называется число, равное сумме всех своих делителей, меньших его самого например, число 6=1+2+3). Напишите программу, которая вводит натуральное число N и определяет, является ли число N совершенным. 31. Напишите программу, которая вводит натуральное число N и находит всесовершенные числа в диапазоне от 1 до N. 32. В магазине продается мастика в ящиках по 15 кг, 17 кг, 21 кг. Как купить ровно 185 кг мастики, не вскрывая ящики Сколькими способами можно это сделать 33. Ввести натуральное число N и вывести значение числа 1/N, выделив период дроби. Например или 1/7=0,(142857). 34. В телевикторине участнику предлагают выбрать один из трёх закрытых чёрных ящиков, причём известно, что водном из них – приза в двух других – пусто. После этого ведущий открывает один пустой ящик (ноне тот, который выбрал участники предлагает заново сделать выбор, но уже между двумя оставшимися ящиками. Используя псевдослучайные числа, выполните моделирование 1000 раундов этой игры и определите, что выгоднее делать участнику викторины выбрать тот же ящик, что ив начале игры, или другой 59. Процедуры Что такое процедура Предположим, что в нескольких местах программы требуется выводить на экран сообщение об ошибке Ошибка программы. Это можно сделать, например, так printf ( Ошибка программы ); cout << Ошибка программы 7 Эта задача известна как парадокс Монти Холла, потому что её решение противоречит интуиции и здравому смыслу. a 64168 358853 6365133 17905514 549868978 b 82678 691042 11494962 23108855 298294835 НОД(a,b) шаги шаги Информатика, 10 класс К.Ю. Поляков, Е.А. Еремин http://kpolyakov.spb.ru 23 Конечно, можно вставить этот оператор вывода везде, где нужно вывести сообщение об ошибке. Но тут есть две сложности. Во-первых, строка-сообщение хранится в памяти много раз. Во-вторых, если мы задумаем поменять текст сообщения, нужно будет искать эти операторы вывода по всей программе. Для таких случаев в языках программирования предусмотрены процедуры – вспомогательные алгоритмы, которые выполняют некоторые действия. void Error() { Ошибка программы } main() { int n; scanf ( "%d" , &n ); if ( n < 0 ) Error(); ... } void Error() { cout << Ошибка программы } main() { int n; cin >> n; if ( n < 0 ) Error(); ... } Фактически мы ввели в язык программирования новую команду Error, которая была расшифрована прямо в телепрограммы. Для того, чтобы процедура заработала, в основной программе (или в другой процедуре) необходимо ее вызвать по имени. Процедура начинается с ключевого слова void (пустой, то есть алгоритм, не возвращающий никакого значения. Тело процедуры заключается в фигурные скобки. Процедура расположена выше основной программы, так чтобы в момент вызова процедуры транслятор уже знало ней. Обратите внимание, что ив заголовке процедуры, и при её вывозе после имени процедуры нужно ставить круглые скобки (в данном случае – пустые. Как мы видели, использование процедур сокращает код, если какие-то операции выполняются несколько разв разных местах программы. Кроме того, большую программу разбивают на несколько процедур для удобства, оформляя в виде процедур отдельные этапы сложного алгоритма. Такой подход делает всю программу более понятной. Процедура с параметрами Процедура Error при каждом вызове делает одно и тоже. Более интересны процедуры, которым можно передавать аргументы – данные, которые изменяют выполняемые действия. Внутри процедуры эти данные рассматриваются как внутренние (локальные) переменные и называются параметрами. Предположим, что в программе требуется многократно выводить на экран запись целого числа (0..255) в 8-битном двоичном коде. Старшая цифра в такой записи – это частное отделения числа на 128. Далее возьмем остаток от этого деления и разделим на 64 – получается вторая цифра и т.д. Алгоритм, решающий эту задачу для переменной n, можно записать так k = 128 ; while ( k > 0 ) { printf ( "%d" , n / k ); n = n % k; k = k / 2 ; } k = 128 ; while ( k > 0 ) { cout << n / k; n = n % k; k = k / 2 ; } Писать такой цикл каждый раз, когда нужно вывести двоичное число, очень утомительно. Кроме того, легко сделать ошибку или опечатку, которую будет сложно найти. Поэтому лучше оформить этот вспомогательный алгоритм в виде процедуры. Но этой процедуре нужно передать аргумент – число для перевода в двоичную систему. Программа получается такая void printBin ( int n ) { int k; k = 128 ; while ( k > 0 ) { void printBin ( int n ) { int k; k = 128 ; while ( k > 0 ) { Информатика, 10 класс К.Ю. Поляков, Е.А. Еремин http://kpolyakov.spb.ru 24 22.10.2015 printf ( "%d" , n / k ); n = n % k; k = k / 2 ; } } main() { printBin ( 99 ); } cout << n / k; n = n % k; k = k / 2 ; } } main() { printBin ( 99 ); } Основная программа содержит всего одну команду – вызов процедуры printBin с аргументом 99. В заголовке процедуры в скобках записывают тип и внутреннее имя параметра (то есть имя, по которому к нему можно обращаться в процедуре. В процедуре объявлена локальная (внутренняя) переменная k – она известна только внутри этой процедуры, обратиться к ней из основной программы и из других процедур невозможно. Параметров может быть несколько, в этом случае они перечисляются в заголовке процедуры через запятую (тип данных для каждого параметра указывается отдельно. Например, процедуру, которая выводит на экран среднее арифметическое двух чисел, можно записать так void printSred ( int a, int b ) { printf ( "%f" , (a+b)/ 2 . ); } void printSred ( int a, int b ) { cout << (a+b)/ 2 .; } Изменяемые параметры Напишем процедуру, которая меняет местами значения двух переменных. Проще всего для этого использовать третью переменную void Swap ( int a, int b ) { int c; c = a; a = b; b = c; } main() { int x = 2 , y = 3 ; Swap ( x, y ); printf ( "%d %d" , x, y ); } После запуска этой программы обнаружится, что значения переменных x и y остались прежние на экран будет выведено «2 3». Дело в том, что процедуры работают с копиями переданных ей аргументов. Это значит, что процедура Swap создает в памяти временные локальные переменные с именами a и b и копирует в них переданные значения переменных x и y основной программы. Поэтому и все перестановки в нашей программе были сделаны именно с копиями, а значения переменных и y не изменились. Чтобы решить проблему, нужно явно сказать, чтобы процедура работала с теми же ячейками памяти, что и основная программа. Проще всего это можно сделать в языке C++: для этого в заголовке процедуры перед именем изменяемой переменной ставят знак &: void Swap ( int & a, int & b ) { ... } Теперь процедура решает поставленную задачу на выходе мы увидим «3 2», что и требовалось. В подобных случаях говорят, что параметры передаются по ссылке, а не по значению. Это означает, что фактически в процедуру передается адрес переменной, и можно изменять значение этой переменной, записывая новые данные поэтому адресу. При вызове такой процедуре Swap можно передавать только параметры-переменные, ноне константы (постоянные) и не арифметические выражения. Например, вызовы Swap(2,3) и Информатика, 10 класс К.Ю. Поляков, Е.А. Еремин http://kpolyakov.spb.ru 25 22.10.2015 Swap(x,y+3) противоречат правилам языка программирования, и программа выполняться не будет. В языке С все несколько более сложно процедуре нужно передавать не сами переменные, а их адреса, чтобы она смогла работать с памятью. Вспомните, что с таким приёмом мы уже встречались при изучении функции scanf. Адрес переменной обозначается знаком & и процедура должна вызываться так Swap( & a, & b); Необходимо внести изменения ив саму процедуру void Swap ( int *adrA, int *adrB ) { int c; c = *adrA; *adrA = *adrB; *adrB = c; } Здесь изменены названия параметров, чтобы показать, что мы работаем с адресами переменных. Для того, чтобы получить значение переменной по адресу adrA, нужно использовать запись *adrA. 1. Что такое процедуры В чем смысл их использования 2. Как оформляются процедуры в языках C и C++? 3. Достаточно ли включить процедуру в текст программы, чтобы она сработала 4. Что такое параметры Зачем они используются 5. Какие переменные называются локальными Где они объявляются 6. Как оформляются процедуры, имеющие несколько параметров 7. Что такое изменяемые параметры Зачем они используются 8. Как в заголовке процедуры отличить изменяемый параметр от неизменяемого 9. Чем отличается оформление процедур с изменяемыми параметрами в языках C и C++? 1. Напишите процедуру, которая выводит на экран в столбик все цифры переданного ей числа, начиная с последней. 2. Напишите процедуру, которая выводит на экран в столбик все цифры переданного ей числа, начиная с первой. 3. Напишите процедуру, которая выводит на экран все делители переданного ей числа (в одну строчку. 4. Напишите процедуру, которая выводит на экран запись переданного ей числа в римской системе счисления. 5. Напишите процедуру, которая выводит на экран запись числа, меньшего, чем 8 10 , в виде 10 знаков в восьмеричной системе счисления. 6. Напишите процедуру, которая выводит на экран запись числа, меньшего, чем 2 4 = 65536, в виде х знаков в шестнадцатеричной системе счисления. 7. Напишите процедуру, которая принимает параметр – натуральное число N – и выводит на экран линию из N символов '–'. 8. Напишите процедуру, которая принимает параметр – натуральное число N – и выводит на экран квадрат из звездочек со стороной N. 9. Напишите процедуру, которая принимает числовой параметр – возраст человека в годах, и выводит этот возраст со словом год, года или лет. Например, «21 год, «22 года, «12 лет. 10. Напишите процедуру, которая выводит переданное ей число прописью. Например, 21 → двадцать один. Задачи и задания ? Контрольные вопросы Информатика, 10 класс К.Ю. Поляков, Е.А. Еремин http://kpolyakov.spb.ru 26 22.10.2015 11. Напишите процедуру, которая принимает параметр – натуральное число N – и выводит первые чисел Фибоначчи (см. задания к § 58. ). 12. Напишите процедуру, которая определяет, верно ли, что переданное ей число – простое. Используйте изменяемые параметры. |