AutoIt/Ćwiczenia dla zaawansowanych - przykładowe rozwiązania
Funkcje rekurencyjne
[edytuj]1. Napisać funkcję rekurencyjną sumująca liczby całkowite w przedziale od m do n (m i n podawane jako parametry).
Funkcja powinna działać prawidłowo także dla liczb ujemnych, oraz niezależnie od kolejności podanych parametrów.
Jeżeli podamy jeden parametr to sumowanie powinno być od zera lub do zera (dla liczb ujemnych).
Przykładowe rozwiązanie:
Func suma($n, $m=0.0) ;drugi parametr opcjonalny, z domyślną wartością 0.0
If $n<$m Then ;kalibrowanie danych, aby można było wpisywać liczby w dowolnej kolejności
$pom=$n
$n=$p
$m=$pom
EndIf
if $n=$m Then Return $m ;przypadek bazowy dla najmniejszej liczby
Return $n+suma($n-1,$m) ;obliczenia rekurencyjne
EndFunc
Ilość sumowanych liczb jest ograniczona do ok.4000, przy większej ilości ze względu na możliwość przepełnienia stosu działanie funkcji zostanie przerwane.
2. Napisać rekurencyjną funkcję obliczającą liczbę e. Funkcja ta powinna korzystać z rekurencyjnej funkcji silna zdefiniowanej w powyższym przykładzie.
Skorzystać z rozwinięcia w szereg e = 1 + 1/1! + 1/2! + ... + 1/n! + ... (graniczna wartość n podawana jako parametr).
(dla sprawdzenia przybliżona wartość e = 2.718281828459...)
Przykładowe rozwiązanie:
Func e($n)
if $n=0 Then Return 1.0 ;przypadek bazowy dla n=0
Return 1/silnia($n)+e($n-1) ;wywołanie rekurencyjne i wywołanie innej funkcji rekurencyjnej
EndFunc
Func silnia($n)
if $n=0 Then Return 1.0
Return $n*silnia($n-1)
EndFunc
Jak widać w powyższym przykładzie funkcja rekurencyjna może w swojej definicji wywoływać inną funkcję rekurencyjną.
Napisy (stringi)
[edytuj]1. Napisać skrypt wyświetlający ile procent znaków w wczytanym z dysku pliku tekstowym stanowi litera a (wielkość litery nie ma znaczenia). Skrypt powinien zawierać zdefiniowaną funkcję zliczającą w stringu ilość wystąpień dowolnego znaku.
;wywołanie systemowego selektora plików i wczytanie do zmiennej nazwy wybranego pliku
$sFile = FileOpenDialog("Wybierz plik tekstowy","","(*.txt)")
$sTxt = FileRead($sFile);wczytanie pliku tekstowego do zmiennej
$sChr = "a"
;wyliczenie procentowego udziału litery a w całym tekście
;(ilość_a/ilość_znaków w tekście, x100 żeby było w procentach)
$iUdzial = 100 * licz_znaki($sTxt, $sChr) / StringLen($sTxt)
;
$iUdzial = Round($iUdzial, 2) ;zaokrąglenie wyniku do 2 miejsc po kropce dziesiętnej
;wyświetlenie wyniku na ekranie
MsgBox(0,"Stringi - ćwiczenie 1", "Litera '" & $sChr & "' stanowi " & $iUdzial & "% wszystkich znaków")
;funkcja zliczająca ilość wystąpień znaku $sChr w stringu $sTxt
Func licz_znaki($sTxt, $chr)
StringReplace($sTxt,$sChr,$sChr) ;zamiana znaków na te same znaki
Return @extended ;to makro podaje ilość zamian
EndFunc
2. Używając funkcji formatującej StringFormat napisać skrypt wyświetlający liczby -445.987, 0.00878, 2011 z wyrównaniem na kropce dziesiętnej jak poniżej:
-445.987 +0.00878 +2011.00
Tego typu wyrównanie będzie możliwe tylko dla fontów nieproporcjonalnych (o stałej szerokości), np. Courier, Courier New, itp.
Przykładowe rozwiązanie:
$v1 = -445.987
$v2 = 0.00878
$v3 = 2011
$format = "%+11.5f\n%+11.5f\n%+11.5f" ;łańcuch formatujący
SplashTextOn("Formatowanie liczb:", StringFormat($format, $v1, $v2, $v3),-1,-1,-1,-1,-1,"Courier")
Sleep(5000)
Wyrażenia regularne
[edytuj]1. Napisać skrypt sprawdzający czy podany string jest prawidłową (pod względem formalnym) ścieżką dostępu do pliku.
Rozwiązanie rozpoczynamy od określenia formatu ścieżki dostępu. Wygląda on następująco: x:\...\...\...\nazwa_pliku itd., gdzie x - dowolna litera od a do z, ... - nazwa podfolderów. W systemie plików NTFS nazwa folderów i plików może składać się z dowolnych znaków z wyjątkiem /\*?<>|:"
Maksymalna długość pełnej ścieżki 260 znaków.
Przykładowe rozwiązanie:
$sPath = "c:\folder1\folder2\folder3\program.exe" ;przykładowa ścieżka dostępu
;eliminujemy łańcuchy za długie lub zawierające niedozwolone znaki (wzorce alternatywne)
;więcej niż 1 dwukropek, któryś ze znaków /*?<>|" lub jest dłuższy niż 260 znaków
;lub między \\ nic lub tylko białe znaki
If StringRegExp($sPath, ':{2,}|[/*?<>|"]|.{260,}|\\\s*\\') Then
MsgBox(0, "", "Zła ścieżka dostępu")
Else
If StringRegExp($sPath,"(?i)^[a-z]:\\") Then ;sprawdzenie formatu ścieżki
MsgBox(0, "" ,"Prawidłowa ścieżka dostępu")
Else
MsgBox(0, "", "Zła ścieżka dostępu")
Endif
Endif
2. Napisać skrypt dzielący dany tekst na pojedyncze słowa. Separatorem słów są białe znaki.
Przykładowe rozwiązanie:
#include <Array.au3> ;dołączenie biblioteki Array.au3, aby uzyskać dostęp do funkcji _ArrayDisplay()
$txt="matma tata kasetka. roma 1278a" ;przykładowy tekst
$tab=StringRegExp($txt,"\S+",3) ;w tablicy $tab znajdą się wszystkie dopasowania, czyli wyrazy
;(w naszym wypadku wyraz może się składać z dowolnych czarnych znaków)
_ArrayDisplay($tab) ;a tu można obejrzeć zawartość tablicy
3. Zamienić amerykański zapis dowolnej daty (mm-dd-rrrr) na zapis w formacie europejskim (rrrr.mm.dd).
Przykładowe rozwiązanie:
$sDataA = "12-22-1952" ;przykładowa data po amerykańsku
;zamiana na europejską z użyciem zapamiętanych dopasowań
$sDataE = StringRegExpReplace($sDataA, "(\d{2})-(\d{2})-(\d{4})", "$3.$1.$2")
MsgBox(0, $sDataA, $sDataE)
4. Napisać skrypt wyszukujący we wczytanym z dysku pliku tekstowym wszystkie słowa zaczynające się i kończące na te same dwie litery.
Przykładowe rozwiązanie:
#include <Array.au3>
;wywołanie systemowego selektora plików i wczytanie do zmiennej nazwy wybranego pliku
$sFtxt = FileOpenDialog("Wybierz plik tekstowy","","(*.txt)")
$sTxt = FileRead($sFtxt) ;wczytanie pliku tekstowego do zmiennej
$aTab = _StringRegExp($sTxt,"(?i)\b([a-z]{2})[a-z]*\1\b",1) ;porównanie tekstu z wzorcem
_ArrayDisplay($aTab) ;podgląd wyników
;==============================================================================================
;funkcja _StringRegExp (jest to zmodyfikowana funkcja StringRegExp z flagą 4)
;dla $iFlag=0 funkcja zwraca ilość dopasowań, dla $iFlag<>0 zwraca jednowymiarową tablicę
;zawierającą w kolejnych komórkach wszystkie dopasowania
;pozostałe parametry jak dla StringRegExp
;==============================================================================================
Func _StringRegExp($sTxt, $sPat, $iFlag=0, $iCount=1)
$aTab = StringRegExp($sTxt, $sPat, 4, $iCount)
If $iFlag = 0 Then Return UBound($aTab) ;zwrócenie odczytanej ilości dopasowań (dla flag=0)
Local $aRes[UBound($aTab)] ;tworzymy tablicę wyników
For $i = 0 to UBound($aTab)-1 ;w pętli wpisujemy do tablicy wyników kolejne dopasowania
$aRes[$i] = ($aTab[$i])[0]
Next
Return $aRes ;zwrócenie tablicy wyników (dla flag<>0)
EndFunc
Wyskakujące okna - prosta interakcja ze skryptem
[edytuj]1. Napisać skrypt porównujący wprowadzone z klawiatury hasło, z hasłem zapamiętanym w zmiennej. Skrypt powinien wyświetlić komunikat, czy hasło jest poprawne (w komunikacie umieścić odpowiednie ikonki informacyjne). Na wprowadzenie poprawnego hasła mamy 3 próby, potem skrypt powinien zakończyć działanie (wyświetlając stosowny komunikat).
Przykładowe rozwiązanie:
$pas="AutoIt" ;przykładowe hasło (wzorzec)
$title="SPRAWDZANIE HASŁA" ;stała część komunikatu wyświetlanego na belce
For $i=1 To 3 ;3 krotne sprawdzanie w pętli For...Next
;wprowadzenie hasła z klawiatury, znaki są maskowane
$wpas=InputBox($title&" - próba "&$i,"Wprowadź hasło","","*")
If $wpas==$pas Then ;sprawdzenie czy hasło i wzorzec są jednakowe (== sprawdza wielkość liter)
;jeżeli tak to wyświetla stosowny komunikat (z ikoną informacyjną)
MsgBox(64,$title&" - próba "&$i,"Hasło prawidłowe. ",5)
ExitLoop ;i kończymy pętlę po 5 sekundach (ExitLoop)
ElseIf $i<3 Then ;jeżeli hasło jest nieprawidłowe, a ilość prób mniejsza od
;można wybrać, czy kończymy, czy próbujemy dalej
If MsgBox(5+48,$title&" - próba "&$i,"Hasło nieprawidłowe!"&@LF&"Czy próbujesz ponownie?")=2 Then
;w przypadku rezygnacji stosowny komunikat
MsgBox(16,$title&" - próba "&$i,"Hasło nieprawidłowe!"&@LF&"Rezygnacja użytkownika.",5)
Exit ;i opuszczenie skryptu
EndIf
ElseIf $i=3 Then ;nieprawidłowe hasło w trzeciej próbie
;stosowny komunikat, po 5 sekundach
MsgBox(16,$title&" - próba "&$i,"Wprowadzono 3 razy złe hasło!"&@LF&"Program zostanie zamknięty.",5)
Exit ;kończymy program
EndIf
Next
;...........................................
;dalej część skryptu,
;działająca gdy wprowadzono prawidłowe hasło
;...........................................
2. Napisać skrypt będący przeglądarką plików. Powinien wczytywać wybrany na dysku plik i wyświetlić w okienku. Obsługa plików TXT, BMP, GIF i JPG.
Sposób wyświetlania uzależniony od typu pliku (rozpoznanie po rozszerzeniu).
Przykładowe rozwiązanie:
While 1 ;pętla nieskończona
;wywołanie systemowego selektora plików, z domyślnymi rozszerzeniami
$file=FileOpenDialog("Wybierz plik tekstowy lub obrazek","","(*.txt; *.bmp; *.jpg; *.gif)")
If @error Then Exit ;jeżeli użyto klawisz anuluj lub zamknięcia okna to makro @error=1 i koniec skryptu
If StringRight($file,4)=".txt" Then ;jeżeli nazwa pliku kończy się na ".txt"
$txt=FileRead($file,10000) ;wczytanie pliku tekstowego do zmiennej
SplashTextOn($file,$txt,600,900,20,20,2+4+16,Default,6) ;wywołanie okienka tekstowego
Else
SplashImageOn($file,$file,800,600,20,100,2+16) ;wywołanie okienka z obrazkiem
EndIf
WEnd ;koniec pętli
GUI
[edytuj]1. W oparciu o funkcję GUICtrlCreateInput napisać funkcję umożliwiającą wprowadzanie wyłącznie liczb dziesiętnych. Liczby mogą być dodatnie lub ujemne, całkowite lub z kropką dziesiętną. Stworzoną funkcję użyj w prostym skrypcie demonstracyjnym.
Wprowadzony string może mieć na początku znak minus (-), następnie dowolną ilość cyfr, kropkę dziesiętną i znowu dowolną ilość cyfr. Oczywiście znak minus i kropka są opcjonalne.
Minus może być tylko na początku, a kropka może wystąpić najwyżej jeden raz np.: -1.25, -.02, .1, 0.1, 356 itp.
Do sprawdzania poprawności wpisywanej liczby najprościej będzie użyć wyrażeń regularnych. Będzie ono wyglądać następująco: ^-?\d*\.?\d*$
Przykładowe rozwiązanie:
#include <GUIConstantsEx.au3>
GUICreate("Wprowadź liczbę",250,200,-1,250)
$f1=GUICtrlCreateInput("", 10, 5, 200, 20,2) ;wyrównanie do lewej
$f2=GUICtrlCreateInput("", 10, 35, 200, 20,2)
$f3=GUICtrlCreateInput("", 10, 65, 200, 20,2)
$f4=GUICtrlCreateInput("", 10, 95, 200, 20,2)
$btn=GUICtrlCreateButton("Ok", 90, 140, 60, 20)
GUISetState()
Do
$msg=GUIGetMsg()
$l1= _GUICtrlReadInputNumber($f1) ;liczby rzeczywiste
$l2= _GUICtrlReadInputNumber($f2,"+") ;liczby rzeczywiste dodatnia
$l3= _GUICtrlReadInputNumber($f3,"I") ;tylko liczby całkowite ze znakiem
$l4= _GUICtrlReadInputNumber($f4,"I+") ;tylko liczby całkowite dodatnia
If $msg=$btn Then ExitLoop
Until $msg=$GUI_EVENT_CLOSE
MsgBox(4096, "","Wprowadziłes liczbę: "&Number($l1)&" "&Number($l2)&" "&Number($l3)&" i "&Number($l4))
;================================================================================================================
;funkcja umożliwiająca wprowadzenie tylko stringu będącego prawidłowym zapisem liczby dziesiętnej
;do sprawdzenia poprawności stringu używamy wyrażenia regularnego
;aby odtworzyć wartość poprzednią wartość stringu przy kolejnym wywołaniu funkcji używamy
;zmiennej statycznej w postaci tablicy (aby można było obsłużyć jednocześnie większą ilość kontrolek)
;zadeklarowana ilość komórek powinna być większa od łącznej ilości kontrolek (na wszelki wypadek z dużym zapasem)
;Parametry:
;$handle_input - zaczep do kontrolki INPUT
;Parametr opcjonalny:
;$op="R+" lub $op="+" - liczby rzeczywiste dodatnie i 0
;$op="I" - liczby całkowite
;$op="I+" - liczby całkowite dodatnie i 0
;dowolna inna wartość - liczba rzeczywista (domyślne)
;================================================================================================================
Func _GUICtrlReadInputNumber($handle_input,$op=Default)
Local $liczba, $WR="^-?\d*\.?\d*$"
;deklarowanie statycznej tablicy do przechowywania aktualnej prawidłowej wartości wprowadzanego stringu
Static $liczba1[100]
If $op="R+" Or $op="r+" Or $op="+" Then $WR="^\d*\.?\d*$"
If $op="I" Or $op="i" Then $WR="^-?\d*$"
If $op="I+" Or $op="i+" Then $WR="^\d*$"
$liczba=GUICtrlRead($handle_input) ;odczytanie aktualnej wartości stringu
If StringRegExp($liczba,$WR) Then
$liczba1[$handle_input]=$liczba ;jeżeli string jest prawidłowy to zostanie zapamiętany
Else
GUICtrlSetData($handle_input,$liczba1[$handle_input]) ;jeżeli nie to odtwarzamy poprzednią wersję
EndIf
Return $liczba
EndFunc
2. Korzystając z kontrolek GUI napisać skrypt wyświetlający na ekranie zegar analogowo cyfrowy. Aby zajmować jak najmniej miejsca na ekranie zegar powinien mieć możliwość wyświetlania okna bez belki i ramki. W tym stanie zegar powinien mieć atrybut "zawsze na wierzchu". Należy także zapewnić możliwość przemieszczanie zegara w wygodne dla użytkownika miejsce ekranu.
Wyświetlacz analogowy można by zrealizować rysowania w okienku graficznym, ale prościej będzie użyć jakiejś kontrolki odwzorowującej graficznie zadaną wartość. Do wyboru mamy suwak (SLIDER) lub pasek postępu (PROGRESS). Zdecydowałem się na suwak. Okienko GUI za pomocą parametru exstyle (0x800+8=0x808) ma ustawiony atrybut "zawsze na wierzchu", oraz styl okienka narzędziowego (dzięki temu ikona nie pojawi się na pasku zadań). Ponieważ dla style = 0xc00000 nie są wyświetlane przyciski systemowe okna, musimy je stworzyć sami. Przycisk "X" służy do zamykania okna, natomiast przycisk "S" jest przełącznikiem zmieniającym styl okna (okno z belką i ramką / okno bez belki i ramki). Wyświetlacz cyfrowy został zrealizowany za pomocą kontrolki LABEL.
Przykładowe rozwiązanie:
#include <GUIConstantsEx.au3>
Local $iS1, $msg, $fWSK=True
$hGUI=GUICreate("Zegar:", 255, 95, 600, 300, 0xc00000, 0x88)
GUISetBkColor(0x00e6ff)
GUICtrlSetDefBkColor(0x00e6ff)
$hGodziny = GUICtrlCreateSlider(14, 2, 230, 30)
GUICtrlSetLimit(-1, 23) ;godziny
$hMinuty = GUICtrlCreateSlider(14, 24, 230, 22)
GUICtrlSetLimit(-1, 59) ;minuty
$hSekundy = GUICtrlCreateSlider(14, 46, 230, 22)
GUICtrlSetLimit(-1, 59) ;sekundy
$hZegar = GUICtrlCreateLabel("", 45, 68, 190, 40, 0x800)
GUICtrlSetFont(-1, 20, 1000, 2, "Comic Sans MS")
GUICtrlCreateLabel("H", 4, 6, 12, 12)
GUICtrlCreateLabel("M", 4, 28, 12, 12)
GUICtrlCreateLabel("S", 4, 50, 12, 12)
$hEnd = GUICtrlCreateButton("X", 245, 1, 10, 10)
GUICtrlSetBkColor(-1, 0xe07000)
$hStyle = GUICtrlCreateButton("S", 244, 20, 10, 10)
GUICtrlSetBkColor(-1, 0x00ff00)
GUISetState()
Do
$iH=@HOUR ;odczyt godziny
$iM=@MIN ;odczyt minuty
$iS=@SEC ;odczyt sekundy
If $msg=$hStyle Then ;obsługa przełącznika stylu okna
GUISetStyle(0x80000000 * $fWSK + (0xc00000*(Not $fWSK)))
$fWSK = Not $fWSK
EndIf
If $iS<>$iS1 Then ;zmiana ustawień gdy zmieniły się sekundy
GUICtrlSetData($hGodziny, $iH) ;ustawienie suwaka godzin
GUICtrlSetData($hMinuty, $iM) ;ustawienie suwaka minut
GUICtrlSetData($hSekundy, $iS) ;ustawienie suwaka sekund
GUICtrlSetData($hZegar, $iH&" : " & $iM & " : " & $iS) ;wyświetlacz cyfrowy
$iS1 = $iS
EndIf
$msg = GUIGetMsg()
Until $msg = $GUI_EVENT_CLOSE Or $msg = $hEnd
Przejmowanie kontroli
[edytuj]1. W oparciu o zdobyte w tym rozdziale informacje, zmodyfikować program zegara z ćwiczeń w GUI tak, aby możliwa była regulacja przejrzystości okna zegara.
Wykorzystamy funkcję ustalającą stopień przejrzystości okna WinSetTrans. Funkcja ta działa na wszystkich oknach, tak utworzonych przez zewnętrzne procesy, jak i przez sam skrypt. Wystarczy znać zaczep do okna. Nie ma z tym problemu, ponieważ sami je utworzyliśmy. Do okna zegara dodajemy dwa przyciski, jeden ze znakiem +, drugi ze znakiem -. Naciśnięcie pierwszego powoduje, że okno staje się wyraźniejsze (mniejsze przezroczystość), drugiego jego zblednięcie (większa przezroczystość).
Przykładowe rozwiązanie:
#include <GUIConstantsEx.au3>
Local $iS1, $msg, $fWSK=True, $iTrans=255
$hGUI = GUICreate("Zegar:", 255, 95, 600, 300, 0xc00000, 0x88)
GUISetBkColor(0x00e6ff)
GUICtrlSetDefBkColor(0x00e6ff)
$hGodziny = GUICtrlCreateSlider(14, 2, 230, 30)
GUICtrlSetLimit(-1, 23) ;godziny
$hMinuty = GUICtrlCreateSlider(14, 24, 230, 22)
GUICtrlSetLimit(-1, 59) ;minuty
$hSekundy = GUICtrlCreateSlider(14, 46, 230, 22)
GUICtrlSetLimit(-1, 59) ;sekundy
$hZegar = GUICtrlCreateLabel("", 45, 68, 190, 40, 0x800)
GUICtrlSetFont(-1, 20, 1000, 2, "Comic Sans MS")
GUICtrlCreateLabel("H", 4, 6, 12, 12)
GUICtrlCreateLabel("M", 4, 28, 12, 12)
GUICtrlCreateLabel("S", 4, 50, 12, 12)
$hEnd = GUICtrlCreateButton("X", 245, 1, 10, 10)
GUICtrlSetBkColor(-1, 0xe07000)
$hStyle = GUICtrlCreateButton("S", 244, 20, 10, 10)
GUICtrlSetBkColor(-1, 0x00ff00)
;dwa nowe przyciski
$hPlus = GUICtrlCreateButton("+", 244, 40, 10, 10)
GUICtrlSetBkColor(-1, 0xaaff00)
$hMinus = GUICtrlCreateButton("-", 244, 60, 10, 10)
GUICtrlSetBkColor(-1, 0xaaff00)
GUISetState()
Do
$iH = @HOUR ;odczyt godziny
$iM = @MIN ;odczyt minuty
$iS = @SEC ;odczyt sekundy
Switch $msg
Case $hStyle ;obsługa przełącznika stylu okna
GUISetStyle(0x80000000 * $fWSK + (0xc00000 * (Not $fWSK)))
$fWSK = Not $fWSK
Case $hPlus
$iTrans = min($iTrans+20, 255)
WinSetTrans($hGUI, "", $iTrans) ;zmniejszenie przezroczystości
Case $hMinus
$iTrans = max($iTrans-20, 30)
WinSetTrans($hGUI, "", $iTrans) ;zwiększenie przezroczystości
EndSwitch
If $iS <> $iS1 Then ;zmiana ustawień gdy zmieniły się sekundy
GUICtrlSetData($hGodziny, $iH) ;ustawienie suwaka godzin
GUICtrlSetData($hMinuty, $iM) ;ustawienie suwaka minut
GUICtrlSetData($hSekundy, $iS) ;ustawienie suwaka sekund
GUICtrlSetData($hZegar, $iH & " : " & $iM&" : " & $iS) ;wyświetlacz cyfrowy
$iS1 = $iS
EndIf
$msg = GUIGetMsg()
Until $msg = $GUI_EVENT_CLOSE Or $msg = $hEnd
;funkcje pomocnicze
Func min($a, $b)
If $a<=$b Then Return $a
Return $b
EndFunc
Func max($a, $b)
If $a<=$b Then Return $b
Return $a
EndFunc
Tworzenie bibliotek
[edytuj]1. Napisać pozostałą część biblioteki matematycznej, oraz prosty skrypt testujący jej działanie.
Przykładowe rozwiązanie (zwróćmy uwagę, że funkcje _am(), _gm() i _permutation() są polimorficzne):
#include-once
; #INDEX# ====================================================================
; Nazwa .........: Mathematic function
; AutoIt Version : 3.3.8.1
; Language ......: Polish
; Description ...: Dodatkowe funkcje matematyczne (Additional math functions)
; Author(s) .....: Wasta (2012)
; ============================================================================
; #CURRENT# ==================================================================
;Const $_PI
;_max
;_min
;_sign
;_am
;_gm
;_log10
;_logA
;_sinh
;_cosh
;_QRoots
;_factorial
;_combination
;_combinationWR
;_variation
;_variationWR
;_permutation
;_Bin
;_BinToDec
; =============================================================================
Global Const $_PI = 3.14159265358979323846264338328
; #FUNCTION# ==================================================================
; Name...........: _max
; Description ...: Większy z dwóch parametrów (The larger of the two parameters)
; Syntax.........: _max($var1, $var2)
; Parameters ....: Dwie liczby rzeczywiste (Two real numbers)
; Return values .: Większy z dwóch parametrów (The larger of the two parameters)
Func _max ($iVar1, $iVar2)
Return $iVar1>=$iVar2 ? $iVar1 : $iVar2
EndFunc
; #FUNCTION# ==================================================================
; Name...........: _min
; Description ...: Mniejszy z dwóch parametrów (The smaller of the two parameters)
; Syntax.........: _max($var1, $var2)
; Parameters ....: Dwie liczby rzeczywiste (Two real numbers)
; Return values .: Większy z dwóch parametrów (The smaller of the two parameters)
Func _min ($iVar1, $iVar2)
Return $iVar1>=$iVar2 ? $iVar2 : $iVar1
EndFunc
; #FUNCTION# ==================================================================
; Name...........: _sign
; Description ...: Znak liczby (The sign of number)
; Syntax.........: _sign($var)
; Parameters ....: liczba rzeczywista (Real number)
; Return values .: -1 - $var<0
; 0 - $var=0
; 1 - $var>0
Func _sign ($iVar)
Return ($iVar>0)-($iVar<0)
EndFunc
; #FUNCTION# ==================================================================
; Name...........: _am
; Description ...: Średnia arytmetyczna (The arithmetic mean)
; Syntax.........: _am($var1[, $var2])
; : _am($array)
; Parameters ....: Dwie liczby rzeczywiste (Two real numbers)
; : Jednowymiarowa tablica (One-dimensional array)
; Return values .: Success - Średnia arytmetyczna dwu liczb, lub elementów tablicy.
; (The arithmetic mean of two numbers, or elements of the array)
; Failure - "-1.#IND"
; @error=1
Func _am ($vVar1, $vVar2=False)
Local $i, $iSum=0
If @NumParams=2 Then Return ($vVar1+$vVar2)/2
If @NumParams=1 Then
If IsArray($vVar1) Then
If UBound($vVar1,0)>1 Then
SetError(1)
Return "-1.#IND"
EndIf
$n=UBound($vVar1)
For $i=0 To $n-1
$iSum+=$vVar1[$i]
Next
Return $iSum/$n
Else
Return $vVar1
EndIf
EndIf
EndFunc
; #FUNCTION# ==================================================================
; Name...........: _gm
; Description ...: Średnia geometryczna (The geometric mean)
; Syntax.........: _gm($var1[, $var2])
; : _gm($array)
; Parameters ....: Dwie liczby rzeczywiste dodatnie (Two positive real numbers)
; : Jednowymiarowa tablica liczb dodatnich
; (One-dimensional array of positive numbers)
; Return values .: Success - Średnia geometryczna dwu liczb, lub elementów tablicy
; (The geometric mean of two numbers, or elements of the array)
; Failure - "-1.#IND" - tablica wielowymiarowa, lub występuje liczba <=0
; @error=1 - tablica wielowymiarowa (multidimensional array)
; @error=2 - występuje liczba <=0 (by a number <= 0)
Func _gm ($vVar1, $vVar2=False)
Local $i, $n, $il=1
If @NumParams=2 Then
If $vVar1>0 And $vVar2>0 Then
Return Sqrt($vVar1*$vVar2)
Else
SetError(2)
Return "-1.#IND"
EndIf
EndIf
If @NumParams=1 Then
If IsArray($vVar1) Then
If UBound($vVar1,0)<>1 Then
SetError(1)
Return "-1.#IND"
EndIf
$n=UBound($vVar1)
For $i=0 To $n-1
If $vVar1[$i]<=0 Then
SetError(2)
Return "-1.#IND"
Else
$il*=$vVar1[$i]
EndIf
Next
Return $il^(1/$n)
Else
If $vVar1>0 Then
Return $vVar1
Else
SetError(2)
Return "-1.#IND"
EndIf
EndIf
EndIf
EndFunc
; #FUNCTION# ==================================================================
; Name...........: _log10
; Description ...: Logarytm dziesiętny (Decimal logarithm)
; Syntax.........: _log10($var)
; Parameters ....: Liczba rzeczywista dodatnia (Positive real number)
; Return values .: Success - Logarytm dziesiętny (Decimal logarithm)
; Failure - "-1.#IND" - $var <= 0
; @error=1
Func _log10 ($iVar)
If $iVar>0 Then Return Log($iVar)/Log(10)
SetError(1)
Return "-1.#IND"
EndFunc
; #FUNCTION# ==================================================================
; Name...........: _logA
; Description ...: Logarytm o dowolnej podstawie (Logarithm of any basis)
; Syntax.........: _logA($var, $base)
; Parameters ....: Liczby rzeczywiste dodatnie (Positive real numbers)
; Return values .: Success - Logarytm o dowolnej podstawie (The logarithm of any base)
; Failure - "-1.#IND" - $var <= 0 or $base <= 0 or $base = 1
; @error=1
Func _logA ($iVar, $iBase)
If $iVar>0 And $iBase>0 And $iBase<>1 Then Return Log($iVar)/Log($iBase)
SetError(1)
Return "-1.#IND"
EndFunc
; #FUNCTION# ==================================================================
; Name...........: _sinh
; Description ...: Sinus hiperboliczny (Hyperbolic sine)
; Syntax.........: _sinh($var)
; Parameters ....: Liczba rzeczywista (Real number)
; Return values .: Sinus hiperboliczny (hyperbolic sine)
Func _sinh ($iVar)
Return (Exp($iVar)- Exp(-$iVar))/2
EndFunc
; #FUNCTION# ==================================================================
; Name...........: _cosh
; Description ...: Cosinus hiperboliczny (Hyperbolic cosine)
; Syntax.........: _cosh($var)
; Parameters ....: Liczba rzeczywista (Real number)
; Return values .: Cosinus hiperboliczny (hyperbolic cosine)
Func _cosh ($iVar)
Return (Exp($iVar)+ Exp(-$iVar))/2
EndFunc
; #FUNCTION# ==================================================================
; Name...........: _QRoots
; Description ...: Pierwiastki równania kwadratowego a*x^2 + b*x + c
; (Roots of a quadratic equation)
; Syntax.........: _QRoots($a, $b, $c)
; Parameters ....: Liczbay rzeczywiste (Real numbers)
; Return values .: 3-elementawa tablica wyników (Three-element array results)
; $res[0] - ilość pierwiastków (Number of roots)
; $res[1] - wartość 1 pierwiastka lub "-1.#IND" gdy nie ma pierwiastków
; $res[2] - wartość 2 pierwiastka lub "-1.#IND" gdy nie ma pierwiastków
; $res[2]=$res[1] if $res[0]=1
Func _QRoots ($iA, $iB, $iC)
Local $iDelta, $aRes[3]=[0,"-1.#IND","-1.#IND"]
$iDelta=$iB^2-4*$iA*$iC
Select
Case $iDelta=0
$aRes[0]=1
$aRes[1]=-$iB/(2*$iA)
$aRes[2]=$aRes[1]
Case $iDelta>0
$aRes[0]=2
$aRes[1]=(-$iB-Sqrt($iDelta))/(2*$iA)
$aRes[2]=(-$iB+Sqrt($IDelta))/(2*$iA)
EndSelect
Return $aRes
EndFunc
; #FUNCTION# ==================================================================
; Name...........: _factorial
; Description ...: Silnia (Factorial)
; Syntax.........: _factorial($var)
; Parameters ....: Liczba naturalna 0-170 (Natural number)
; Return values .: Success - Silnia (Factorial)
; Failure - "-1.#IND"
; @error=1 - zły parametr (bad parameter)
; @error=2 - przekroczony zakres (range exceeded)
Func _factorial($iVar)
If $iVar<0 Or (Not IsInt($iVar)) Then
SetError(1)
Return "-1.#IND"
EndIf
If $iVar>170 Then
SetError(2)
Return "-1.#IND"
EndIf
If $iVar=0 Then Return 1.0
Return $iVar*_factorial($iVar-1)
EndFunc
; #FUNCTION# ==================================================================
; Name...........: _combination
; Description ...: Kombinacja (Combination)
; Syntax.........: _combination($k, $n)
; Parameters ....: Liczby naturalne 0-170 (Natural numbers)
; Return values .: Success - Kombinacja (Combination)
; Failure - "-1.#IND"
; @error=1
Func _combination($iK, $iN)
Local $iFk=_factorial($iK), $iFn=_factorial($iN), $iFnk=_factorial($iN-$iK)
If $iFk="-1.#IND" Or $iFn="-1.#IND" Or $iFnk="-1.#IND" Then
SetError(1)
Return "-1.#IND"
EndIf
Return $iFn/($iFk*$iFnk)
EndFunc
; #FUNCTION# ==================================================================
; Name...........: _combinationWR
; Description ...: Kombinacja z powtórzeniami (Combination with repetition)
; Syntax.........: _combinationWR($k, $n)
; Parameters ....: Liczby naturalne 0-170 (Natural numbers)
; Return values .: Success - Kombinacja (Combination)
; Failure - "-1.#IND"
; @error=1
Func _combinationWR($iK, $iN)
Local $iFk=_factorial($iK), $iFkn1=_factorial($iK+$iN-1), $iFn1=_factorial($iN-1)
If $iFk="-1.#IND" Or $iFkn1="-1.#IND" Or $iFn1="-1.#IND" Then
SetError(1)
Return "-1.#IND"
EndIf
Return $iFkn1/($iFk*$iFn1)
EndFunc
; #FUNCTION# ==================================================================
; Name...........: _variation
; Description ...: Wariacja (Variation)
; Syntax.........: _variation($k, $n)
; Parameters ....: Liczby naturalne 0-170 (Natural numbers)
; Return values .: Success - Wariacja (Variation)
; Failure - "-1.#IND"
; @error=1
Func _variation($iK, $iN)
Local $iFn=_factorial($iN), $iFnk=_factorial($iN-$iK)
If $iFn="-1.#IND" Or $iFnk="-1.#IND" Then
SetError(1)
Return "-1.#IND"
EndIf
Return $iFn/$iFnk
EndFunc
; #FUNCTION# ==================================================================
; Name...........: _variationWR
; Description ...: Wariacja z powtórzeniami (Variation with repetition)
; Syntax.........: _variationWR($k, $n)
; Parameters ....: Liczby naturalne 0-170 (Natural numbers)
; Return values .: Success - Wariacja z powtórzeniami (Variation with repetition)
; Failure - "-1.#IND"
; @error=1
Func _variationWR($iK, $iN)
If $iK<0 Or (Not IsInt($iK)) Or $iN<0 Or (Not IsInt($iN)) Then
SetError(1)
Return "-1.#IND"
EndIf
Return $iN^$iK
EndFunc
; #FUNCTION# ==================================================================
; Name...........: _permutation
; Description ...: Permutacja (Permutation)
; Syntax.........: _permutation($n)
; : _permutation($array) - permutacja z powtórzeniami
; (Permutation with repetition)
; Parameters ....: Liczba naturalna 0-170 (Natural number)
; : Jednowymiarowa tablica liczb naturalnych
; (One-dimensional array of natural numbers)
; Return values .: Success - Permutacja (Permutation)
; Failure - "-1.#IND"
; @error=1
Func _permutation($vVar)
Local $iPer, $a, $f, $i, $m=1, $s=0
If IsArray($vVar) Then
$a=UBound($vVar)
If UBound($vVar,0)>1 Then
SetError(1)
Return "-1.#IND"
EndIf
If UBound($vVar)>1 Then
For $i=1 To $a-1
$f=_factorial($vVar[$i])
If $f="-1.#IND" Then
SetError(1)
Return "-1.#IND"
EndIf
$m*=$f
$s+=$vVar[$i]
Next
If $s>$vVar[0] Then
SetError(1)
Return "-1.#IND"
EndIf
$f=_factorial($vVar[0])
If $f="-1.#IND" Then
SetError(1)
Return "-1.#IND"
EndIf
$iPer=$f/$m
Else
$iPer=_factorial($vVar[0])
EndIf
Else
$iPer=_factorial($vVar)
EndIf
If $iPer="-1.#IND" Then
SetError(1)
EndIf
Return $iPer
EndFunc
; #FUNCTION# ==================================================================
; Name...........: _Bin
; Description ...: Zamiana wyrażenia na string liczby binarnej
; (Replacing the expression for the string of binary number)
; Syntax.........: _Bin($var, $len)
; Parameters ....: $var - liczba naturalna (Natural number)
; Return values .: Success - string liczby binarnej (string of binary number)
; Failure - "-1.#IND" - parametr ujemny (negative parameter)
; @error=1
Func _Bin($iVar)
Local $sBin=""
If $iVar<0 Then
SetError(1)
Return "-1.#IND"
EndIf
Do
If Mod($iVar,2)=0 Then
$iVar/=2
$sBin="0"&$sBin
Else
$iVar=($iVar-1)/2
$sBin="1"&$sBin
EndIf
Until $iVar=0
Return $sBin
EndFunc
; #FUNCTION# ==================================================================
; Name...........: _BinToDec
; Description ...: Zamienia string liczby binarnej na liczbę dziesiętną
; (Converts binary number string to a decimal number)
; Syntax.........: _BinToDec($bin)
; Parameters ....: $bin - string liczby binarnej (string of binary number)
; Return values .: Success - liczba dziesiętna
; Failure - "-1.#IND" - zawiera znak inny niż 0 lub 1
; (contains a character other than 0 or 1)
; @error=1
Func _BinToDec($sBin)
Local $iLen=StringLen($sBin), $iDec=0, $i, $j, $a
For $i=$iLen to 1 Step -1
$j=$iLen-$i
$a=StringMid($sBin,$i,1)
If $a<>"0" And $a<>1 Then
SetError(1)
Return "-1.#IND"
EndIf
$iDec+=Number($a)*2^$j
Next
Return $iDec
EndFunc
Przykład programu testującego bibliotekę UDF (bibliteka powinna mieć nazwę math+.au3):
#include"Math+.au3"
MsgBox (0,"Max:",_max(1,2.2))
MsgBox (0,"Min:",_min(1,2.2))
MsgBox (0,"Sign",_sign(-17.4))
MsgBox (0,"Średnia arytmetyczna:",_am(1,2))
MsgBox (0,"Średnia arytmetyczna:",_am(1))
Dim $array[5]=[1,2,-3,4,-5.9]
MsgBox (0,"Średnia arytmetyczna:",_am($array)&@LF&@error)
Dim $array[2][2]=[[1,2],[3,4]]
MsgBox (0,"Średnia arytmetyczna:",_am($array)&@LF&@error)
Dim $array[5]=[1,2,3,4,5]
MsgBox (0,"Średnia geometyczna:",_gm($array)&@LF&@error)
MsgBox (0,"Średnia geometyczna:",_gm(2)&@LF&@error)
MsgBox (0,"Średnia geometyczna:",_gm(-1)&@LF&@error)
MsgBox (0,"Średnia geometyczna:",_gm(2, 3)&@LF&@error)
MsgBox (0,"Logarytm dziesiętny:",_log10(100))
MsgBox (0,"Logarytm o dowolnej podstawie:",_logA(8, 2))
MsgBox (0,"Sinus hiperboliczny:",_sinh(-2))
$t=_QRoots(1,2,1)
MsgBox (0,"Pierwiastki równania kwadratowego",$t[0]&@LF&$t[1]&@LF&$t[2])
MsgBox (0,"Silnia:",_factorial(10)&@LF&@error)
MsgBox (0,"Kombinacja:",_combination(6, 49)&@LF&@error)
MsgBox (0,"Kombinacja z powtórzeniami:",_combinationWR(6, 49)&@LF&@error)
MsgBox (0,"Permutacja:",_permutation(4)&@LF&@error)
Dim $array[3]=[4,2,2]
MsgBox (0,"Permutacja:",_permutation($array)&@LF&@error)
MsgBox (0,"Liczba binarna:",_Bin(666)&@LF&@error)
MsgBox (0,"Liczba binarna:",_Bin(-2)&@LF&@error)
MsgBox (0,"BIN>DEC:",_BinToDec(10)&@LF&@error)
MsgBox (0,"BIN>DEC:",_BinToDec(12)&@LF&@error)
Korzystanie z bibliotek DLL
[edytuj]1. W oparciu o funkcję GUICtrlCreateInput napisać funkcję umożliwiającą wprowadzanie stringów określonego typu, np.:liczby rzeczywiste i całkowite, szesnastkowe, ósemkowe, dwójkowe, itp.
Ponadto używając funkcji systemowych wywoływanych przez DllCall(), umożliwić nawigację między polami INPUT klawiszami ENTER oraz strzałka w górę i w dół.
Stworzoną funkcję użyj w prostym skrypcie demonstracyjnym.
Zadanie jest rozwinięciem zadania z rozdziału GUI. Została zmieniona i rozbudowana składnie funkcji, ponadto dodano część obsługującą klawisze nawigacyjne.
Rozpoznanie użycia dodatkowych klawiszy nawigacyjnych uzyskano za pomocą funkcji systemowej GetAsyncKeyState z biblioteki "user32.dll".
Jej składnia wygląda następująco:
SHORT WINAPI GetAsyncKeyState( __in int vKey );
Funkcja przyjmuje jeden parametr typu int, który jest kodem sprawdzanego klawisza.
Wartość zwracana jest >0 gdy klawisz został wciśnięty.
Kody sprawdzanych klawiszy to (szesnastkowo):
ENTER - 0x0d
strzałka w dół - 0x28
strzałka w górę - 0x26
Przykładowe rozwiązanie:
#include <GUIConstantsEx.au3>
$HWin = GUICreate("Wprowadź znaki:",380,200,-1,250)
GUICtrlCreateLabel("Dowolne znaki:", 10, 5)
$hF1 = GUICtrlCreateInput("", 155, 5, 200, 20,0)
GUICtrlCreateLabel("Liczba rzeczywista:", 10, 35)
$hF2 = GUICtrlCreateInput("", 155, 35, 200, 20,2)
GUICtrlCreateLabel("Liczba całkowita dodatnia i 0:", 10, 65)
$hF3 = GUICtrlCreateInput("", 155, 65, 200, 20,2)
GUICtrlCreateLabel("Liczbe szesnastkowa:", 10, 95)
$hF4 = GUICtrlCreateInput("", 155, 95, 200, 20,2)
$hBtn = GUICtrlCreateButton("Ok", 170, 160, 60, 20)
GUISetState()
Do
$msg=GUIGetMsg()
$sL1 = _GUICtrlInputRead($hF1, "", "", "begin", $hF4)
$sL2 = _GUICtrlInputRead($hF2, "", "R")
$sL3 = _GUICtrlInputRead($hF3, "", "I+")
$sL4 = _GUICtrlInputRead($hF4, "", "X", "end", $hF1)
Until $msg = $GUI_EVENT_CLOSE Or $msg = $hBtn
MsgBox(0, "Test:", "Wprowadziłeś: "&@LF&@LF&$sL1&@LF&$sL2&@LF&$sL3&@LF&$sL4, 5)
#cs=====================================================================
Funkcja umożliwia określenie jakiego typu string ma być
akceptowany przez okienko INPUT. Umożliwia wprowadzanie tylko takich
znaków, które pasują do zadanego typu stringu.
Ponadto umożliwia przemieszczanie się po okienkach INPUT za pomocą
klawiszów ENTER, strzalka w górę i w dół
Wartosć zwracana - prawidłowy wprowadzony w okienku łańcuch.
Składnia:
---------
_GUICtrlInputRead ( $hIDCtrl, [ $hWin [, $sOp [, $sPos [, $hJump ]]]] )
Parametry:
----------
$hIDCtrl - ID kontrolki (zwracane przez GUICtrlCreateInput)
$hWin - uchwyt do okna GUI, lub jego nazwa,
domyślna wartość "" oznacza to samo co "[ACTIVE]"
$sOp - rodzaj wprowadzanego stringu
--------------------------------------------------------------
"" - dowolne znaki (wartość domyślna)
"R" - liczba rzeczywista
"R+" - liczby rzeczywiste dodatnie i 0
"I" - liczby całkowite
"I+" - liczby całkowite dodatnie i 0
"X" - liczba heksadecymalna
"O" - liczba ósemkowa
"B" - liczba dwójkowa
"A" - tylko litery (także polskie)
"A+" - tylko wielkie litery
"A-" - tylko małe litery
dowolna inna wartość jest traktowana jako wyrazenie regularne
$sPos - pozycja kontrolki
--------------------------------------------------------------
"" - wewnętrzne, wartość domyślna
"begin" - początkowe
"end" - końcowe
$hJump - ID kontrolki do której należy przeskoczyć po wyjści poza początek
lub koniec, tylko dla $sPos="begin" i $sPos="end"
#ce;===================================================================
Func _GUICtrlInputRead($hIDCtrl, $hWin="", $sOp="", $sPos="", $hJump=0)
Local $sStr, $sWR, $hCtrl
Static $aStr1[99]
Switch $sOp
Case Default, ""
$sWR=".*"
Case "R", "r"
$sWR="^-?\d*\.?\d*$"
Case "R+","r+"
$sWR="^\d*\.?\d*$"
Case "I","i"
$sWR="^-?\d*$"
Case "I+","i+"
$sWR="^\d*$"
Case "X","x"
$sWR="^[0-9a-fA-F]*$"
Case "O","o"
$sWR="^[0-7]*$"
Case "B","b"
$sWR="^[01]*$"
Case "A","a"
$sWR="^(?i)[a-ząęćłńóśżźĄĆĘŁŃÓŚŻŹ ]*$"
Case "A+","a+"
$sWR="^[A-ZĄĆĘŁŃÓŚŻŹ ]*$"
Case "A-","a-"
$sWR="^[a-ząęćłńóśżź ]*$"
Case Else
$sWR=$sOp
EndSwitch
$sStr = GUICtrlRead($hIDCtrl)
If StringRegExp($sStr, $sWR) Then
$aStr1[$hIDCtrl] = $sStr
Else
GUICtrlSetData($hIDCtrl, $aStr1[$hIDCtrl])
EndIf
;---------obsłga klawiszy nawigacyjnych----------
If $hWin = "" Or $hWin = Default Then $hWin = "[ACTIVE]"
$hCtrl = ControlGetHandle($hWin,"", $hIDCtrl)
If ControlGetHandle($hWin, "", ControlGetFocus($hWin)) = $hCtrl Then
If DllCall("user32.dll", "short", "GetAsyncKeyState", "int", 0x0d)[0] Then
Send("{TAB}")
Sleep(300)
EndIf
If DllCall("user32.dll", "short", "GetAsyncKeyState", "int", 0x28)[0] Then
Send("{TAB}")
If $hJump>0 And $sPos = "end" Then ControlFocus($HWin, "", $hJump)
Sleep(300)
EndIf
If DllCall("user32.dll", "short", "GetAsyncKeyState", "int", 0x26)[0] Then
Send("+{TAB}")
If $hJump>0 And $sPos = "begin" Then ControlFocus($hWin, "", $hJump)
Sleep(300)
EndIf
EndIf
;-----------------------------------------------
Return $sStr
EndFunc
Konsola tekstowa
[edytuj]1. Napisać skrypt umożliwiający uruchamiane w trybie interakcji poleceń i skryptów napisanych w języku interpretera poleceń "cmd.exe". Wyświetlanie wyników i komunikatów błędów w MsgBox.
Przykładowe rozwiązanie:
#include <Constants.au3>
#include <GUIConstantsEx.au3>
GUICreate("Edytor", 300, 600, 800, 250)
$hEdit = GUICtrlCreateEdit("", 10, 10, 280, 500)
$hStart = GUICtrlCreateButton("Wykonać", 10, 560, 100)
$hExit = GUICtrlCreateButton("Rezygnacja", 190, 560, 100)
GUISetState()
Do
Do
$msg = GUIGetMsg()
If $msg = $GUI_EVENT_CLOSE Or $msg=$hExit Then Exit
Until $msg = $hStart
$hID = Run("cmd.exe ", "", "", $STDERR_CHILD + $STDOUT_CHILD + $STDIN_CHILD)
$sMes = ""
$sErrmes = ""
$sCode = GUICtrlRead($hEdit)
If StringRight($sCode, 1) <> @LF Then $sCode &= @LF
StdinWrite($hID,$sCode)
StdinWrite($hID)
Do
$sMes &= StdoutRead($hID)
Until @error
Do
$sErrmes &= StderrRead($hID)
Until @error
If $sErrmes <> "" Then
MsgBox(0, "Błąd:", $sErrmes)
Else
MsgBox(0, "Wynik:", $sMes)
EndIf
Until False