Skocz do zawartości

10. Funkcje - szersze zrozumienie


# CSH External VIP Project

Masz dosyć problemów z czynnikiem zaufania w CS2 lub notorycznymi banami?

Sprawdź CSH External VIP Project.


Więcej informacji  

Rekomendowane odpowiedzi

To będzie króciutka lekcja służąca zrozumieniu niektórych dziwnych tworów funkcji, na które możemy natrafić w niektórych bibliotekach (czyli tych plikach, które ładujemy za pomocą #Include - np. IE.au3). Warto wiedzieć czemu służą różne zapisy, by łatwiej było nam zrozumieć działanie funkcji.

 

Ktoś mógłby zapytać: "Ale po co zaglądać do bibliotek", ano naprawdę warto zaglądać do bibliotek, ponieważ funkcje które tam znajdziemy mogą poszerzyć naszą wiedzę i ułatwić w przyszłości pracę. Podam taki przykład, którego część z Was może nie zrozumie, ale na pierwszy rzut oka widać krótszy zapis, a co za tym idzie szybsze wykonanie programu:

 

Taki fragment kodu:

$oForm=_IEFormGetObjByName($oIE,"login_form")
$oElement=_IEFormElementGetObjByName($oForm,"username")
_IEFormElementSetValue($oElement,$login)

;a tu mamy definicje funkcji które wykonujemy powyżej (pobrane z IE.au3)
Func _IEFormGetObjByName(ByRef $o_object, $s_Name, $i_index = 0)
If Not IsObj($o_object) Then
__IEErrorNotify("Error", "_IEFormGetObjByName", "$_IEStatus_InvalidDataType")
Return SetError($_IEStatus_InvalidDataType, 1, 0)
EndIf
;
;----- Determine valid collection length
Local $i_length = 0
Local $o_col = $o_object.document.forms.item($s_Name)
If IsObj($o_col) Then
If __IEIsObjType($o_col, "elementcollection") Then
$i_length = $o_col.length
Else
$i_length = 1
EndIf
EndIf
;-----
$i_index = Number($i_index)
If $i_index = -1 Then
Return SetError($_IEStatus_Success, $i_length, $o_object.document.forms.item($s_Name))
Else
If IsObj($o_object.document.forms.item($s_Name, $i_index)) Then
Return SetError($_IEStatus_Success, $i_length, $o_object.document.forms.item($s_Name, $i_index))
Else
__IEErrorNotify("Warning", "_IEFormGetObjByName", "$_IEStatus_NoMatch")
Return SetError($_IEStatus_NoMatch, 0, 0) ; Could be caused by parameter 2, 3 or both
EndIf
EndIf
EndFunc ;==>_IEFormGetObjByName
Func _IEFormElementGetObjByName(ByRef $o_object, $s_Name, $i_index = 0)
If Not IsObj($o_object) Then
__IEErrorNotify("Error", "_IEFormElementGetObjByName", "$_IEStatus_InvalidDataType")
Return SetError($_IEStatus_InvalidDataType, 1, 0)
EndIf
;
If Not __IEIsObjType($o_object, "form") Then
__IEErrorNotify("Error", "_IEFormElementGetObjByName", "$_IEStatus_InvalidObjectType")
Return SetError($_IEStatus_InvalidObjectType, 1, 0)
EndIf
;
;----- Determine valid collection length
Local $i_length = 0
Local $o_col = $o_object.elements.item($s_Name)
If IsObj($o_col) Then
If __IEIsObjType($o_col, "elementcollection") Then
$i_length = $o_col.length
Else
$i_length = 1
EndIf
EndIf
;-----
$i_index = Number($i_index)
If $i_index = -1 Then
Return SetError($_IEStatus_Success, $i_length, $o_object.elements.item($s_Name))
Else
If IsObj($o_object.elements.item($s_Name, $i_index)) Then
Return SetError($_IEStatus_Success, $i_length, $o_object.elements.item($s_Name, $i_index))
Else
__IEErrorNotify("Warning", "_IEFormElementGetObjByName", "$_IEStatus_NoMatch")
Return SetError($_IEStatus_NoMatch, 0, 0) ; Could be caused by parameter 2, 3 or both
EndIf
EndIf
EndFunc ;==>_IEFormElementGetObjByName
Func _IEFormElementSetValue(ByRef $o_object, $s_newvalue, $f_fireEvent = 1)
If Not IsObj($o_object) Then
__IEErrorNotify("Error", "_IEFormElementSetValue", "$_IEStatus_InvalidDataType")
Return SetError($_IEStatus_InvalidDataType, 1, 0)
EndIf
;
If Not __IEIsObjType($o_object, "forminputelement") Then
__IEErrorNotify("Error", "_IEFormElementSetValue", "$_IEStatus_InvalidObjectType")
Return SetError($_IEStatus_InvalidObjectType, 1, 0)
EndIf
;
If String($o_object.type) = "file" Then
__IEErrorNotify("Error", "_IEFormElementSetValue", "$_IEStatus_InvalidObjectType", "Browser securuty prevents SetValue of TYPE=FILE")
Return SetError($_IEStatus_InvalidObjectType, 1, 0)
EndIf
;
$o_object.value = $s_newvalue
If $f_fireEvent Then
$o_object.fireEvent("onchange")
$o_object.fireEvent("onclick")
EndIf
Return SetError($_IEStatus_Success, 0, 1)
EndFunc ;==>_IEFormElementSetValue

Zastępuję tym:

;prezentuję tu działania na obiektach, których zapewne nie znacie, ale nie przejmujcie się, jeszcze to poznamy <img src='http://www.cshacked.pl/public/style_emoticons/<#EMO_DIR#>/biggrin.png' class='bbc_emoticon' alt=':D' />
$oIE.document.forms.item("login_form").elements.item("username").value = $login

Chyba każdy z nas widzi ogromną różnicę. Dla programisty są to 2 linijki różnicy, ponieważ on nie będzie musiał przepisywać kodu definicji funkcji z biblioteki, ale dla programu to o wiele więcej linijek, ponieważ program będzie musiał wykonać cały kod.

 

Biblioteki pisane są pod "studentów" czyli tych co lubią zepsuć (bez urazy, ja tu parafrazuję ). Dlatego jest w nich bardzo dużo zbędnego kodu, który wyświetla wszystkie błędy, problemy itd. Nie męczmy tym naszego programu i zaglądajmy w biblioteki. Usuwając zbędne fragmenty zdecydowanie przyśpieszymy działanie programu.

 

Nie o tym jednak ma być mowa w dzisiejszej lekcji. Dzisiaj chciałbym przybliżyć Wam bardziej definicję (czyli tą dłuższą część ) funkcji. Przypomnę te dwa nierozłączne elementy funkcji:

;odwołanie do funkcji
Suma($a,$<img src='http://www.cshacked.pl/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />
;definicja/ciało funkcji
Func Suma($a,$<img src='http://www.cshacked.pl/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />
Return $a + $b
EndFunc

W definicji czasem pojawiają się dziwne twory, których może jeszcze nie rozumiemy, a mianowicie mam na myśli "komendy" przy argumentach.

Czasem możemy spotkać się z takim zapisem:

;definicja/ciało funkcji
Func Suma( ByRef $a, Const $<img src='http://www.cshacked.pl/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />
Return $a + $b
EndFunc

Wytłumaczymy je sobie kolejno poczynając od lewej. Pierwszy z nich (ByRef) to wczytanie argumentu przez referencję.

Gdy NIE MA tego operatora, to podczas wczytania do funkcji powstaje lokalny duplikat argumentu (czyli wczytywana zmienna jest duplikowana specjalnie dla użytku tejże funkcji, po zakończeniu tej funkcji (po słowach EndFunc) po prostu znika). Oznacza to, że nieważne co byśmy w tej funkcji z tą zmienną zrobili, to nie wpłynie to na oryginalną zmienną (zaraz podam przykład). Taki rodzaj wczytywania nazywamy wczytaniem argumentu przez wartość.

 

Gdy natomiast użyjemy operatora ByRef, to do funkcji przesyłana jest oryginalna zmienna i każda jej zmiana w ciele funkcji wpływa na oryginał. Taki rodzaj wczytywania nazywamy wczytaniem argumentu przez referencję.

 

No to machniemy sobie przykładzik:

Przykład 1- wczytanie zmiennej przez wartość

$a=1
$b=2
Machnij($a,$<img src='http://www.cshacked.pl/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />
Func Machnij($a,$<img src='http://www.cshacked.pl/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />
$a=10
$b=10
EndFunc
MsgBox(0,"Co z tego wyszło","$a=" & $a & @LF & "$b=" & $<img src='http://www.cshacked.pl/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />
;@LF to makro zawierające znak przejścia do nowej linii.
Przykład 2- wczytanie zmiennej przez referencję

$a=1
$b=2
Machnij($a, $<img src='http://www.cshacked.pl/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />
Func Machnij(ByRef $a, ByRef $<img src='http://www.cshacked.pl/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />
$a=10
$b=10
EndFunc
MsgBox(0,"Co z tego wyszło","$a=" & $a & @LF & "$b=" & $<img src='http://www.cshacked.pl/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />
;@LF to makro zawierające znak przejścia do nowej linii.

Wykonajcie te 2 przykłady i wszystko Wam się rozjaśni. Sprawa prosta jak drut. Pozostaje jeszcze kwestia: "Dlaczego warto używać ByRef ?".

Oczywiście po to by przyspieszyć program. Czasami zmierzymy się z ogromnych rozmiarów zmiennymi (np. Kod HTML jakiejś obszernej strony, który trzeba odświeżać co 1sek). Tworzenie duplikatu takiej zmiennej kradnie programowi sporo czasu, dlatego wtedy warto wykorzystać ByRef. Tyle na ten temat. Myślę, że zrozumiałe.

 

Co do Const, to oznacza on wczytanie stałej. Takiej stałej nie możemy modyfikować w ciele funkcji. Pokarzę więc krótko o co chodzi (tak będzie najszybciej)

$a=0
Machnij($a);jako arg. mozna podac zmienną
Machnij(1);jako arg. mozna podac wartosc

$a=2;poza ciałem funkcji mozemy zmienną modyfikować
Machnij($a)

Func Machnij(Const $a)
;w ciele funkcji nie mozemy zmiennej modyfikować
;więc tutaj zapis typu:
;a=2
;wywoła bład kompilacji
MsgBox(0,"a",$a)
EndFunc
No myślę, że to jest zrozumiałe. Nie pytajcie mnie po co ktoś wymyślił coś takiego jak Const, bo naprawdę nie wiem. Dla mnie mogłoby tego nie być. Obstawiam, że istnieje to tylko po to, żeby programista czasem nie popełnił gdzieś błędu i nie modyfikował przypadkiem stałych które gdzieś-tam kiedyś zadeklarował. Wiecie jak to jest :

Const $PI=3,14
;...
;1000 linijek później
;...
$PI="Proces Interface"
;...
;ups coś spieprzyłem

No i to na tyle. Powinniście teraz wiedzieć,

- że warto zaglądać do bibliotek/UDF,

- że jest zasadnicza różnica między wczytaniem poprzez wartość, a referencję,

Pozdrawiam i życzę udanej kompilacji.

 

Pozdrawiam,

Yubasek.

Odnośnik do komentarza

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

Gość
Ten temat został zamknięty. Brak możliwości dodania odpowiedzi.
  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...

Powiadomienie o plikach cookie

Umieściliśmy na Twoim urządzeniu pliki cookie, aby pomóc Ci usprawnić przeglądanie strony. Możesz dostosować ustawienia plików cookie, w przeciwnym wypadku zakładamy, że wyrażasz na to zgodę. Regulamin. Polityka prywatności