Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Понятно о Visual Basic.NET. Самоучитель.Ч2.2005...docx
Скачиваний:
46
Добавлен:
25.11.2019
Размер:
4.02 Mб
Скачать
      1. Из чего состоит тело процедуры. Выражения

Тело процедуры состоит из операторов Dim и остальных операторов. Остальные операторы выполняются по порядку.

Из чего состоят операторы? Они могут включать в себя блоки других операторов, как это делают, например, операторы If и Do. Они могут включать в себя выражения.

Мы знаем с вами уже три вида выражений: арифметические (их значение – число), строковые (их значение – текстовая строка) и логические (они принимают одно из двух значений: True или False).

Выражение, стоящее отдельно, само по себе, встречаться не может. Выражения всегда являются частью операторов. Выражения мы встречаем справа (не слева!) от знака равенства в операторе присваивания, в условиях тех же операторов If и Do, внутри скобок при обращении к методам и функциям.

В простейшем случае выражение – это литерал:

Фрагмент

Где тут выражения

a = 0

0

b = -7

-7

s = "Привет"

"Привет"

В простом случае выражение – это переменная:

a = c

c

w = s

s – строковое выражение

В обычном случае выражение – это литералы и переменные, соединенные знаками арифметических и других операций. В выражения входят скобки, а также математические и другие функции:

d = a + 1

Здесь три выражения: a, 1 и a+1

w = s & "ик"

Здесь три выражения: s, "ик" и s & "ик"

Debug.WriteLine(b - 3)

Здесь три выражения: b, 3 и b-3

b = Len(w)

Здесь два выражения: w и Len(w)

b = a * (Len(w) – Rnd())

Выражение a * (Len(w) – Rnd()) и в нем 5 выражений

If c + 9 > a Then

Логическое выражение c+9>a, состоящее из двух арифметических

      1. Функции

Философия. Мы с вами уже сталкивались со стандартными функциями (например, Len(w), Abs(c+200) и др.). Стандартная функция – это некая скрытая программа, которая принимает свои параметры, указанные в скобках, в качестве исходных данных (аргументов), что-то делает с ними и в результате получает одну величину, которая и является значением функции. Много примеров функций вы найдете в Error: Reference source not found и по всей книге.

Когда мы видим оператор

b = a * (Len(w) – Abs(c+200))

то говорим, что при выполнении этого оператора компьютер обращается к функциям Len и Abs. А само упоминание этих функций в тексте оператора называем обращениями к этим функциям, чтобы отличить их от объявлений функций, которые являются солидными программами для вычисления значений этих функций, только скрытыми от нас. Здесь полная аналогия с обращением к процедуре пользователя. Обращение к процедуре – это коротенький оператор, а объявление процедуры может состоять из многих строк.

Обратите внимание, что обращения к стандартным функциям встречаются обычно в выражениях. Редко кто пишет отдельные операторы такого вида:

Len(w)

Abs(c + 20)

Да это и понятно. Ведь в этом случае неизвестно, как использовать вычисленную величину функции. Действительно, ну вот мы вычислили длину строки, а куда ее девать, как приспособить для какого-нибудь дела? Поэтому пишут так:

b = Len(w)

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

Debug.WriteLine(Abs(c + 20))

Здесь тоже от абсолютной величины польза была: мы ее напечатали.

Сейчас я хочу, чтобы мы подошли к осознанию необходимости и удобства обладания собственными функциями – функциями пользователя. Функции пользователя вы создаете тогда, когда вам недостаточно функций из библиотеки классов .NET Framework. Например, вы хотите иметь функцию, аргументами которой были бы длины двух сторон прямоугольника, а значением – периметр этого прямоугольника. Но позвольте! – скажете вы – Мы только что создали процедуру, которая делает именно это, да еще и площадь вычисляет! Зачем нам нужна еще какая-то функция? А затем, что функция в данном случае удобнее и естественнее в использовании. Вы увидите, что удобнее создать и использовать две функции: Периметр и Площадь, чем одну процедуру. И не забывайте, кстати, что единую функцию Периметр_Площадь создать нельзя, так как функция может иметь только одно значение.

Пример 1. Вспомним задачу из 11.4.1: «Известны стороны двух прямоугольников. Нужно напечатать периметр того прямоугольника, чья площадь больше.» Приведу целиком программу решения этой задачи, но уже с использованием не процедуры, как в 11.4.1, а функций:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Dim A1, B1 As Integer 'Две стороны 1 прямоугольника

Dim A2, B2 As Integer 'Две стороны 2 прямоугольника

A1 = 10 : B1 = 50

A2 = 20 : B2 = 30

If Площадь(A1, B1) > Площадь(A2, B2) Then WriteLine(Периметр(A1, B1)) _

Else WriteLine(Периметр(A2, B2))

End Sub

Function Периметр(ByVal Сторона1 As Integer, ByVal Сторона2 As Integer) As Integer

Return 2 * Сторона1 + 2 * Сторона2

End Function

Function Площадь(ByVal Сторона1 As Integer, ByVal Сторона2 As Integer) As Integer

Площадь = Сторона1 * Сторона2

End Function

Пояснения. Оператор

If Площадь(A1, B1) > Площадь(A2, B2) Then WriteLine(Периметр(A1, B1)) _

Else WriteLine(Периметр(A2, B2))

содержит в себе два обращения к функции Площадь и два обращения к функции Периметр. Он хорош своей естественностью и понятностью. Действительно, он практически повторяет условие задачи:

«ЕСЛИ площадь первого прямоугольника больше площади второго,

ТО печатай периметр первого прямоугольника,

ИНАЧЕ печатай периметр второго».

Терминология. Как же устроены наши функции? Сначала о терминологии, которая очень похожа на терминологию процедур.

Все операторы, из которых состоит функция, без заголовка и конечной строки, будем называть телом функции. А вместе с этими строками – объявлением функции. Как видите, тела наших функций очень коротенькие, всего из одного оператора. Но операторов может быть сколько угодно, как и в процедуре.

Когда VB в процессе выполнения программы натыкается на функцию Периметр, он ищет в программе объявление функции с именем Периметр и начинает выполнять тело этой функции. Этот процесс называется вызовом функции или обращением к функции . Говорят также, что управление передается функции. После выполнения тела функции VB возвращается к выполнению программы. Говорят, что управление возвращается к программе. Про значение функции говорят, что функция возвращает это значение в программу.

Отличия функций от процедур. Вы видите, что объявление функции очень похоже на объявление процедуры. Но функция в отличие от процедуры обладает некоторыми свойствами переменной величины. Объявление функции отличается от объявления процедуры следующими элементами:

  • В заголовке функции мы пишем не Sub (процедура), а Function (функция)

  • В заголовке функции после скобок с параметрами должен быть указан тип значения функции (так как у нас это численное значение имеет смысл площади или периметра, то я выбрал в обоих случаях Integer).

  • Внутри тела функции ей хотя бы раз должно быть присвоено какое-нибудь значение. Именно это значение функция и будет возвращать. Присвоение можно делать двумя способами:

  • Обычным оператором присваивания, в котором слева от знака равенства стоит имя функции, как если бы это была не функция, а обычная переменная (у нас этим занимается оператор Площадь = Сторона1 * Сторона2).

  • При помощи специального оператора Return (у нас этим занимается оператор Return 2 * Сторона1 + 2 * Сторона2).

  • В конечной строке мы пишем не End Sub (конец процедуры), а End Function (конец функции)

Напомню еще раз, что обращение к функции отличается от обращения к процедуре. Если обращение к процедуре – самостоятельный оператор, то обращение к функции – это обычно составная часть выражения.

Пример 2. Рассмотрим другой пример функции. Ее параметр (аргумент) – строка. Значение функции – та же строка, повторенная столько раз, сколько символов (букв) в исходной строке. Например, если параметр – «уж», то функция – «ужуж», параметр – «Вена», функция – «ВенаВенаВенаВена». Если длина параметра превышает 8 символов, значение функции таково – «Вы задали слишком длинное слово».

Вот программа:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Dim S As String

S = TextBox1.Text

TextBox1.Text = Размноженное_слово(S)

End Sub

Function Размноженное_слово(ByVal Slovo As String) As String

Dim i, Длина_слова As Integer

Длина_слова = Len(Slovo)

If Длина_слова > 8 Then

Return "Вы задали слишком длинное слово"

Else

Размноженное_слово = ""

For i = 1 To Длина_слова

Размноженное_слово = Размноженное_слово & Slovo

Next

End If

End Function

Пояснения. Здесь мы пишем в текстовом поле слово и щелчком по кнопке тут же получаем в том же текстовом поле результат – размноженное слово.

Посмотрим на объявление функции. В заголовке мы видим, что как параметр функции, так и сама функция имеют тип String. Процедуры и функции, как вы уже видели, могут содержать кроме параметров также и обычные локальные переменные (в нашем случае это i и Длина_слова). Тело функции состоит из нескольких операторов.

Механика работы этой функции проста. Переменная Размноженное_слово накапливает в себе слова, как сумматор сумму. Роль плюса играет знак &. На каждой итерации второй из двух операторов присваивания удлиняет Размноженное_слово на Slovo. А итераций столько, сколько букв в слове. «Обнуляет сумматор» оператор

Размноженное_слово = ""

Роль нуля исполняет пустая строка "" длиной в 0 символов.

Для возврата значений применяется в одном месте оператор Return и в двух местах – оператор присваивания Размноженное_слово = . . .. Не запутаемся ли? – Значение одно, операторов – три. Спрашивается, какой из этих операторов в действительности вернет значение? Чтобы ответить на этот вопрос, вам нужно знать, что

между операторами Return и присваивания, используемыми для возврата значения функции, имеется существенное различие. А именно: наткнувшись на оператор Return, компьютер выполняет его и на этом немедленно прекращает выполнение функции, возвращаясь в программу, ее вызвавшую. Ничего подобного при выполнении оператора присваивания не происходит – компьютер продолжает выполнять тело функции дальше.

Если вы внимательно разберете текст этой или любой другой функции, то увидите, что вернет значение оператор, последний по времени выполнения (а не в порядке записи). Какой именно? Все зависит от длины слова. Если оно длиннее 8 букв, то значение вернет оператор Return. Если его длина – от 1 до 8 букв, то второй из двух операторов присваивания. Если вы ничего не введете в текстовое поле, то – первый.

Обязательно прогоните программу в пошаговом режиме. Вам будет любопытно наблюдать, как постепенно удлиняется Размноженное_слово.

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

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Dim A1, B1, П1 As Integer 'Две стороны и периметр 1 прямоугольника

Dim A2, B2, П2 As Integer 'Две стороны и периметр 2 прямоугольника

A1 = 10 : B1 = 50

A2 = 20 : B2 = 30

If Площадь(A1, B1, П1) > Площадь(A2, B2, П2) Then WriteLine(П1) Else WriteLine(П2)

End Sub

Function Площадь(ByVal Сторона1 As Integer, ByVal Сторона2 As Integer, ByRef Периметр As Integer) _

As Integer

Площадь = Сторона1 * Сторона2

Периметр = 2 * Сторона1 + 2 * Сторона2

End Function

Что мы выиграли и что проиграли? Сэкономили две строчки кода, но пришлось вводить дополнительные переменные и параметр. А самое главное – проиграли в простоте, единообразии и понятности. Функция получилась довольно нелепая.

Если функция кроме возвращаемого значения вычисляет что-то еще побочное, что мы используем в программе, то говорят, что функция имеет побочный эффект. Побочные эффекты довольно часто используются в программировании. Например, среди функций из библиотеки классов .NET Framework довольно много таких, возвращаемое значение которых никого не интересует, а интересует именно побочный эффект. Поэтому обращение к функции разрешено писать не только в выражениях, но и отдельным оператором. Например, так:

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

Dim A1, B1, П1 As Integer 'Две стороны и периметр прямоугольника

A1 = 10 : B1 = 50

Площадь(A1, B1, П1)

Debug.WriteLine(П1)

Math.Abs(-20)

End Sub

Как я уже упоминал, от площади в этом примере толк есть, а от абсолютной величины – нет.

Напишите функцию с двумя строковыми параметрами. Функция должна выдать длину той строки, которая короче.