Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатика
ИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханика
ОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторика
СоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансы
ХимияЧерчениеЭкологияЭкономикаЭлектроника

ЧАСТЬ 2. Выделение функций

Читайте также:
  1. C) В легком, потому что наибольшая часть тени расположена в легочном поле
  2. DO Часть I. Моделирование образовательной среды
  3. II Основная часть
  4. II часть.
  5. II. Описание трудовых функций, входящих в профессиональный стандарт
  6. Анализ как часть процесса управления
  7. Аналитическая часть.

Запустите проект. У вас должны быть выполнены абсолютно все задания.

Откройте программный код окна. Нам предстоит проанализи­ровать содержимое метода-обработчика button1_Click. Это достаточно длинный текст. Но он правильный, обеспечивает удобную работу пользователя - и в этом смысле (от пользователя) никаких претензий к программисту нет. А вот у программиста к себе самому - есть.

Когда «сплошной» программный текст достаточно большой, то он становится трудно понимаемым. Особенно со временем - чем больше проходит времени с момента его написания, тем меньше остается в памяти. Текст не должен быть очень большим. Текст можно уменьшить, если разбить его на отдельные подпро­граммы (маленькие программы), дать этим подпрограммам имена и обращаться к ним, когда надо, с помощью всего одной команды.

В C# такие подпрограммы, выделенные программистом, называ­ются функциями (или методами).

Попробуем перестроить текст обработчика, выделив из него отдельные фрагменты как функции. Вынесем в отдельную функ­цию следующую группу:

try

{ a = Convert.ToDouble(textBox1.Text);

b = Convert.ToDouble(textBox2.Text);

c = Convert.ToDouble(textBox3.Text);

}

catch

{ MessageBox.Show("проверьте исходные данные"); return;

}

Смысл группы тоже понятен: преобразование исходных строковых данных в численные значения. Назовем эту функцию Преобразование. Однако, простого вынесения операторов будет недостаточно. Дело в том, что результат работы этого блока двоякий. Может быть нор­мальное завершение, когда все данные - численные. Но возможен и второй вариант - если выработается исключение. Следовательно, надо предусмотреть оба варианта завершения функции. Как?

Например, так. Пусть функция при нормальном завершении выработает значение «истина», а при втором варианте - значение «ложь». В обработчике мы вызовем эту функцию, а после её за­вершения проверим, что она выработала (говорят, вернула). Сле­довательно, функция будет возвращать значение типа bool, т. е. тип функции будет уже не void, а bool. Запишем проект нашей функции сразу перед обработчиком в таком виде:

private bool Преобразование()

{ try

{ a = Convert.ToDouble(textBox1.Text);

b = Convert.ToDouble(textBox2.Text);

c = Convert.ToDouble(textBox3.Text);

}

catch

{ MessageBox.Show("проверьте исходные данные"); return;

}

}

Все вынесенные команды удалим из обработчика, а вместо них за­пишем такой оператор:

if (Преобразование() == false) return;

Смысл этого оператора таков: если в результате работы функции вернулось значение «ложь», то это значит, что в данных есть ошибка и надо завершить работу обработчика оператором return (возврат). Попробуем запустить программу. Увы, мы получим не­сколько ошибок (рис. 19). Три первых ошибки имеют одну и ту же природу. Текст пояснения к ошибке говорит о том, что перемен­ные не определены внутри функции Преобразование.

Рис. 19. Окно ошибок

В самом деле, эти переменные объявлены внутри обработчика. Мы же теперь так построили работу, что значения в эти переменные должны сформироваться внутри другой функции (Преобразование), и эти значения должны быть переданы из неё в обработчик. Сформированные значения - это выход функции Преобразование. В этом случае надо использовать выходные параметры. Исправим заголовок функции и укажем список из трех выходных параметров:

private bool Преобразованием double a, out double b, out double c) Но раз изменился заголовок, то надо изменить и оператор вызова:

if (Преобразование(out a, out b, out c) == false) return;

Теперь мы можем быть уверены, что если значения сформируются в функции Преобразование, то они будут переданы в переменные a, b, и c в обработчик.

Вновь попробуем запустить программу. И снова ошибка, зато какая интересная! Обратите внимание: под подозрение компилятора попала теперь уже вся функция. В сообщении об ошибке говорится, что не все варианты исполнения функции завершаются возвратом значения. Верно, имеется два варианта. Один вариант, когда пре­образование не выполнено, мы завершим оператором return false; А другой вариант, когда всё нормально? Добавим и туда оператор возврата, но уже вернём «истину» (показан фрагмент):

try

{ a = Convert.ToDouble(textBoxl.Text);

b = Convert.ToDouble(textBox2.Text);

c = Convert.ToDouble(textBox3.Text); return true;

}

 

Снова выполним компиляцию и получим уже три ошибки, имею­щих одинаковую природу. Выходные параметры должны ОБЯЗА­ТЕЛЬНО получать какие-то значения. А если будет выработано исключение? Компилятор это «заметил». Давайте для успокоения души компилятора присвоим переменным какие-либо значения. Например, нулевые, в самом начале функции (показан фрагмент): private bool Преобразованием double a, out double b, out double c)

{ a = 0; b = 0; c = 0;

try

Исправим и вновь запустим программу. Теперь всё в порядке!

Следующий большой фрагмент текста (при a==0):

if (b==0)

{label5.Text = "решения нет"; label8.Text= "";}

else

{ x1 = (-c) /b; label8.Text=string.Format("{0,10:##.##}",x1);

label5.Text = "один корень";

}

label9.Visible = false; label6.Visible = false; label11.Visible = false; label10.Visible = false; label7.Visible = false;

Поступим мудрее, чем в прошлый раз: сначала проанализируем, а уж потом будем выносить код в функцию. Итак, что тут делается? Вычисляется x1. Значит, это будет выходной параметр. На основа­нии чего вычисляется? На основании b и c. Значит, эти значения должны быть переданы в новую функцию. Следовательно, будет три параметра: два обычных (значения) и один выходной (out). Возвращать функция ничего не будет. Значит, тип функции void. Назовём функцию Линейное. Итак:

private void Линейное(double b, double c, out double x1)

{ if (b==0)

{ label5.Text = "решения нет "; label8.Text= "";}

else

{ x1 = (-c) /b; label8.Text=string.Format("{0,10:##.##}",x1);

label5.Text = "один корень";

}

label9.Visible = false; label6.Visible = false;

label11.Visible = false; label10.Visible = false;

label7. Visible = false;

}

Вместо вынесенного текста - один оператор:

Линейное (b, c, out xl);

Запускаем программу. Опять работает!

Ну, а теперь вынесем в отдельную функцию всю логику реше­ния квадратного уравнения, т. е. весь текст из ветви else. Начинаем рассуждать. Очевидно, что в данном алгоритме используются для вычисления все коэффициенты. Это будут параметры-значения. Далее, формируются результаты xl и x2 - это будут выходные па­раметры. Функция всё вычисляет и «рассовывает» по объектам label, то есть ей просто нечего возвращать - значит, тип void. При­своим ей имя - Квадратное. Итак, заголовок: private void Квадратное(double a, double b, double c, out double xl,

out double x2)

Соответственно, вызов функции:

Квадратное(a, b, c, out xl, out x2);

Запускаем! Восемь ошибок! Но... всё это уже мелочь. Первые семь ошибок связаны с переменной d. Правильно, она же в новой функции не объявлена. Объявляем в самом начале функции:

double d;

А восьмая ошибка... и не ошибка вовсе - это предупреждение. Кликнем по тексту ошибки дважды и увидим, что компилятор «придрался» к объявлению этой переменной в обработчике. В са­мом деле, переменная объявлена, но нигде не используется. Так давайте её удалим.

Запускаем! И вновь видим: не по всем веткам алгоритма вы­ходные переменные получают значения (а должны). Дадим им в самом начале нулевые значения (фрагмент):

double d;

xl = 0; x2 = 0;

d = b * b - 4 * a * c;

И вновь запускаем программу. Наконец-то всё.

Так чего же ради мы мучались? А посмотрите на метод-обра­ботчик: он совсем крохотный стал. И понятный. Правда, функций стало больше, но опять-таки каждая - небольшая и понятная. Ну, можно было бы еще разделить на части функцию Квадратное... А почему бы и нет!?


Дата добавления: 2015-08-09; просмотров: 111 | Нарушение авторских прав


Читайте в этой же книге: Начало работы | Имя и место размещения приложения | Набор текста программы | Создание Windows-приложения | Организация класса Form1 | События, связанные с окном | Решение проблемы ввода данных | Доработка и устранение ошибок ввода | Типовые алгоритмы обработки массива | Задание для самостоятельного выполнения |
<== предыдущая страница | следующая страница ==>
ЧАСТЬ 1. Разработка алгоритма программы| Разработка некоторых элементов класса данных

mybiblioteka.su - 2015-2024 год. (0.017 сек.)