• Nie Znaleziono Wyników

Własne funkcje i procedury

N/A
N/A
Protected

Academic year: 2021

Share " Własne funkcje i procedury "

Copied!
5
0
0

Pełen tekst

(1)

Zajęcia 4.

Własne funkcje i procedury

Dany jest walec zewnętrzny o promieniu podanym w TextBox ‘txtRz’ i wysokości w TextBox ‘txtHz’. W walcu tym są trzy wydrążenia w kształcie walców o promieniach i wysokościach podanych odpowiednio w obiektach TextBox: ‘txtRw1’, ‘txtHw1’, ‘txtRw2’, ‘txtHw2’, ‘txtRw3’, ‘txtHw3’. Aplikacja służy do obliczania objętości tak powstałej bryły. Procedura obsługi zdarzenia ‘Click’ przycisku

btnObliczObjetoscBryly’ wywołuje dla danych każdego z czterech walców naszą funkcję o nazwie

‘walecObjetosc’, która przyjmuje dwa argumenty typu tekstowego (String) przekazane przez wartość (ByVal).

Pierwszy argument jest interpretowany jako promień walca, drugi jako wysokość. Funkcja zwraca objętość walca jako liczbę rzeczywistą typu (Double). Zwracane w kolejnych wywołaniach funkcji wartości są podstawianie pod zmienne typu (Double), które są następnie wykorzystane do obliczenia objętości bryły.

Aby użyć funkcji należy w obliczanym wyrażeniu podać jej nazwę i w nawiasach okrągłych listę parametrów aktualnych (oddzielonych przecinkami), na których ma przeprowadzić obliczenia. Natomiast by funkcja zwróciła wartość należy użyć wewnątrz jej kodu słowa kluczowego (Return), a po nim należy umieścić wyrażenie, którego wartość ma przyjąć funkcja. Wykonanie tej instrukcji kończy jednocześnie działanie funkcji i następujące po niej instrukcje, o ile takie istnieją, nie zostaną wykonane. Zwrócenie wartości jest też możliwe w stylu Visual Basic 6.0, czyli przez podstawienie wartości pod nazwę funkcji. Jednak takie postępowanie nie kończy działania funkcji, aż do napotkania słowa kluczowego (End Function) kończącego kod funkcji albo (Exit Function), które wymusza wcześniejsze jej zakończenie.

Do funkcji czy procedury można przesłać zmienne przez wartość (ByVal) albo przez referencje (ByRef).

Zadeklarowanie zmiennej powoduje przydzielenie jej w pamięci ciągłego kawałka miejsca o rozmiarze zależnym od typu zmiennej. Na początek tego miejsca wskazuje adres. Dzięki temu adresowi i typowi zmiennej program wie ile

(2)

bitów skąd ma odczytać i jak je zinterpretować. Przekazanie argumentu przez wartość wymusza utworzenie

w osobnej przestrzeni adresowej kopii zmiennej i do tego nowo zarezerwowanego miejsca skopiowanie ciągu bitów z miejsca, gdzie jest przechowywana oryginalna zmienna. Ta nowo utworzona kopia jest dostępna jedynie wewnątrz funkcji czy procedury i wszystkie zmiany jej wartości nie wpływają na wartość zmiennej oryginalnej utworzonej na wyższym poziomie. Natomiast przekazanie argumentu przez referencję jest jednoznaczne z udostępnieniem podprogramowi adresu do zmiennej oryginalnej. Ponieważ w tym przypadku funkcja czy procedura działa

na oryginale, więc wszystkie zmiany wartości zmiennej w podprogramie są widoczne na zewnątrz. Podsumowując, (ByVal) należy użyć, by jedynie przesłać parametr do podprogramu, co jednocześnie zabezpiecza przed przypadkową zmianą wartości zmiennej oryginalnej. Natomiast (ByRef) należy użyć, aby wyprowadzić na zewnątrz wyniki

działania podprogramu.

Konstrukcję (Try - Catch) należy użyć w najbardziej zewnętrznym podprogramie. Wszystkie błędy powstałe w bloku (Try) bez względu na to, czy powstały w instrukcji bezpośrednio tu umieszczonej, czy w instrukcji wewnątrz procedur i funkcji w tym bloku wywoływanych (i na każdym następnym poziomie wywołań) zostaną przechwycone przez (Catch) i mogą tu być obsłużone. Znajomość tego faktu znacznie upraszcza tworzenie skomplikowanych aplikacji, gdyż odpada problem poinformowania procedury nadrzędnej o błędzie zaistniałym w procedurach podrzędnych, z których ta korzysta. W środowisku .NET jest już zdefiniowana cała gama błędów. Istnieje obiekt

‘Err’, który zawiera informacje dotyczące błędów powstałych w czasie wykonywania programu. Właściwość

‘Number’ zawiera numer błędu. Numery od 0 do 512 są zarezerwowane na błędy zdefiniowane w systemie.

Natomiast numery od 513 do 65535 są dostępne dla błędów definiowanych przez programistę. Właściwość

‘Description’ zawiera opis błędu. Właściwość (‘Source’) zawiera ciąg znaków określający nazwę źródła, gdzie błąd został wygenerowany (najczęściej nazwa obiektu lub aplikacji). Obiekt ten posiada również bardzo użyteczną metodę ‘Raise’ umożliwiającą programiście wygenerowanie błędu, który można obsłużyć jak samo, jak błędy zdefiniowane w systemie. Pierwszym i jedynym obowiązkowym argumentem tej metody jest liczba całkowita od 0 do 65535, która określa numer błędu (ustawienie właściwości ‘Err.Number’). Wszystkie pozostałe argumenty są opcjonalne. Dlatego aby wygenerować błąd zdefiniowany w systemie wystarczy podąć jego numer. Drugim argumentem jest łańcuch znaków określający źródło błędu (ustawienie właściwości ‘Err.Source’). Trzecim argumentem jest łańcuch znaków będący opisem błędu (ustawienie właściwości ‘Err.Description’). Istnieją jeszcze dwa parametry definiujące plik pomocy i kontekst w tym pliku dotyczący generowanego błędu, lecz w ramach laboratorium nie będą wykorzystywane.

Przycisk ‘btnObliczWszystko’ oprócz objętości końcowej bryły liczy również objętości i pola powierzchni dla poszczególnych walców składowych. Procedura obsługi zdarzenia ‘Click’ tego przycisku wywołuje dla danych każdego z czterech walców naszą procedurę o nazwie ‘walecObliczenia’, która przyjmuje w sumie sześć

argumentów. Dwa argumenty typu tekstowego (String) przekazywane są przez wartość (ByVal). Pierwszy argument jest interpretowany jako promień walca, drugi jako wysokość. Cztery pozostałe argumenty służą do wyprowadzenia na zewnątrz procedury wyników dokonanych przez nią obliczeń. Są to liczby typu (Double) przekazane przez

referencję (ByRef), dzięki temu operujemy na oryginalnych zmiennych zadeklarowanych w procedurze wywołującej.

Wszystkie zmiany ich wartości wewnątrz procedury są widoczne w procedurze wywołującej, co pozwala

na wyprowadzenie obliczeń z procedury na zewnątrz. Parametry te są interpretowane odpowiednio jako: objętość;

pole powierzchni podstawy, pole powierzchni bocznej i pole powierzchni całkowitej walca. Proszę zwrócić uwagę, że w procedurze wywołującej trzy zmienne dotyczące pól powierzchni są wspólne dla wszystkich walców. Wynika to z faktu, iż po dokonaniu obliczeń dla jednego walca, wyniki są zapisywane w obiektach TextBox i mogą już zostać nadpisane obliczeniami dla następnego walca.

Procedura o nazwie ‘wyczyscNaZmiane’ obsługuje zdarzenia ‘TextChanged’ dla ośmiu obiektów TextBox do wprowadzania danych (białe na formularzu). Nazwa procedury nie ma znaczenia pod warunkiem, że jest unikalna w ramach formularza. Istotna jest natomiast, posłowie kluczowym (Handles), lista oddzielona przecinkami

‘obiekt.zdarzenie’ określająca, które zdarzenia, jakich obiektów będą obsłużone przez tą procedurą.

Zarówno w procedurze obsługi zdarzenia ‘Click’ przycisku ‘btnWyczysc’, jak i w procedurze obsługi zdarzenia ‘TextChanged’ dla obiektów TextBox służących do wprowadzania danych, należy wyczyścić wszystkie obiekty TextBox prezentujące wyniki (zielone na formularzu). Dlatego napisano własna procedurę bez parametrów o nazwie ‘czyscWyniki’, która została wywołana w tych dwóch ww. procedurach. Procedurę ‘czyscWyniki’

można byłoby wywołać również w procedurze obsługi zdarzenia ‘Click’ przycisku ‘btnObliczWszystko’ w sytuacji, gdy zostaje wygenerowany błąd, gdy objętość bryły nie jest dodatnia.

(3)

Kod aplikacji:

Public Class frmWalecSub

Private Sub btnKoniec_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles btnKoniec.Click

Application.Exit() 'Zakończenie aplikacji

End Sub

' Własna procedura czyszcząca obiekty TextBox prezentujące wyniki (zielone na formularzu)

Private Sub czyscWyniki() txtVw1.Clear()

txtVw2.Clear() txtVw3.Clear() txtVz.Clear() txtPbW1.Clear() txtPbW2.Clear() txtPbW3.Clear() txtPbZ.Clear() txtPcW1.Clear() txtPcW2.Clear() txtPcW3.Clear() txtPcZ.Clear() txtPpW1.Clear() txtPpW2.Clear() txtPpW3.Clear() txtPpZ.Clear()

txtObjetoscBryly.Clear() End Sub

' do wprowadzania danych (białe na formularzu)

' Procedura obsługująca zdarzenia TextChanged dla obiektów TextBox

' Nazwa procedury nie ma znaczenia, aby była unikalna

' Istotna jest posłowie kluczowym Handles (oddzielona przecinkami) lista obiekt.zdarzenie

' określająca, które zdarzenia, jakich obiektów będą obsłużone tą procedurą

Private Sub wyczyscNaZmiane(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles txtHw1.TextChanged, txtHw2.TextChanged, txtHw3.TextChanged, txtHz.TextChanged, _ txtRw1.TextChanged, txtRw2.TextChanged, txtRw3.TextChanged, txtRz.TextChanged

Call czyscWyniki() 'Wywołanie procedury czyszczącej wszystkie pola TextBox prezentujące wyniki

End Sub

' Procedura obsługująca zdarzenie klik na przycisku Wyczyść

' Czyści wszystkie obiekty TextBox na formularzu

Private Sub btnWyczysc_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles btnWyczysc.Click

txtHw1.Clear() txtHw2.Clear() txtHw3.Clear() txtHz.Clear() txtRw1.Clear() txtRw2.Clear() txtRw3.Clear() txtRz.Clear()

Call czyscWyniki() 'Wywołanie procedury czyszczącej wszystkie pola TextBox prezentujące wyniki

End Sub

' Własna funkcja zwracająca objętość walca jako liczbę typu Double

' Przyjmuje dwa argumenty typu tekstowego (String) przekazane przez wartość (ByVal)

' Pierwszy argument jest interpretowany jako promień walca, drugi jako wysokość ' czyli wymuszające utworzenie wewnątrz funkcji kopii przekazywanej zmiennej

Private Function walecObjetosc(ByVal txtR As String, ByVal txtH As String) As Double 'Deklaracja zmiennych liczbowych dla promienia i wysokości walca

Dim dblR, dblH As Double

dblR = CDbl(txtR) 'Zamiana typu ze String na Double dla promienia

If dblR <= 0 Then 'prawda, gdy promień nie jest dodatni

'wygenerowanie własnego błędu, gdy promień nie jest dodatni

'Err.Raise(numer_błędu, źródło_błędu, opis_błędu)

'chr(34) zwraca znak " 'Err.Raise(Err.Number, Err.Source, Err.Description)

Err.Raise(9999, "Sprawdzenie danych walca", _

"Promień " & Chr(34) & txtR & Chr(34) & " nie jest większy od zera") End If

dblH = CDbl(txtH) 'Zamiana typu ze String na Double dla wysokości

(4)

If dblH <= 0 Then 'prawda, gdy wysokość nie jest dodatnia

'wygenerowanie własnego błędu, gdy wysokość nie jest dodatnia

Err.Raise(9998, "Sprawdzenie danych walca", _

"Wysokość " & Chr(34) & txtH & Chr(34) & " nie jest większa od zera") End If

'Zwrócenie wartości przez funkcję

'słowo kluczowe Return zwraca wartość wyrażenia podanego po nim i kończy działanie funkcji

Return Math.PI * dblR ^ 2 * dblH

'pod nazwę funkcji, lecz nie kończy to funkcji aż do końca jej kodu 'innym sposobem zwrócenia wartości przez funkcję jest przypisanie wartości wyrażenia

' alecObjetw osc = Math.PI * dblR ^ 2 * dblH End Function

Private Sub btnObliczObjetoscBryly_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnObliczObjetoscBryly.Click

'objętość walca zewnętrznego, wewnętrznych od 1 do 3 i objętość bryły

Dim dblVz, dblVw1, dblVw2, dblVw3, dblVbryly As Double Try 'próbuj

dblVz = walecObjetosc(txtRz.Text, txtHz.Text) 'wywołanie funkcji dla walca zewnętrznego

dblVw1 = walecObjetosc(txtRw1.Text, txtHw1.Text) 'wywołanie funkcji dla walca wewnętrznego nr 1

dblVw2 = walecObjetosc(txtRw2.Text, txtHw2.Text) 'wywołanie funkcji dla walca wewnętrznego nr 2

dblVw3 = walecObjetosc(txtRw3.Text, txtHw3.Text) 'wywołanie funkcji dla walca wewnętrznego nr 2

dblVbryly = dblVz - dblVw1 - dblVw2 - dblVw3 'obliczenie całkowitej objętości bryły

If dblVbryly <= 0 Then 'prawda, gdy objętość bryły nie jest dodatnia

'wygenerowanie własnego błędu, gdy objętość bryły nie jest dodatnia

Err.Raise(9997, "Obliczanie objętości bryły", _ "Złe dane:" & vbCrLf & _

"Suma objętości walców wewnętrznych jest większa niż objętość walca zewnętrznego") End If

txtObjetoscBryly.Text = dblVbryly.ToString 'wyświetlenie objętości bryły

Catch ex As Exception 'gdy błąd przechwyć

'czy wygenerowanych przez nas za pomocą metody Raise obiektu Err 'Obsługa zaistniałych błędów, również tych powstałych wewnątrz wywoływanych funkcji

MsgBox("Błąd numer: " & Err.Number.ToString & vbCrLf & Err.Description, _ MsgBoxStyle.Exclamation, Err.Source)

End Try End Sub

' Własna procedura przyjmuje w sumie sześć argumentów

' czyli wymuszające utworzenie wewnątrz funkcji kopii przekazywanej zmiennej ' Dwa argumenty typu tekstowego (String) przekazane przez wartość (ByVal)

' Pierwszy argument jest promień walca, drugi jako wysokość

' Cztery pozostałe argumenty są liczbami typu Double przekazane przez referencję (ByRef),

' dzięki temu operujemy na oryginalnych zmiennych zadeklarowanych w procedurze wywołującej.

' Wszystkie zmiany ich wartości są widoczne w procedurze wywołującej,

' co pozwala na wyprowadzenie obliczeń z procedury na zewnątrz

' są interpretowane odpowiednio jako:

' objętość; pole powierzchni podstawy, bocznej i całkowitej walca

Private Sub walecObliczenia(ByVal txtR As String, ByVal txtH As String, _

ByRef dblV As Double, ByRef dblPp As Double, ByRef dblPb As Double, ByRef dblPc As Double) 'Deklaracja zmiennych liczbowych dla promienia i wysokości walca

Dim dblR, dblH As Double

dblR = CDbl(txtR) 'Zamiana typu ze String na Double dla promienia

If dblR <= 0 Then 'prawda, gdy promień nie jest dodatni

'wygenerowanie własnego błędu, gdy promień nie jest dodatni

Err.Raise(9999, "Sprawdzenie danych walca", _

"Promień " & Chr(34) & txtR & Chr(34) & " nie jest większy od zera") End If

dblH = CDbl(txtH) 'Zamiana typu ze String na Double dla wysokości

If dblH <= 0 Then 'prawda, gdy wysokość nie jest dodatnia

'wygenerowanie własnego błędu, gdy wysokość nie jest dodatnia

Err.Raise(9998, "Sprawdzenie danych walca", _

"Wysokość " & Chr(34) & txtH & Chr(34) & " nie jest większa od zera") End If

'Obliczenia wykonywane poniżej podstawiane są pod zmienne przekazane do procedury przez referencję,

'dzięki temu operujemy na oryginalnych zmiennych zadeklarowanych w procedurze wywołującej

'i wyniki są tam widoczne

dblPp = Math.PI * dblR ^ 2 'obliczenie pola powierzchni podstawy

dblPb = 2 * Math.PI * dblR * dblH 'obliczenie pola powierzchni bocznej

dblPc = 2 * dblPp + dblPb 'obliczenie pola powierzchni całkowitej

dblV = dblPp * dblH 'obliczenie objętości walca

End Sub

(5)

Private Sub btnObliczWszystko_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnObliczWszystko.Click

'objętość walca zewnętrznego, wewnętrznych od 1 do 3 i objętość bryły

Dim dblVz, dblVw1, dblVw2, dblVw3, dblVbryly As Double 'pole powierzchni podstawy, bocznej i całkowitej walca

Dim dblPp, dblPb, dblPc As Double Try 'próbuj

'wywołanie procedury dla walca zewnętrznego

Call walecObliczenia(txtRz.Text, txtHz.Text, dblVz, dblPp, dblPb, dblPc) txtVz.Text = dblVz.ToString 'wyświetlenie objętości dla walca zewnętrznego

txtPpZ.Text = dblPp.ToString 'wyświetlenie pola powierzchni podstawy dla walca zewnętrznego

txtPbZ.Text = dblPb.ToString 'wyświetlenie pola powierzchni bocznej dla walca zewnętrznego

txtPcZ.Text = dblPc.ToString 'wyświetlenie pola powierzchni całkowitej dla walca zewnętrznego

'wywołanie procedury dla walca wewnętrznego nr 1

Call walecObliczenia(txtRw1.Text, txtHw1.Text, dblVw1, dblPp, dblPb, dblPc) txtVw1.Text = dblVw1.ToString 'wyświetlenie objętości dla walca wewnętrznego nr 1

txtPpW1.Text = dblPp.ToString 'wyświetlenie pola pow. podstawy dla walca wewnętrznego nr 1

txtPbW1.Text = dblPb.ToString 'wyświetlenie pola pow. bocznej dla walca wewnętrznego nr 1

txtPcW1.Text = dblPc.ToString 'wyświetlenie pola pow. całkowitej dla walca wewnętrznego nr 1

'wywołanie procedury dla walca wewnętrznego nr 2

Call walecObliczenia(txtRw2.Text, txtHw2.Text, dblVw2, dblPp, dblPb, dblPc) txtVw2.Text = dblVw2.ToString 'wyświetlenie objętości dla walca wewnętrznego nr 2

txtPpW2.Text = dblPp.ToString 'wyświetlenie pola pow. podstawy dla walca wewnętrznego nr 2

txtPbW2.Text = dblPb.ToString 'wyświetlenie pola pow. bocznej dla walca wewnętrznego nr 2

txtPcW2.Text = dblPc.ToString 'wyświetlenie pola pow. całkowitej dla walca wewnętrznego nr 2

'wywołanie procedury dla walca wewnętrznego nr 3

Call walecObliczenia(txtRw3.Text, txtHw3.Text, dblVw3, dblPp, dblPb, dblPc) txtVw3.Text = dblVw3.ToString 'wyświetlenie objętości dla walca wewnętrznego nr 3

txtPpW3.Text = dblPp.ToString 'wyświetlenie pola pow. podstawy dla walca wewnętrznego nr 3

txtPbW3.Text = dblPb.ToString 'wyświetlenie pola pow. bocznej dla walca wewnętrznego nr 3

txtPcW3.Text = dblPc.ToString 'wyświetlenie pola pow. całkowitej dla walca wewnętrznego nr 3

dblVbryly = dblVz - dblVw1 - dblVw2 - dblVw3 'obliczenie całkowitej objętości bryły

If dblVbryly <= 0 Then 'prawda, gdy objętość bryły nie jest dodatnia

'wygenerowanie własnego błędu, gdy objętość bryły nie jest dodatnia

Err.Raise(9997, "Obliczanie objętości bryły", _ "Złe dane:" & vbCrLf & _

"Suma objętości walców wewnętrznych jest większa niż objętość walca zewnętrznego") End If

txtObjetoscBryly.Text = dblVbryly.ToString 'wyświetlenie objętości bryły

Catch ex As Exception 'gdy błąd przechwyć

'Obsługa zaistniałych błędów, również tych powstałych wewnątrz wywoływanych procedur

'czy wygenerowanych przez nas za pomocą metody Raise obiektu Err

MsgBox("Błąd numer: " & Err.Number.ToString & vbCrLf & Err.Description, _ MsgBoxStyle.Exclamation, Err.Source)

End Try

End ClassEnd Sub

Cytaty

Powiązane dokumenty

Funkcja ta jest określona w ℝ\{0}, ale w {0} ma tę właściwość, że w tym punkcie ma obustronną granicę, równą 1, więc istnieje pokusa, by taką funkcję określić na całym

(2) Jeżeli istnieje czysto materialistyczne, niekoliste, kauzalne wyjaśnienie intencjonalności, to w odpowiednich ciągach przyczynowych jest możliwe wskazanie – bez odwoływania

Wykazaliśmy, że ciąg liczb naturalnych, który ma skończoną granicę musi być od pewnego miejsca stały, więc granica jest równa pewnym wyrazom ciągu.. Jest to niezgodne z

Uogólnieniem interpolacji Lagrange’a jest interpolacja l’Hermitte’a, w której w węzłach obok wartości funkcji mogą być również dane wartości pochodnych...

Wynika z tego, że dopiero po wykonaniu instrukcji wyzwalany jest wyzwalacz, natomiast warunki ograniczeń sprawdzane są przed wykonaniem instrukcji języka SQL. Konsekwencją

W bazie danych hurtownia_nazwisko utwórz procedurę o nazwie ZAMOWIENIA, która wyświetli ilość zamówień złożonych przez każdego klienta.

(Poniższe zadanie jest bardzo uproszczoną wersją zadania opracowanego przez dr hab. Witolda Marowskiego). patrz także inne

Znaleźć kąt przecięcia się krzywych: a). Wyznaczyć przedziały monotoniczności i ekstrema funkcji określonych wzorami:..