Visual Basic 6 - Zmienne i stałe
Zmienne |
Typy danych |
Typy użytkownika |
Zasięg i czas życia zmiennych |
Przesłanianie zmiennych |
Zmienne statyczne |
Tablice |
Tablice dynamiczne |
Stałe |
Konwencje nazw zmiennych i stałych
Jak w każdym języku programowania, tak i w Visual Basic używa się zmiennych do czasowego przechowywania różnych wartości podczas pracy programu. Każda zmienna posiada nazwę - słowo poprzez które odwołujemy się do jej zawartości - i określony typ, który determinuje, jaki rodzaj danych może być w zmiennej przechowywany. Możesz traktować zmienną jako miejsce w pamięci komputera do przechowywania nieznanych w momencie tworzenia programu wartości. Pozwala to na wykonywanie dowolnych obliczeń na wartościach, które pojawią się dopiero po uruchomieniu programu i mogą być za każdym razem inne. Zapisywanie i odczytywanie wartości zmiennych Do zmiennej można przypisać wartość, aby wykonać na niej jakieś obliczenia i wynik przypisać również do zmiennej: x = 10 ' do zmiennej x przypisano wartość 10 x = x + 1 ' wartość zmiennej x została powiększona o 1Zauważ, że znak równości jest operatorem przypisania. Deklarowanie zmiennych Deklaracja zmiennej jest poinformowaniem programu o jej istnieniu. Zmienne deklarujemy poleceniem Dim podając co najmniej nazwę deklarowanej zmiennej: Dim NazwaZmiennej [As typ] Zmienne zadeklarowane wewnątrz procedury lub funkcji istnieją tylko tak długo, jak długo wykonywana jest procedura lub funkcja. Po ich zakończeniu zmienne są usuwane z pamięci. Dlatego też takie zmienne nazywamy lokalnymi: zmienne i ich wartości nie są dostępne w żadnej innej procedurze lub funkcji. Dzięki temu można w różnych procedurach używać zmiennych o identycznych nazwach bez obawy, ze zmiana wartości zmiennej w jednej procedurze będzie miała wpływ na zmienną o identycznej nazwie w innej procedurze.
Istnieją również inne metody deklarowania zmiennych:
Domyślna (Implicit) deklaracja Visual Basic pozwals na używanie zmiennych bez ich wcześniejszego deklarowania. Np.: Function Pierwiastek(x) Temp = Abs(x) Pierwiastek = Sqr(Temp) End FunctionVisual Basic automatycznie tworzy zmienną o nazwie, której użyjesz. Ponieważ jednak nie jest znany typ takiej zmiennej, to automatycznie przypisywany jest jej typ Variant, który wymaga dużo pamięci i znacznie zwalnia pracę aplikacji. Inną nieprzyjemną konsekwencją takiego używania zmiennych jest możliwość pomyłki literowej przy pisaniu programu. Zobacz kolejny przykład: Function Pierwiastek(x) Temp = Abs(x) Pierwiastek = Sqr(Tmp) End Function Na pierwszy rzut oka niczym nie różni się od poprzedniego. Jednak użyte tu zmienne Temp i Tmp. Kompilator nie domyśli się, że chodzi nam o tą samą zmienna i wyniku ta funkcja zawsze zwróci 0, gdyż kompilator utworzy dwie różne zmienne. Jawna (Explicit) deklaracja Aby zapobiec tego typu "wypadkom" można wymusić sprawdzanie przez kompilator, czy każda użyta zmienna została wcześniej zadeklarowana. Należy w tym celu każdy moduł kodu aplikacji rozpocząć od polecenia: Option ExplicitNasza przykładowa funkcja wyglądałaby wtedy tak: Function Pierwiastek(x) Dim Temp as Double Temp = Abs(x) Pierwiastek = Sqr(Tmp) End FunctionPrzy takim zapisie i użyciu polecenia Option Explicit brak deklaracji zmiennej Tmp spowoduje wyświetlenie komunikatu o nie zadeklarowanej zmiennej. Polecenie Option Explicit musi być użyte w każdym module, w którym chcemy mieć kontrolę deklaracji zmiennych. Musi ono być użyte na początku modułu, jeszcze przed pierwszą procedurą, funkcją lub deklaracją zmiennych. Typ zmiennej determinuje jakiego typu dane mogą być w niej przechowywane. Domyślnym - nie wymagającym deklaracji typem danych jest Variant. Jest to typ-kameleon: może przechowywać dane każdego typu. Nie wymaga również konwersji podczas przypisywania: Visual Basic automatycznie wykonuje konieczną konwersję. Odbywa się to jednak kosztem ilości pamięci i czasu wykonania. Znając rodzaj danych przechowywanych w zmiennej bardziej optymalnym rozwiązaniem jest zadeklarowanie odpowiedniego jej typu. Można również deklarować tablice o elementach dowolnego typu podstawowego. Deklarowanie zmiennych ze zdefiniowanym typem Zmienne deklarujemy instrukcją: Dim, Private, Public lub Static podając po niej nazwę zmiennej słowo kluczowe As i po nim typ zmiennej. Możemy w jednej instrukcji deklarować wiele zmiennych, ale każda musi mieć indywidualnie zdefiniowany typ. Np.:Private i As Integer ' zmienna i typu całkowitego Dim d As Double ' zmienna d typu rzeczywistego Static Imię As String ' zmienna Imię typu łańcuchowego Public Cena As Currency ' zmienna Cena typu walutowego Private a As Integer, s As Single ' zmienna a - całkowita i s - rzeczywista Private data As Date, Wart As Currency ' zmienna data - data i Wart - walutowa Private x, y As Integer ' zmienna x - Variant i y - całkowitaZwróć uwagę na ostatni przykład: zmienna x bez zdefiniowanego typu ma automatycznie przypisany typ Variant.Jest to istotna różnica w stosunku do większości innych języków programowania. Deklarowanie zmiennych łańcuchowych Zmienne typu String służące do przechowywania łańcuchów znakowych możemy deklarować na 2 sposoby.Domyślnie - podając tylko typ String - tworzymy zmienną, w której możemy przechowywać praktycznie łańcuch znaków nieograniczonej długości. Możemy jednak zadeklarować łańcuch znaków o stałej długości: String * długośćNp.: Dim Nazwisko As String * 25W tym przypadku krótsze łańcuchy znaków będą uzupełnione spacjami do podanej długości, a dłuższe zostaną obcięte z prawej strony za 25 znakiem. Łańcuchy stałej długości można deklarować w modułach jako Public lub Private. W Formach i klasach muszą być zadeklarowane jako Private. Wymiana łańcuchów i numeryków Do zmiennej typu String można zawsze przypisać wartość zmiennej typu numerycznego. Visual Basic automatycznie dokona poprawnej konwersji typu.Możliwe jest również odwrotne przypisanie, ale tylko wtedy, gdy zmienna typu String rzeczywiście zawiera poprawną wartość numeryczną. W innym wypadku powstanie błąd wykonania (run-time error). Np.:Dim intX As Integer Dim strY As String strY = "100.23" intX = strY ' przypisanie łańcucha do zmiennej numerycznej List1.AddItem Cos(strY) ' dodanie do ListBox'a cosinusa obliczonego z napisu strY = Cos(strY) ' przypisanie do łańcucha cosinusa obliczonego z napisu Wartość Empty Wartość Empty mogą posiadać tylko zmienne typu Variant. Nie posiada jej żaden inny typ danych. Wartość Empty jest czymś innym niż 0 lub pusty łańcuch znaków (""): oznacza, że zmienna od momentu zadeklarowania nie miała przypisanej jakiejkolwiek wartości. Może ona służyć do sprawdzenia, czy zmienna została zainicjowana.Użycie pustej (Empty) zmiennej typu Variant w wyrażeniu spowoduje, że będzie ona traktowana jako 0 lub pusty łańcuch znaków ("") zależnie od typu wyrażenia. Zmienna typu Variant ma wartość Empty, tak długo, aż nie przypiszemy do niej innej wartości (włączając w to 0, "" i Null). Można do zmiennej ponownie przypisać wartość Empty. Wartość Null Zmienna typu Variant może przyjmować specjalna wartość: Null. Null jest wartością używana w bazach danych dla oznaczenia nieznanej lub brakującej wartości pola. Wartość Null posiada kilka unikalnych cech:
Podstawowe typy danych Poniższa tabela przedstawia podstawowe typy danych, ich opisy i zakresy danych, które mogą przechowywać, wielkości pamięci jakiej używają i konwencjonalne przedrostki deklaracji typu.
Uwagi:
Tworzenie własnych typów danych Deklarowanie typu użytkownika Można stworzyć kombinację zmiennych różnych typów jako typ danych użytkownika (ang. user-defined type). Stanowi to odpowiednik typu rekordowego z Pascala lub struktury z C/C++. Może to być wygodne do przechowywania wielu powiązanych z sobą informacji w jednej zmiennej.Własne typy danych deklarujemy instrukcją Type, która musi być umieszczona w części deklaracyjnej modułu (przed wszystkimi procedurami i funkcjami). Własne typy możemy deklarować jako prywatne lub publiczne za pomocą odpowiednio klauzul: Private i Public. Np.: Private Type MójTyp lub Public Type MójTypDeklaracja typu kończy się klauzulą End Type. Tak mogłaby wyglądać deklaracja typu zawierającego podstawowe dane osobowe w jakiejś kartotece: Private Type Osoba Nazwisko As String * 25 Imię As Srting * 15 DataUrodzenia As Date End Type Deklarowanie zmiennej własnego typu Po stworzeniu własnego typu możemy go wykorzystać do tworzenia zmiennych. Należy pamiętać, że sama deklaracja typu nie tworzy jeszcze żadnej zmiennej. Zmienne własnych typów - jak wszystkie inne - możemy deklarować jako lokalne, prywatne wewnątrz modułu lub publiczne. Możemy również tworzyć tablice własnego typu. Np.:Dim Ja As Osoba, Ty As Osoba, My (2) As OsobaPoniższa tabela pokazuje jakiego rodzaju typy i ich zmienne możemy tworzyć zależnie od miejsca, gdzie definiujemy własny typ danych:
Praca ze zmiennymi własnego typu Korzystnie ze zmiennych zdefiniowanych przez siebie typów jest podobna do korzystania z właściwości obiektów: nazwę zmiennej od jej poszczególnych elementów oddzielamy kropką. Np:Ja.Imię = "Władysław" If Ty.DataUrodzenia > #1/1/2000# ThenJeżeli mamy kilka zmiennych własnego typu, to wymiana danych między nimi może odbywać się przez przypisanie kolejnych elementów jednej zmiennej do drugiej lub przez przypisanie całej zmiennej. Np: Ja.Imię = Ty.Imię Ja.Nazwisko = Ty.Nazwisko Ja.DataUrodzenia = Ty.DataUrodzenia lub krócej Ja = Ty Typ użytkownika zawierający tablice Definiowany przez użytkownika typ danych może zawierać również tablice. Np:Type SystemInfo CPU As Variant Memory As Long DiskDrives (25) As String ' tablica o 25 elementach typu String VideoColors As Integer End TypeTablice w definiowanym przez użytkownika typie danych mogą też być dynamiczne. Np: Type SystemInfo CPU As Variant Memory As Long DiskDrives () As String ' tablica dynamiczna VideoColors As Integer End TypeDostęp do tablic w zmiennych typu użytkownika jest podobna do korzystania z właściwości obiektów: Dim MySystem As SystemInfo ReDim MySystem.DiskDrives(3) MySystem.DiskDrives(0) = "1.44 MB"Jak już wspomnieliśmy, można również tworzyć tablice własnego typu. Sposób odwoływania się do jej poszczególnych elementów jest analogiczny: Dim Systems(100) As SystemInfo Systems(5).CPU = "386SX" Systems(5).DiskDrives(2) = "100M SCSI" Zmienne typu użytkownika jako parametry Zmienne typów zdefiniowanych przez użytkownika mogą być przekazywane jako parametry do innych procedur lub funkcji na takich samych zasadach, jak wszystkie inne zmienne. Np.:Sub SystemData (SystemX As SystemInfo) SystemX.CPU = lstCPU.Text SystemX.Memory = txtMemory.Text SystemX.DiskDrives = cmbDrive.Text SystemX.VideoColors = cmbVideo.Listindex End SubUwaga: przekazanie zmiennej typu użytkownika wewnątrz modułu formularza wymaga, aby procedura była zadeklarowana jako prywatna. Zmienne typów zdefiniowanych przez użytkownika mogą być przekazywane jako parametry do procedur i zwracane przez funkcje. Zmienne tego typu zawsze przekazywane są przez referencję. Oznacza to, że zmiana wartości parametru wewnątrz procedury lub funkcji zostaje w niej zapamiętana. Widać to w powyższym przykładzie. Ponieważ zmienne typu użytkownika zawsze są przekazywane przez referencję, to wymaga to każdorazowego przekazania wszystkich danych do i z procedury/funkcji. Jeżeli zmienna zawiera duże tablice może być to dość czasochłonne (zwłaszcza przy aplikacjach sieciowych). Często lepszym rozwiązaniem jest wydzielenie z typu tylko niezbędnych danych i przekazanie ich do wywoływanej procedury: może to znacznie przyspieszyć pracę programu. Zagnieżdżanie struktur danych Zagnieżdżanie może być dowolnie skomplikowane. Wynika z tego, ze typ zdefiniowany przez użytkownika może zawierać inny typ użytkownika, itd. Widać to w poniższym przykładzie:Type Dysk Typ As String Wielkość As Long End Type Type SystemInfo CPU As Variant Memory As Long Dyski(26) As Dysk End Type Dim Systems(100) As SystemInfo ... Systems(1).Dyski(0).Typ = "FDD"Ze względów praktycznych - żeby łatwiej było analizować program i śledzić złożoność struktur - dobrą metoda jest umieszczenie wszystkich definicji własnych typów w kodzie jednego modułu. Może to znacznie ułatwić wykrywanie ewentualnych błędów oraz konieczność wprowadzenia zmian do aplikacji. Miejsce oraz sposób deklaracji zmiennej decydują o tym, która część kody będzie tą zmienna "widziała" (mogła się do niej odwoływać), a która nie. Deklarując zmienną wewnątrz procedury powodujemy, że będzie widziana tylko w tej procedurze: zostanie utworzona i zainicjowana domyślną wartością w momencie wywołania procedury, a po zakończeniu działania procedury zostanie usunięta z pamięci. Nie będzie również widziana przez inne procedury, które z niej zostaną wywołane (chyba, że przekażemy ją do nich jako parametr). Takie zmienne nazywamy lokalnymi zmiennymi procedury. Zmienne zdefiniowane w części deklaracyjnej modułu (przed wszystkimi procedurami i funkcjami) będą widziane przez wszystkie procedury tego modułu. Są to zmienne lokalne modułu. Zmienne możemy deklarować za pomocą czterech słów kluczowych: Public, Private, Dim i Static. Decydują one o tym, gdzie zmienna będzie widziana i jak długo będzie istniała w pamięci:
Poniższa tabelka pokazuje zasięg widoczności i czas życia zmiennych w zależności od tego gdzie i jakim słowem kluczowym zostaną zadeklarowane:
Zmienne i procedury publiczne Z przesłanianiem zmiennych mamy do czynienia, gdy ta sama nazwa zmiennej zostanie użyta w różnych częściach programu i jednocześnie są (mogą być) widoczne wewnątrz jednej procedury. Ma to miejsce, gdy zadeklarujemy w różnych modułach zmienne publiczne o tej samej nazwie (choć niekoniecznie o tych samych typach) lub gdy wewnątrz procedury mamy zmienną lokalna o nazwie identycznej ze zmienna publiczną.Generalną regułą w Visual Basic'u jest wyższy priorytet zmiennych lokalnych. W pierwszym przypadku problem możemy rozwiązać podając nazwę kwalifikowana zmiennej, czyli poprzedzając ją nazwą modułu, z którego zmienną chcemy pobrać. Rozpatrzmy to przykładzie. Utwórz projekt składający się z dwóch modułów i jednego formularza. Na formularzu umieść trzy przyciski poleceń (CommandButton). Następnie zapiszemy poniższy kod: 'W module Module1: Public x As Integer ' deklaracja zmiennej publicznej Sub Test() x = 123 End Sub 'W module Module2: Public x As String ' deklaracja zmiennej publicznej Sub Test() x = "ABCDEFGH..." End Sub 'W module Form1: Public x As Date ' deklaracja zmiennej publicznej Sub Test() x = Date() End Sub ' oraz procedury obsługi kliknięcia na każdy z przycisków Private Sub Command1_Click() Module1.Test ' wywołanie procedury Test z Module1 MsgBox Module1.x ' wyświetlenie zmiennej x z Module1 End Sub Private Sub Command1_Click() Module2.Test ' wywołanie procedury Test z Module1 MsgBox Module2.x ' wyświetlenie zmiennej x z Module1 End Sub Private Sub Command1_Click() Test ' wywołanie procedury Test z Module1 MsgBox x ' wyświetlenie zmiennej x z Module1 End SubPo uruchomieniu tego programu kliknięcie na każdy z przycisków wyświetli odpowiedni komunikat: zmienną z wybranego modułu. Zwróć uwagę, że odwołanie do procedury Test() i zmiennej x z Form1 nie wymaga podania kwalifikatora. Dzieje się tak dlatego, że domyślnie wewnątrz każdego modułu widziane są jego własne, wewnętrzne zmienne. Ponieważ jest to działanie domyślne, to nie wymaga podawania żadnych kwalifikatorów. Jak widać z powyższego przykładu te same reguły dotyczą powtarzających się nazw nie tylko zmiennych, ale również procedur i funkcji. Zmienne publiczne i prywatne Pozostaje jeszcze problem przesłaniania zmiennych publicznych przez lokalne zmienne procedury. Ma to miejsce wtedy, gdy w procedurze zadeklarujemy taką samą nazwę zmiennej, jaka istnieje jako zmienna publiczna lub prywatna w całym module. W Visual Basic'u pierwszeństwo zawsze mają zmienne lokalne. Dlatego w tej sytuacji znowu musimy odwołać się do nazw kwalifikowanych, aby pobrać wartość zmiennej publicznej.Zobaczmy to na kolejnym przykładzie. Tym razem wystarczy nam sam formularz z dwoma przyciskami. Public x As Integer Private Sub Command1_Click() Dim x As Integer x = 2 MsgBox Form1.x ' wyświetlenie zmiennej modułowej End Sub Private Sub Command2_Click() Dim x As Integer x = 2 MsgBox x ' wyświetlenie zmiennej lokalnej End SubNależy przy tym pamiętać, aby zmienna modułowa była zmienną publiczna. Zadeklarowanie jej klauzulą Dim lub Private spowoduje błąd wykonania przy próbie odwołania się do nazwy kwalifikowanej Form1.x. Ten sam problem dotyczy używania nazw lokalnych o nazwach identycznych z nazwami kontrolek lub ich właściwości: nazwa lokalana zawsze będzie miała wyższy priorytet! Zobaczmy to na kolejnym przykładzie. Tym razem na formularzu umieścimy tylko pole tekstowe. Private Sub Form_Load() Text1 = "ABCD..." ' przypisanie tekstu do kontrolki Text1.Top = 1000 ' przemieszczenie kontrolki na formularzu BackColor = vbWhite ' ustawienie białego tła formularza End Sub Private Sub Form_Click() Dim Text1, BackColor Text1 = "abcd..." ' przypisanie tekstu do zmiennej lokalnej Me.Text1 = "Kontrolka" ' przypisanie tekstu do kontrolki Text1.Top = 0 ' Tutaj wystąpi błąd wykonania Me.Text1.Top = 0 ' przemieszczenie kontrolki na formularzu BackColor = 0 ' przypisanie 0 do zmiennej lokalnej Me.BackColor = 0 ' ustawienie czarnego tła formularza End Sub Nazwy zmiennych i procedur Wewnątrz modułu nie wolno używać tych samych nazw dla zmiennych i procedur. Spowoduje to powstanie błędu już na etapie kompilacji modułu. Może się zdarzyć, że nazwa zmiennej publicznej z jednego modułu będzie identyczna z nazwą publicznej procedury innego modułu. W takim przypadku zawsze musimy używać nazw kwalifikowanych, podajacych moduł, do którego zmiennej lub procedury się odwołujemy.Ponieważ przesłanianie nazw może prowadzić nieraz do nieprzewidzianych zachowań programu, dlatego dobrym zwyczajem jest unikanie powtarzających się nazw i nadawanie każdej zmiennej i procedurze publicznej nazw unikalnych. Na powtarzające się nazwy można sobie bezpiecznie pozwoliś przy lokalnych zmiennych procedur: nie grozi to praktycznie żadnymi konsekwencjami. Zmienne modułowe i publiczne istnieją przez cały czas pracy programu. Natomiast zmienne deklarowane w procedurach są tworzone w momencie jej wywołania i usuwane z pamięci zaraz po jej zakończeniu. Kolejne wywołanie procedury inicjuje jej wszystkie zmienne od nowa.W niektórych przypadkach wygodnie byłoby jednak zachować wartości lokalnych zmiennych procedury do jej kolejnego wywołania. Można to wprawdzie zastąpić zmienną publiczna albo modułową. Jednak do tego typu zmiennych mają dostęp wszystkie procedury i może się zdarzyć, że jej wartość zostanie gdzieś zmieniona. Pilnowanie tego typu zmiennych jest bardziej pracochłonne i czyni kod programu mniej czytelnym. Sposobem na zachowanie wartości zmiennych lokalnych między kolejnymi wywołaniami procedury jest zadeklarowanie ich klauzulą Static zamiast Dim. Tak zadeklarowana zmienna zachowuje swoja wartość nawet po zakończeniu procedury i usunięciu z pamięci jej innych zmiennych lokalnych. Oto przykład procedury służącej do sumowania ilości i zliczania wartości ogółem: Function Ogółem(Ile As integer) As Integer Static Razem Razem = Razem + Ile Ogółem = Razem End FunctionJeżeli chcemy, aby wszystkie zmienne procedury lub funkcji były statyczne, to możemy użyć klauzuli Static w deklaracji procedury lub funkcji. Np: Static Function Ogółem(Ile As integer) As IntegerSpowoduje to, że każda zmienna - nawet te zadeklarowane klauzulami Dim i Private - będzie zmienną statyczna. Klauzula Static może być użyta w kazdej funkcji i procedurze łącznie z procedurami obsługo zdarzeń. Np.: Private Static Sub Form_Click()Tablica jest specyficzną struktura, która pozawala za pomocą jednej nazwy odwołać się do wielu zmiennych tego samego typu. Dostęp do każdego elementu tablicy jest możliwy poprzez podanie jego indeksu (numeru kolejnego) wewnątrz tablicy. W wielu sytuacja jest to bardzo pomocne i wygodne: zmniejsza ilość zmiennych, których nazwy musimy pamiętać, pozwala zastosować pętle do wykonania operacji na wszystkich elementach tablicy. Kod programu staje się przez to znacznie krótszy, a działanie programu bardziej efektywne. Każda tablica posiada minimalny i maksymalny indeks, który musi być liczba całkowitą, a wszystkie elementy tablicy otrzymują kolejne numery między tymi indeksami. Należy pamiętać, aby nie rezerwować większych tablic, niż to jest konieczne: kompilator przydziela pamięć dla każdego elementu tablicy i tablica zarezerwowana "na wyrost" może się okazać bardzo pamięciochłonną i znacznie zwolnić działanie programu. Uwaga: tablice zmiennych deklarowane w kodzie programu są zawsze indeksowane (numerowane) w sposób ciągły. Natomiast tablice kontrolek umieszczanych na formularzu nie muszą być tak numerowane. Ich indeksy nadajemy we właściwości Index każdej kontrolki, a to nie wymaga zachowania ciągłości. Wszystkie elemeenty tablicy musza być tego samego typu. Jeżeli jednak jast to typ Variant, który pozwala na przechowywanie danych dowolnego typu, to w każdym elemencie możemy mieć inny rodzaj danych. Typ elementów tablicy może być dowolnym typem podstawowym lub zdefiniowanym przez użytkownika. W Visual Basic'u istnieją 2 typy tablic:
Tablice stałej długości Tablice - analogicznie jak wszystkie inne zmienne - deklarujemy z użyciem któregoś z słów kluczowych Public, Private, Dim lub Static. Zasięg ich widoczności i czas życia automatycznie wynika ze sposobu deklaracji.Deklarując tablicę musimy po jej nazwie podać w nawiasach okrągłych jej minimalny i maksymalny indeks. Oba indeksy muszą mieścić się w przedziale (-2 147 483 648 do 2 147 483 647) - liczba typu Long. Możemy podać w nawiasie tylko jedną liczbę: traktowana jest ona jako indeks górny, a wartość indeksu dolnego otrzymuje domyślną wartość 0. Np.: Dim Tab1(14) As Integer ' tablica o 15 elementach ' z indeksami od 0 do 14 Dim Tab2(99) As Integer ' tablica o 100 elementach ' z indeksami od 0 do 99Możemy sami zadeklarować nie tylko górny, ale i dolny indeks tworzonej tablicy. Np: Dim Tab1(1 To 10) As Integer ' tablica o 10 elementach ' z indeksami od 1 do 10 Dim Tab2(-5 To 5) As Integer ' tablica o 11 elementach ' z indeksami od -5 do 5 Tablice wielowymiarowe Czasami istnieje potrzeba zapamiętania bardziej złożonych danych, np.: oceny 25 uczniów z 10 przedmiotów. Możemy to zrobić deklarując tablice wielowymiarowe. W zasadzie ilość wymiarów tablicy jest nieograniczona. Jednak w praktyce wynika ona z ilości dostępnej pamięci, a tą tablice wykorzystują w postępie geometrycznym. Zobaczmy to przykładzie tablicy, która w każdym wymiarze ma 10 elementów typu Integer (2 bajty):Wymiarów Elementów Pamięć 1 10 20 2 100 200 3 1 000 2 000 4 10 000 20 000 5 100 000 200 000 6 1 000 000 2 000 000 7 10 000 000 20 000 000Pamiętając o tym należy z tablic wielowymiarowych korzystać, gdyż są bardzo przydatne, ale z rozsądkiem. Sposób deklarowania tablic wielowymiarowych jest analogiczny do jednowymiarowych, z tym, że kolejne wymiary w deklaracji oddzielamy przecinkiem. Zakresy indeksów w każdym wymiarze są niezależne. Oto przykład kilku różnych deklaracji tablicy dwuwymiarowej o wymiarach 10 x10, których wszystkie elementy są typu wariant: Deklaracja Indeksy 1-go wymiaru Indeksy 2-go wymiaru Dim Tab1(9, 9) 0 do 9 0 do 9 Dim Tab1(9, 1 To 10) 0 do 9 1 do 10 Dim Tab1(1 To 10, 9) 1 do 10 0 do 9 Dim Tab1(1 To 10, 1 To 10) 1 do 10 1 do 10 Dim Tab1(5 To 14, -5 To 4) 5 do 14 -5 do 4W kodzie programu do tablicy odwołujemy się podając jej nazwę oraz w nawiasach okrągłych indeks (indeksy) elementu. Regułą jest bowiem praca z pojedynczym elementem tablicy. Oto przykład procedury, która zapisuje w tablicy dwuwymiarowej tabliczkę mnożenia: Sub Tabliczka() Dim i As Integer, j As Byte Dim MatrixA(1 To 10, 1 To 10) As Byte For i = 1 To 10 For j = 1 To 10 MatrixA(i, j) = i * j Next Next End SubCzasami zdarza się, że podczas pisania programu nie wiemy, jak dużej tablice będziemy potrzebowali. Wygodnie byłoby móc ustalić wymiar tablicy dopiero podczas pracy programu. do tego służą tablice dynamiczne, których rozmiar możemy zmienić (zwiększyć lub zmniejszyć) w każdym momencie pracy programu. Alternatywnym rozwiązaniem jest rezerwowanie tablic o maksymalnym możliwym rozmiarze. Jest to jednak marnotrawienie pamięci i znaczne wydłużenie pracy programu, które - najczęściej - nie jest niczym uzasadnione. Tworzenie tablic dynamicznych Deklarowanie tablic dynamicznych jest niemal identyczne z deklarowaniem tablic stałej długości. Jedyna różnica polega na tym, że w momencie deklarowania takiej tablicy nie podajemy jej rozmiaru pozostawiając puste nawiasy okrągłe. Np.:Dim Tab() As StringJest to poprawna deklaracja tablicy, ale nie wystarcza do jej użycia. Wymaga wcześniejszego zadeklarowania jej wymiarów. Możemy z niej uczynić zarówno tablicę jedno- jak i wielowymiarową. Do zainicjowania tablicy lub późniejszego zmienienia jej wielkości służy polecenie ReDim, w którym podajemy jej rozmiar. Np.: ReDim Tab(x+5)Oczywiście polecenia ReDim możemy użyć tylko wewnątrz procedury lub funkcji, gdyż jest to instrukcja wykonywalna, ani deklaracja zmiennej. Można oczywiście instrukcja ReDim tworzyć dowolne zakresy indeksów i ilość wymiarów tablicy: Deklaracja Indeksy 1-go wymiaru Indeksy 2-go wymiaru Dim Tab1(x) As Integer 0 do x-1 brak Dim Tab2(99) As Integer 0 do 99 brak Dim Tab1(1 To 10) As Integer 1 do 10 brak Dim Tab2(-5 To 5) As Integer -5 do 5 brak Dim Tab1(x, y) 0 do x 0 do y Dim Tab1(9, 1 To 10) 0 do 9 1 do 10 Dim Tab1(1 To 10, 9) 1 do 10 0 do 9 Dim Tab1(1 To 10, 1 To 10) 1 do 10 1 do 10 Dim Tab1(5 To 14, -5 To 4) 5 do 14 -5 do 4 Zachowywanie zawartości tablicy Każda zmiana rozmiaru tablicy powoduje jej ponowne zainicjowanie, a więc utratę wszystkich zapisanych w niej danych. Można temu zapobiec używając w poleceniu zmiany wielkości tablicy klauzulo Preserve. Np.:Dim Tab() As String ... ReDim Tab(5) ' 1-sza inicjacja tablicy ... ReDim Preserve Tab(10) ' powiększenie o 5 elementów ' pierwsze 5 zachowa swoje wartościInicjując tablicę nadajemy jej elementom wartości domyślne:
W kolejnym przykładzie zwiększamy tablicę o 5 nowych elementów: ' dla tablicy o indeksie początkowym 0 ReDim Preserve Tab(UBound(Tab) + 5) lub ' dla tablicy o dowolnym indeksie początkowym ReDim Preserve Tab(UBound(Tab) - LBound(Tab) + 6)Uwaga: jeżeli używamy klauzuli Preserve w tablicach wielowymiarowych, to możemy zmienić tylko ostatni wymiar tablicy. Próba zmiany "wcześniejszych" wymiarów spowoduje błąd wykonania. Poprawną instrukcją jest zatem: ReDim Preserve Tab(UBound(Tab, 1), UBound(Tab, 2) + 10)Ale błędna: ReDim Preserve Tab(UBound(Tab, 1) + 10, UBound(Tab, 2)) Często zdarza się, że jakaś stała powtarza się bardzo często w kodzie programu lub wykonanie fragmentu kodu zależy od jakichś wartości, które wymagają zapamiętania, ale z niczym się nie kojarzą. W takich przypadkach można uczynić kod programu bardziej czytelnym i zrozumiałem używając stałych. Stała jest to symboliczna nazwa, która reprezentuje pewną wartość numeryczna, łańcuch znaków lub jakieś wyrażenie. Ponieważ nazwę stałej nadajesz sam, to łatwiej jest ją zapamiętać niż jakieś wymyślne liczby czy wyrażenia. Natomiast w trakcie kompilacji programu wszystkie nazwy stałych zastępowane są przez przypisane do nich wartości czy wyrażenia. Rozwiązanie takie posiada jeszcze inną zaletę. Jeżeli wartość stałej ulega zmianie, to wystarczy ją zmienić tylko w jednym miejscu. Nie ma potrzeby analizowania całego kodu programu i wyszukiwania wszystkich miejsc, gdzie ta wartość wystąpił. Zmiana wartości stałej spowoduje automatyczną zmianę wszystkich jej wystąpień Istnieją dwa rodzaje stałych:
Predefiniowane stałe Visual Basic i Visual Basic for Applications mają nazwy rozpoczynające się przedrostkiem vb. Stałe z innych bibliotek na ogół również posiadają przedrostki pozwalające zorientować się z jakiej biblioteki pochodzą. Ten sposób nazewnictwa ma zapobiec ewentualnym kolizją z nazwami własnymi nadawanymi przez programistę oraz nazwami stałych z różnych bibliotek dołączonych do programu. Identyczne nazwy mogłyby spowodować w programie sporo bałaganu. Aby być całkowicie pewnym, że nie nastąpi kolizja nazw, zawsze można odwoływać się do stałej z jej pełną nazwą kwalifikowaną: [NazwaBiblioteki.][NazwaModułu.]NazwaStałejJest to jednak dość pracochłonny sposób zabezpieczania się przed konfliktami nazw stałych i lepiej nadawać in rzeczywiście unikalne nazwy. Tworzenie własnych stałych Składnia deklaracji stałej jest następująca: [Public|Private] Const NazwaStałej [As typ] = wyrażenieGdzie:
Przykładowe deklaracje własnych stałych w programie: Const conPi = 3.14159265358979 Public Const conPlanet As Integer = 9 Const conData = #6/5/1979# Public Const conAutor = "Jan Kowalski" Wyrażenie po prawej stronie znaku równości jest najczęściej liczbą lub łańcuchem znaków. Może ono być jednak również wynikiem wykonania pewnych operacji lub odwołania się do innych zadeklarowanych stałych. Nie wolno jednak odwoływać się w deklaracji stałej do funkcji. Np: Const conPi2 = conPi * 2 Const conInfo = conAutor & " urodzony " & conData Należy jednak pamiętać, aby wzajemne odwołania jednej zmiennej do drugiej nie tworzyły pętli cyklicznej, gdyż spowoduje to wystąpienie błędu wykonania. Poniższy przykład pokazuje sytuację, która nie jest poprawna i nie powinna wystąpić w programie: Public Const conA = conB * 2 Public Const conB = conA / 2 Jeżeli już zdefiniowałeś stałą to możesz się do niej odwołać w dowolnym miejscu programu. Tak zapisany kod jest bardziej czytelny. Np.: SystemSłoneczny(1 To conPlanet) If x > conPi2 Then Exit Sub Zasięg widoczności stałych Deklaracja Const ma zasięg widoczności stałych i reguły identyczne jak deklaracje zmiennych:
Konwencje nazw zmiennych i stałych Każdy praktycznie program używa jakichś zmiennych. Często również własnych stałych. W małych aplikacjach nie stanowi to na ogół problemu. W dużych, gdy ilość zmiennych i stałych idzie w setki , a często w tysiące, trudno jest zapanować nad wszystkimi nazwami zmiennych i stałych. Dlatego przyjęło się używać pewnej konwencji nadawania zmiennym i stałym nazw. Ma ona ułatwić poruszanie sie w gąszczu nazw. Nie jest ona oczywiście obowiązkowa i w praktyce możesz nazywać swije zmienne w dowolny sposób. Zachowanie jednak pewnych konwencji znacznie ułatwia pisanie i testowanie oraz ewentualne zmiany w programie: kod jest czytelniejszy i łatwiejszy do zrozumienia.Przyjmując zachowanie konwencji, każdy programista może storzyć oczywiście własne. Przedstawione tutaj stanowią jednak pewien standard, choć wcale nie muszą byc bezwzglednie zachowane. Ogólny schemat nadawania nazw zmiennym można przedstawić następująco: PrzedrostekZakresu PrzedrostekTypu NazwaWłasna Gdzie:
Przedrostek zasięgu Ponieważ zmienne i stałe zawsze są widziane w jakimś określonym zasięgu programu, to dobrze jest w ich nzawie zasygnalizować z jakiego typu zmienną (stałą) mamy do czynienia. Przyjętą w tym zakresie konwencję pokazuje poniższa tabela:
Przedrostek typu Przedrostek typu to trzyznakowy łańcuch informujący o typie danych przechowywanych w zmiennej. ułatwnia to czytanie kodu oraz kontrolę nad tym, co do danej zmiennej mozemy przypisac, a czego nie. Przykęte konwencje używania przedrostków typu przedstawia poniższa tabela:
Nazwy własne Nazwy własne nie podlegają żadnym konwencjom. Należy jednak pamiętac, zę dobrym obyczajem jest nadawanie nazw, które o czymkolwiek mówia. Dotyczy to zarówno zmiennyhc, stałych jak i nazw tworzonych przez peogramistę procedur i funkcji. Zobaczmy dwa fragmenty kodu programu:'Przykład 1: Function WartośćOgółem(intIlość As Integer, curCena As Currency) Static curWartośćOgółem As Currency curWartośćOgółem = curWartośćOgółem + intIlość * curCena WartośćOgółem = curWartośćOgółem End Function 'Przykład 2: Function wo(i As Integer, c As Currency) Static o As Currency o = o + i * c wo = o End FunctionOba przykłady wykonują dokładnie to samo. Drugi z nich wymaga na pewno mniej pracy podczas pisania kodu. Jednak patrząc na pierwszy przykład od razu wiemy, o co w nim chodzi. Nie wymaga on żadnego komentarza. Drugi natomiast nic nam nie mówi. Sądzę, że sam autor takiego kodu wracając do niego po kilkutygodniowej przerwie musiałby się dobrze zastanowic, co miał na myśli pisząc te instrukcje. Pierszy kod jest na pewno bardziej pracochłonny, ale nakład pracy na pewno się opłaca.
|