Передача параметров по значению и по ссылке



 

Когда параметры передаются в метод обычным образом (без до-полнительных ключевых слов ref и out), любые изменения параметров внутри метода не влияют на его значение в основной программе. Пред-положим, у нас есть следующий метод:

 

private void Calc(int Number)

 

{

Number = 10;

}

 

Видно, что внутри метода происходит изменение переменной

Number, которая была передана как параметр. Попробуем вызвать метод:

 

int n = 1;

 

Calc(n);

MessageBox.Show(n.ToString());

 

На экране появится число 1, то есть, несмотря на изменение пере-менной в методе Calc, значение переменной в главной программе не изменилось. Это связано с тем, что при вызове метода создается копия переданной переменной, именно ее изменяет метод. При завершении метода значение копий теряется. Такой способ передачи параметра на-зывается передачей по значению.

Чтобы метод мог изменять переданную ему переменную , ее следу-ет передавать с ключевым словом ref – оно должно быть как в сигнату-ре метода, так и при вызове:

 

private void Calc(ref int Number)

 

{

Number = 10;

}

 

int n = 1;

 

Calc(ref n);

MessageBox.Show(n.ToString());

 

В этом случае на экране появится число 10: изменение значения

в методе сказалось и на главной программе. Такая передача метода на-зывается передачей по ссылке, т. е. передается уже не копия, а ссылка на реальную переменную в памяти.

Если метод использует переменные по ссылке только для возврата значений и не имеет значения, что в них было изначально, то можно не


 

92


 

инициализировать такие переменные, а передавать их с ключевым сло-вом out. Компилятор понимает, что начальное значение переменной не важно, и не ругается на отсутствие инициализации:

 

private void Calc(out int Number)

 

{

Number = 10;

}

 

int n; // Ничего не присваиваем!

 

Calc(out n);

 

Индивидуальное задание

 

1. Написать метод min(x, y), находящий минимальное значение из двух чисел. С его помощью найти минимальное значение из четырех чисел a, b, c, d.

 

2. Написать метод max(x, y), находящий максимальное значение из двух чисел. С его помощью найти максимальное значение из четырех чисел a, b, c, d.

3. Написать метод, вычисляющий значение n/x n. С его помощью вычислить выражение:

10 i

.

 

4. Написать метод, вычисляющий значение n/x n. С его помощью вычислить выражение:

10 i

.

 

5. Написать метод, вычисляющий значение x n/(n+x). С его помо-щью вычислить выражение:

10  x i

åi=1 x + i .

6. Написать метод, вычисляющий значение sin(x) + cos(2 * x).

С его помощью определить, в какой из точек a, b или с значение будет минимальным.

7. Написать метод, вычисляющий значение x2 + y2. С его помо-щью определить, с какой парой чисел (a, b) или (с, d) значение будет максимальным.

 

8. Написать метод, вычисляющий значение x2 * y3 * √ . С его по-мощью определить, с какой тройкой чисел (a, b, c) или (d, e, f) значение будет максимальным.


 

93


 

9. Написать метод, который у четных чисел меняет знак, а нечет-ные числа оставляет без изменения. С его помощью обработать ряд чи-сел от 1 до 10.

10. Написать метод, который положительные числа возводит

 

в квадрат, а отрицательные – в куб. С его помощью обработать ряд чи-сел от –10 до 10.

11. Написать метод, который вычисляет значения x = sin2(a)

и y = cos2(a). Напечатать таблицу значений от –π до π с шагом π/4.

 

12. Написать метод, который вычисляет значения x = a2 и y = √ . Напечатать таблицу значений от –10 до 10 с шагом 1.

13. Написать метод, который в переданной строке заменяет все точки на многоточие. С его помощью обработать пять разных строк

и отобразить их на экране.

14. Написать метод, который в переданной строке заменяет все строчные буквы на заглавные, и наоборот. С его помощью обработать пять разных строк и отобразить их на экране.

15. Написать метод, который разделяет переданную строку на две отдельных строки: первая содержит исходную строку до первой точки, а вторая – исходную строку после первой точки. С его помощью обра-ботать пять разных строк и отобразить результаты на экране.

 

16. Написать метод, который подсчитывает количество знаков препинания в переданной строке. С его помощью обработать пять раз-ных строк и отобразить результаты на экране.

17. Написать метод, который находит сумму чисел в переданной строке. Числом считается непрерывная последовательность цифр, отде-ленная от остального текста пробелами или расположенная в начале ли-бо конце строки. Допустимо использовать метод Split класса String. С помощью этого метода обработать пять разных строк и отобразить ре-зультаты на экране.

18. Написать метод, определяющий, является ли переданная строка палиндромом, то есть текстом, который слева направо и справа налево читается одинаково без учета пробелов и регистра символов. С помо-щью этого метода обработать пять разных строк и отобразить результа-ты на экране.

 

19. Написать метод, находящий сумму матриц одинакового разме-ра и возвращающий новую матрицу. С помощью этого метода обрабо-тать пары матриц и отобразить результаты на экране.

20. Написать метод, находящий сумму элементов, находящихся не на главной диагонали переданной матрицы. С помощью этого метода обработать пары матриц и отобразить результаты на экране.


 

 

94


 

 

ЛАБОРАТОРНАЯ РАБОТА № 14.

 

РЕКУРСИЯ

 

Цель лабораторной работы : изучить рекурсивные методы,напи-сать программу с использованием рекурсии.

 

Общие понятия

 

Рекурсивным называют метод,если он вызывает сам себя в качествевспомогательного. В основе рекурсивного метода лежит так называемое рекурсивное определение какого-либо понятия.Классическим примеромрекурсивного метода является метод, вычисляющий факториал.

 

Из курса математики известно, что 0! = 1! = 1, n! = 1*2*3…*n.

С другой стороны n! = (n – 1)!*n. Таким образом, известны два частных случая параметра n, а именно n = 0 и n = 1, при которых мы без каких-либо дополнительных вычислений можем определить значение факто-риала. Во всех остальных случаях, то есть для n > 1, значение факториа-ла может быть вычислено через значение факториала для параметра n

1. Таким образом, рекурсивный метод будет иметь вид:

 

long F(int n)

 

{

// Дошли до 0 или 1? if (n == 0 || n == 1)

// Нерекурсивная ветвь return 1;

else

// Шаг рекурсии: повторный вызов

// метода с другим параметром return n * F(n ‐ 1);

 

}

 

// Пример вызова рекурсивного метода long f = F(3); MessageBox.Show(f.ToString());

 

Рассмотрим работу описанного выше рекурсивного метода для n = 3. Первый вызов метода осуществляется из основной программы,

в нашем случае командой f = F(3). Этап вхождения в рекурсию обо-значим стрелками с подписью «шаг». Он продолжается до тех пор, пока значение переменной n не становится равным 1. После этого начинается


 

95


 

выход из рекурсии (стрелки с подписью «возврат»). В результате вы-числений получается, что F(3) = 3 * 2 * 1.

 

 

Рис. 14.1. Структура рекурсивных вызовов

 

Рассмотренный вид рекурсии называют прямой. Метод с прямой рекурсией обычно содержит следующую структуру:

 

if (<условие>)

 

<оператор>;

 

else

<вызов этого же метода с другими параметрами>;

 

В качестве <условия> обычно записываются некоторые граничные случаи параметров, передаваемых рекурсивному методу, при которых результат его работы заранее известен, поэтому далее следует простой оператор или блок, а в ветви else происходит рекурсивный вызов дан-ного метода с другими параметрами.

Что необходимо знать для реализации рекурсивного процесса? Со входом в рекурсию осуществляется вызов метода, а для выхода не-обходимо помнить точку возврата, т. е. то место программы, откуда мы пришли и куда нам нужно будет возвратиться после завершения метода. Место хранения точек возврата называется стеком вызовов, и для него выделяется определенная область оперативной памяти. В этом стеке за-поминаются не только адреса точек возврата, но и копии значений всех параметров. По этим копиям восстанавливается при возврате вызываю-щий метод. При развертывании рекурсии за счет создания копий пара-


 

96


 

метров возможно переполнение стека. Это является основным недос-татком рекурсивного метода. С другой стороны, рекурсивные методы позволяют перейти к более компактной записи алгоритма.

Следует понимать, что любой рекурсивный метод можно преобра-зовать в обычный метод с использованием циклов. И практически лю-бой метод можно преобразовать в рекурсивный, если выявить рекур-рентное соотношение между вычисляемыми в методе значениями.

 

Рассмотрим пример кода для создания набора самоподобных структур.В нашем случае это будет набор увеличивающихся квадра-тов (рис. 14.2).

 

 

Рис. 14.2. Набор квадратов

 

При проектировании данной программы были созданы два метода:

 

private void MyDraw(Graphics g, int N, int x, int y)

 

{

if (N == 0)

return;

 

else

{

// Отрисовка прямоугольника g.DrawRectangle(new Pen(Brushes.Blue, 2),

 

0, 0, x, y);

// Увеличение x и y на 50

 

x += 50;

y += 50;

N‐‐;

// Рекурсивный вызов с новыми параметрами

MyDraw(g, N, x, y);

}

 

}


 

97


 

private void Form1_Paint(object sender, PaintEventArgs e)

{

Graphics g = e.Graphics;

// Первый вызов метода и вход в рекурсию

MyDraw(g, 7, 50, 50);

}

 

Координаты левого верхнего угла всех прямоугольников неизмен-ны и находятся в точке (0, 0). Поэтому в параметрах метода MyDraw дос-таточно передавать x и y для правого нижнего угла. Также в параметрах передается N, значение которой определяет текущую вложенность ре-курсии (сколько вызовов рекурсии еще будет).

 


Дата добавления: 2020-04-08; просмотров: 568; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!