![]() Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву ![]() Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Передача параметров по ссылке и по значениюСодержание книги
Поиск на нашем сайте
Передача параметров по значению - еще один способ повысить надежность программирования. Рассмотрим пример. Вот процедура Квадр, вычисляющая периметр и площадь квадрата по его стороне: Dim A As Integer 'сторона Dim P As Integer 'периметр Dim S As Integer 'площадь
Private Sub Квадр(Сторона As Integer, Периметр As Integer, Площадь As Integer) Периметр = 4 * Сторона Площадь = Сторона ^ 2 End Sub
Private Sub Command1_Click() A = 10 Квадр A, P, S Debug.Print "Сторона="; A; "Периметр="; P; "Площадь="; S End Sub Результат: Сторона= 10 Периметр= 40 Площадь= 100 Здесь щелчком по кнопке вы приказываете компьютеру вычислить периметр и площадь квадрата со стороной 10. Компьютер, выполняя тело процедуры Квадр и присваивая значения переменным Периметр и Площадь, тем самым присваивает значения переменным P и S, то есть изменяет содержимое ячеек памяти, отведенных под эти переменные. Говорят, что в этом случае между вызывающей и вызываемой процедурами осуществляется передача параметров по ссылке. Чтобы подчеркнуть, что вы используете именно этот способ передачи параметров, вы можете записать заголовок процедуры так: Private Sub Квадр (Сторона As Integer, ByRef Периметр As Integer, ByRef Площадь As Integer) хоть это и излишне. При этом способе вызываемая процедура получает полный контроль над переменными A, P и S вызывающей процедуры и может присваивать им все, что хочет. Это удобно, но небезопасно. Ведь в этом случае переменные становятся беззащитными против ошибок в вызываемой процедуре. Так, программист может случайно, для каких-то других нужд, включить в процедуру какой-нибудь оператор, меняющий значение параметра Сторона, например, Сторона=1. Предположим, в этом случае процедура примет такой вид: Private Sub Квадр(Сторона As Integer, Периметр As Integer, Площадь As Integer) Периметр = 4 * Сторона Площадь = Сторона ^ 2 Сторона = 1 End Sub Тогда результаты будут напечатаны неверно: Сторона= 1 Периметр= 40 Площадь= 100 Чтобы обезопасить себя от такой ситуации, вы можете явно приказать Бэйсику, чтобы он не смел трогать такую-то переменную, отдающую свое значение параметру. Для этого достаточно заголовок процедуры написать так: Private Sub Квадр (ByVal Сторона As Integer, Периметр As Integer, Площадь As Integer) Теперь, что бы ни произошло с параметром Сторона, значение переменной A меняться не будет. Убедитесь, что теперь снова все в порядке. Такой способ передачи параметров называется передачей параметров по значению.
Не переборщите с надежностью. Так, глупо было бы писать Private Sub Квадр (ByVal Сторона As Integer, ByVal Периметр As Integer, ByVal Площадь As Integer) так как результат в этом случае был бы такой: Сторона= 10 Периметр= 0 Площадь= 0
Задание 130: На двух метеостанциях (A и B) в течение года измерялась температура. Соответственно созданы два массива чисел длиной 365. Затем оказалось, что на обеих станциях термометры были испорчены: на станции A термометр все время показывал температуру на 2 градуса выше настоящей, а на станции B - на 3 градуса ниже. Написать процедуру с двумя параметрами, которая исправляет один исходный массив и с ее помощью исправить оба массива. Один параметр - величина поправки, другой - массив температур. Индукция. Рекурсия Понятие рекурсии - сложное, но необходимое понятие для программиста. Здесь мне никуда не уйти от классического примера о факториале. Факториалом целого положительного числа N называется произведение всех целых чисел от 1 до N. Например, факториал пяти равен 1*2*3*4*5, то есть 120. Факториал единицы считается равным 1. Все понятно. Однако, существует еще один, совершенно ужасный способ определения, что такое факториал. Этот способ определения называется индуктивным. Вот он: "Факториал единицы равен 1. Факториал любого целого положительного числа N, большего единицы, равен числу N, умноженному на факториал числа N-1 ." Если вам уже все ясно, значит вы - профессор математики. Для обычных людей поясню. Возьмем какое-нибудь конкретное N, например, 100. Тогда ужасное определение будет звучать проще: Факториал числа 100 равен числу 100, умноженному на факториал числа 99. Ну и что? И как же отсюда узнать, чему равен какой-нибудь конкретный факториал, скажем, факториал трех? Будем рассуждать также совершенно чудовищным образом:
Смотрю в определение: Факториал трех равен 3 умножить на факториал двух. Не знаю, чему равен факториал двух. Поэтому спускаюсь на ступеньку ниже.
Смотрю в определение: Факториал двух равен 2 умножить на факториал единицы. Не знаю, сколько это. Спускаюсь еще на ступеньку.
Смотрю в определение: Факториал единицы равен 1. Вот, наконец-то - впервые узнал конкретное число. Значит можно подниматься обратно.
Поднимаюсь на одну ступеньку. Факториал двух равен 2 умножить на 1, то есть 2. Хорошо.
Поднимаюсь еще на ступеньку. Факториал трех равен 3 умножить на 2, то есть 6. Задача решена!
Рассуждая таким образом, можно вычислить факториал любого числа. Этот способ рассуждения называется рекурсивным. : Какое отношение все это имеет к компьютерам? Дело в том, что рекурсивный способ рассуждений реализован во многих языках программирования, в том числе - и в Visual Basic. Значит, этим языкам должен быть понятен и индуктивный способ написания программ. Обозначим кратко факториал числа N, как Factorial(N), и снова повторим наш индуктивный способ объяснения: "Если N=1, то Factorial(N) = 1. Если N>1, то Factorial(N) вычисляется умножением N на Factorial(N-1) ."
В соответствии с этим объяснением напишем на Visual Basic функцию Factorial для вычисления факториала: Private Function Factorial(ByVal N As Integer) As Long If N = 1 Then Factorial = 1 If N > 1 Then Factorial = N * Factorial(N - 1) End Function
Private Sub Command1_Click() Debug.Print Factorial(3) End Sub Что самое удивительное - функция работает! Несмотря на то, что в программе нигде не употребляется оператор цикла. Вся соль программы в том, что функция Factorial вместо этого включает в себя вызов самой себя - Factorial(N-1). : Что же происходит в компьютере во время выполнения программы? Механизм происходящего в точности соответствует нашему путешествию по ступенькам:
Все начинается с того, что мы щелкаем по кнопке и Visual Basic пробует выполнить строку Debug.Print Factorial(3). Для этого он вызывает функцию Factorial. Выполнение подпрограммы начинается с того, что в памяти отводится место для всех параметров и локальных переменных, а значит и для нашего параметра N. Затем число 3 подставляется на место параметра N, то есть в память в ячейку N посылается 3. Затем выполняется тело функции. Так как 3>1, то Visual Basic пытается выполнить умножение 3* Factorial(3-1) и сталкивается с необходимостью знать значение функции Factorial(2), для чего вызывает ее, то есть отправляется ее выполнять, недовыполнив Factorial(3), но предварительно запомнив, куда возвращаться.
Спускаюсь на ступеньку ниже. В соседнем месте памяти отводится место для N. Это уже другое N, путать их нельзя! В эту ячейку N посылается 2. Затем выполняется тело функции. Пусть вас не смущает, что Visual Basic второй раз выполняет тело функции, не закончив его выполнять в первый раз. Так как 2>1, то Visual Basic пытается выполнить умножение 2* Factorial(2-1) и сталкивается с необходимостью знать значение функции Factorial(1), для чего вызывает ее.
Спускаюсь еще на ступеньку. В соседнем месте памяти отводится место еще для одного N. В эту ячейку N посылается 1. Затем выполняется тело функции. Так как 1=1, то Visual Basic вычисляет Factorial=1. Вот - впервые конкретное число. Затем Visual Basic пытается выполнить следующую строку if N>1 then Factorial = N* Factorial(N-1). Поскольку нельзя сказать, что 1>1, то строка не выполняется и выполнение тела функции закончено. Значит можно подниматься.
Поднимаюсь на одну ступеньку. Visual Basic возвращается внутрь тела функции (той, где N=2) и успешно выполняет умножение - Factorial =2*1=2.
Поднимаюсь еще на ступеньку. Visual Basic возвращается внутрь тела функции (той, где N=3) и успешно выполняет умножение - Factorial =3*2=6. Задача решена.
Итак, рекурсией в программировании называется вызов подпрограммы из тела самой подпрограммы.
Чем хорош рекурсивный стиль программирования? В нашей программе о факториале мы как бы и не программировали вовсе, а просто обяснили компьютеру, что такое факториал. Как бы перешли на новый уровень общения с компьютером: вместо программирования - постановка задачи. Чем плох рекурсивный стиль программирования? Если мы для решения той же задачи напишем программу не с рекурсией, а с обычным циклом, то такая программа будет выполняться быстрее и потребует меньше памяти.
Задание 131: Напишите рекурсивную функцию fib для вычисления чисел Фибоначчи. Сортировка Здесь вы не узнаете ничего нового о Visual Basic. Будем совершенствовать технику программирования.
Пусть имеется ряд чисел: 8 2 5 4. Под сортировкой понимают их упорядочивание по возрастанию (2 4 5 8) или убыванию (8 5 4 2). Сортировать можно и строки (как слова в словаре). Сортировка - очень распространенная вещь в самых разных программах, в частности - в системах управления базами данных.
Задача: Задан массив из 100 произвольных положительных чисел. Отсортировать его по возрастанию. Идея решения: Если мы не можем сходу запрограммировать задачу, нужно подробно представить себе, в каком порядке мы решали бы ее вручную, без компьютера. Как бы мы сами сортировали 100 чисел? Мы бы запаслись пустым листом бумаги из 100 клеток. Затем нашли бы в исходном массиве максимальное число и записали его в самую правую клетку, а в исходном массиве на его месте записали бы число, меньшее самого маленького в массиве (в нашем случае подойдет 0). Затем нашли бы в изменившемся исходном массиве новое максимальное число и записали его на второе справа место, а на его место в исходном массиве - 0. И так далее. Вот программа для 10 чисел: Const N = 10 'N - размер массива Dim massiv_ishodn(1 To N) As Integer 'Это исходный массив Dim massiv_rezult(1 To N) As Integer 'Это наш пустой лист бумаги
'Вспомогательная функция для поиска максимума в массиве m(1 To N). Она выдает значение 'максимального элемента (maximum) и заодно номер этого элемента (Nomer_max): Private Function maximum(m, N As Integer, Nomer_max As Integer) As Integer Dim i As Integer, max As Integer max = m(1): Nomer_max = 1 'max - "временный" максимум For i = 2 To N If max < m(i) Then max = m(i) Nomer_max = i End If maximum = max Next End Function
'Основная процедура сортировки исходного вектора mass_ish размера N в результирующий - mass_rez: Private Sub sortirovka(mass_ish, N As Integer, mass_rez) Dim Nom_max As Integer For i = 1 To N mass_rez(N + 1 - i) = maximum(mass_ish, N, Nom_max) 'Пишем "в правую клетку" mass_ish(Nom_max) = 0 'Ноль - на старое место Next End Sub
Private Sub Command1_Click() massiv_ishodn(1) = 41 'Задаем значения элементов исходного массива
massiv_ishodn(2) = 8 massiv_ishodn(3) = 17 massiv_ishodn(4) = 82 massiv_ishodn(5) = 20 massiv_ishodn(6) = 2 massiv_ishodn(7) = 30 massiv_ishodn(8) = 12 massiv_ishodn(9) = 6 massiv_ishodn(10) = 9
sortirovka massiv_ishodn, N, massiv_rezult 'Сортируем массив
For i = 1 To N Debug.Print massiv_rezult(i); 'Распечатываем отсортированный массив Next End Sub
Функция maximum, кроме того, что сама имеет значение максимального элемента массива, выдает еще порядковый номер максимального элемента - Nomer_max. Это называется побочным эффектом функции.
Методов сортировки много. Приведенный метод - самый примитивный. Мало того, что нам пришлось расходовать память на второй массив, для выполнения сортировки массива из 100 элементов понадобилось бы около 100*100=10000 операций сравнения элементов массива между собой. Существуют методы гораздо более эффективные. Приведу один из них - метод пузырька. Представьте себе тонкую вертикальную трубку с водой. Запустим снизу пузырек воздуха. Он поднимется до самого верха и остановится. Затем пустим еще один. Он поднимется наверх и остановится сразу же под первым. Затем запустим третий и так далее все сто пузырьков. А теперь представим, что это не трубка, а наш исходный массив, а вместо пузырьков поднимаются максимальные элементы. Вот алгоритм: Сравним первый элемент массива со вторым, и если второй больше, то ничего не делаем, а если первый больше, то меняем местами первый и второй элементы. В этом вся соль метода. Затем повторяем это со вторым и третьим элементами - если третий больше, то ничего не делаем, а если второй больше, то меняем местами второй и третий элементы. Затем повторяем все это с третьим и четвертым элементами и так далее. Где-то по пути мы встретим максимальный элемент, и он, как пузырек, поднимется у нас до самого верха. Теперь, когда мы знаем, что элемент номер 100 у нас самый большой, нам предстоит решить задачу сортировки для массива из остальных 99 элементов. Метод тот же. Запускаем второй пузырек и так далее. Метод пузырька не требует второго массива, да и сравнений здесь в два раза меньше. Вот программа: Const N = 10 'N - размер массива Dim massiv(1 To N) As Integer 'Это массив
'Сортировка массива mass размером Razmer: Private Sub puziryok(mass, Razmer As Integer) Dim i As Integer For m = Razmer To 2 Step -1 'Всего пузырьков - 9 For i = 1 To m - 1 'i увеличивается - пузырек ползет вверх If mass(i) > mass(i + 1) Then 'Стоит ли обмениваться значениями c = mass(i) 'Три оператора для обмена значений двух элементов с помощью mass(i) = mass(i + 1) 'транзитного элемента c mass(i + 1) = c End If Next i Next m End Sub
Private Sub Command1_Click() massiv(1) = 41 'Задаем значения элементов массива massiv(2) = 8 massiv(3) = 17 massiv(4) = 82 massiv(5) = 20 massiv(6) = 2 massiv(7) = 30 massiv(8) = 12 massiv(9) = 6 massiv(10) = 9
puziryok massiv, N 'Сортируем массив
For i = 1 To N Debug.Print massiv(i); 'Распечатываем отсортированный массив Next End Sub В заключение скажу, что существуют методы гораздо более эффективные, чем метод пузырька. Задание 132: Отсортируйте по возрастанию двумерный массив. Я имею в виду - нужно сделать так, чтобы: а(1,1) <= a(1,2) <=... <= a(1,N) <= <= a(2,1) <= a(2,2) <=... <= a(2,N) <= <= a(3,1) <= a(3,2) <=...
|
||||||||
Последнее изменение этой страницы: 2016-08-12; просмотров: 212; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.17.156.114 (0.012 с.) |