Strona używa cookies (ciasteczek). Dowiedz się więcej o celu ich używania i zmianach ustawień. Korzystając ze strony wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki.    X

Godny następca C i C++, czyli programowanie w D - cz. 3: Tablice

Po dwóch poprzednich wpisach o języku programowania D przyszedł czas na kolejny. Tym razem opiszę, jak w D wyglądają tablice. Choć takie funkcje, jak tablice dynamiczne i asocjacyjne pojawiają się w wielu innych językach programowania (czasem pod postacią map lub wektorów), w D rozwiązano tą sprawę trochę inaczej, niż w C++.

Wskaźniki

Chociaż w D występują wskaźniki, nie ma potrzeby ich używania. Zachowane zostały wyłącznie w celu zapewnienia kompatybilności binarnej z C. W większości wypadków tablice dynamiczne oraz inne elementy D w pełni zastępują wykorzystanie wskaźników.

Tablice statyczne

O tym rodzaju tablic nie ma sensu zbytnio się rozpisywać, ponieważ są one bardzo dobrze znane z C/C++. Ich długość musi być znana już w czasie kompilacji.

Tablice statyczne możemy deklarować na dwa sposoby: int tab1[10]; // sposób znany z C int[10] tab2; // sposób znany np. z Javy

Tablice dynamiczne

Kolejnym typem tablic dostępnych w D są tablice dynamiczne. W odróżnieniu od statycznych mogą one zmieniać swój rozmiar. W wielu językach ta funkcjonalność dostępna jest przy użyciu wektorów. Rozwiązanie zastosowane w D jest jednak prostsze i bardziej czytelne.

Deklaracja tablic dynamicznych przebiega identycznie, jak w wypadku tablic statycznych z tą różnicą, że w nawiasach kwadratowych nie podajemy rozmiaru: int tab1[]; int[] tab2;

Operacje na tablicach dynamicznych

D umożliwia również proste wykonywanie różnych operacji na tablicach:
- zmiana długości - aby zmienić długość tablicy dynamicznej w D, należy ustawić wartość length: int[] tablica; tablica.length = 10; - łączenie - wiele języków przeciąża operator "+" do łączenia tablic. W D wykorzystywany jest znak tyldy (~), co niestety może być pewną niedogodnością podczas pisania na Windowsie (ze względu na utrudnione wprowadzanie tego znaku). Można też użyć operatora ~=. Wygląda to w ten sposób: int[] tab1; int[] tab2; int liczba; tab1.length = 10; // Ustawiamy długość na 10 tab2 = tab1 ~ liczba; //przepisuje tab1 do tab2, następnie zwiększa długość o 1 i dopisuje liczbę na końcu tab2 ~= tab1; // Dopisuje tab1 do tab2 - wycinki - pozwalają operować na fragmentach tablicy. Tworzą wyłącznie referencje, nie kopiują danych. int[] a; a.length = 10; int[] b = a[2..5]; //tablica b składa się z elementów a[2], a[3] i a[4] - kopiowanie - następuje wtedy, gdy zarówno po lewej, jak i po prawej stronie znaku '=' umieścimy wycinek: int[] a, b; a.length = 10; b.length = 5; a[2..5] = b[0..3]; a[0..3] = a[6..9]; Możliwe jest kopiowanie w obrębie jednej tablicy, pod warunkiem, że fragmenty są tej samej długości i nie zachodzą na siebie.
- operacje arytmetyczne - kolejna sprytna opcja. W D wykonanie tej samej operacji arytmetycznej na wszystkich elementach tablicy nie wymaga użycia pętli: int[] array; array.length = 10; array[] += 5; - pozostałe - Tablice w D udostępniają komendy odpowiedzialne za sortowanie i odwracanie kolejności elementów w miejscu. Możemy również pobrać długość tablicy. int dlugosc = array.length; array.sort; array.reverse; Oczywiście do działania opcji sort musi istnieć możliwość porównywania dla danego typu. W przypadku liczb, znaków itp. nie musimy się martwić, ale w celu sortowania tablic obiektów własnych klas musimy własnoręcznie zaimplementować porównywanie.

Kontrola indeksów

D kontroluje również rozmiary tablic. W przypadku próby przekroczenia rozmiaru tablicy statycznej program zgłosi błąd w trakcie kompilacji. W wypadku tablic dynamicznych zostanie zgłoszony wyjątek ArrayBoundsError, który możemy przechwycić za pomocą bloku try/catch.

Tablice asocjacyjne

Tablice asocjacyjne są to tablice, których indeksy niekoniecznie są liczbami. Indeks takiej tablicy zwany jest kluczem. Tablice asocjacyjne w wielu językach dostępne są jako mapy. W D nie wymagają wykorzystywania specjalnych stworzonych w tym celu klas. Podstawowe operacje na tablicach asocjacyjnych wyglądają następująco: double[string] array; // deklarujemy tablicę array["maslo"] = 1.99; // dodajemy element o indeksie "maslo" array["batonik"] = 1.49; zaplac(array["batonik"]); // zaplac(1.49); 10.05 -> poprawiłem literówkę. array.remove("batonik"); // usuwamy element o indeksie "batonik" Na koniec - jak obiecałem - przykład prostego słownika:import std.stdio; void main() { string[string] words; // Deklarujemy tablicę słówek. Indeksy będą ciągami znaków. words["ser"] = "cheese"; // Słowom polskim przyporządkowujemy angielskie. words["mleko"] = "milk"; words["maslo"] = "butter"; words["jajko"] = "egg"; write("Podaj słowo: "); // Prosimy o wprowadzenie słowa string key = readln[0..$-1]; /*Wczytujemy słowo. Wycinek [0..$-1] obetnie ostatni znak wczytanego ciągu znaków (zatwierdzenie enterem umieści tu łamanie wiersza)*/ try { writeln(key ~ " - " ~ words[key]); /*Wypisujemy słówko z przetłumaczeniem. Używamy operatora ~ do połączenia ciągów znaków w jeden. Alternatywnie można użyć przecinka.*/ } catch(core.exception.RangeError err) /*Jeżeli nie będzie podanego klucza w tablicy, program wyrzuci wyjątek RangeError. Musimy go obsłużyć*/ { writeln("Nie znam takiego slowa."); } readln(); // Zapobiegamy natychmiastowemu zniknięciu konsoli. }

Koniec części trzeciej

Choć i tutaj D nie wprowadza jakiejś niesamowitej rewolucji, tablice wydają się być bardziej uporządkowane i znacznie prostsze w użyciu. To wszystko sprawia, że D jest przede wszystkim językiem bardzo wygodnym.

Część pierwsza, druga, trzecia... troszkę już się uzbierało. "Mody na sukces" co prawda liczbą odcinków nie pobiję, ale jeszcze czwarty z pewnością się pojawi. Pokażę w nim programowanie kontraktowe i testy jednostokowe, czyli jak program może sam się przetestować. Zapraszam niebawem. 

Komentarze

0 nowych
Xirdus   2 #1 06.04.2010 00:07

Od dawna (ostatnie wakacje) zamierzałem się zabrać za D, jednak nie mogłem znaleźć 'entry point' :) Dzięki Ci bardzo za te wpisy, czekam na następne. Mam nadzieję, że dowiem się do czego służy foreach i jak się tego używa.

skandyn   9 #2 06.04.2010 15:09

Godny następca C i C++, czyli programowanie w D, chyba jeszcze długo nie.
Najpopularniejszym językiem programowania pozostaje jednak nadal C++.
Pozdrawiam.

  #3 06.04.2010 19:52

foreach - jak sama nazwa wskazuję jest to pętla która oznacza dla każdego, w c# się tego bardzo często używa, np w szukaniu w tablicach. W foreach nie musisz sztywno oznaczać ilości powtórzeń pętli

ulth   4 #4 07.04.2010 11:44

Fajny temat jednak dla "specjalistów".
Może by tak w końcu temat jakiś taki fajny dać ?

GL1zdA   11 #5 07.04.2010 11:55

@skandyn
C++ od dawna nie jest najpopularniejszy i prawdopodobnie nigdy nie był:
http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html

borzole   4 #6 07.04.2010 15:37

@GL1zdA
Święta trójca C/C++/Java od lat stanowi czołówkę. A to kto na którym miejscu to już kwestia tego kto robi ranking i na jakiej podstawie.

cinekcnx   2 #7 07.04.2010 18:38

można zauważyć że przedstawione na listingach kody źródłowe są jak na język wysokiego poziomu przystało dość łatwe do przyswojenia (chodzi mi głównie o nazewnictwo funkcji oraz ogólną składnię). Jednak dopóki rozpatrujemy tylko przykłady tak elementarne jak tu (deklaracje, [read/write]ln...), możemy nie zauważyć innych kluczowych dla nowoczesnego języka aspektów, które też muszą być łatwe do implementacji (dziedziczenie, wielowątkowość, hermetyzacja itp). Pojedynek pomiędzy C++ a D rozegra się właśnie w tych aspektach a programiści sami zdecydują czy będzie on wydajniejszy.

  #8 07.04.2010 18:53

@cinekcnx

Amen :)

przemek1234   7 #9 08.04.2010 15:10

Dla mnie godnym następcą jest C# od Microsoftu.

cinekcnx   2 #10 08.04.2010 18:42

gdyby MS nie trzymał się tak kurczowo tylko windows'a przy zastosowaniach platformy .NET C# mógłby odnieść naprawdę poważny sukces, wystarczy dziś spojrzeć na Javę