{"id":662,"date":"2014-01-05T22:33:48","date_gmt":"2014-01-05T22:33:48","guid":{"rendered":"http:\/\/piatkosia.k4be.pl\/wordpress\/?p=662"},"modified":"2014-01-06T12:24:11","modified_gmt":"2014-01-06T12:24:11","slug":"c-tablice","status":"publish","type":"post","link":"https:\/\/piatkosia.k4be.pl\/wordpress\/2014\/01\/05\/c-tablice\/","title":{"rendered":"[C#] Tablice"},"content":{"rendered":"<p style=\"text-align: justify;\">(to te\u017c post na konkurs)<\/p>\n<p style=\"text-align: justify;\">Tablice s\u0105 zmiennymi tego samego typu, u\u0142o\u017cone w pami\u0119ci s\u0105siednio tak, \u017ce wiedz\u0105c kt\u00f3rym kolejno elementem od zerowego jest poszukiwany, mo\u017cemy si\u0119 do niego dosta\u0107. Mo\u017cemy sobie wyobrazi\u0107 tablic\u0119 jak poci\u0105g z\u0142o\u017cony z wagonik\u00f3w (ka\u017cdy z tych wagonik\u00f3w mo\u017ce przewozi\u0107 tylko przedmioty jednego typu, na przyk\u0142ad kosz jab\u0142ek, lub samoch\u00f3d). Aby wyobrazi\u0107 sobie drugi wymiar tablicy, trzeba by wyimaginowa\u0107 sobie poci\u0105g, kt\u00f3ry jecha\u0142by jednocze\u015bnie po dw\u00f3ch torach (na chwil\u0119 zapomnijmy \u017ce te tory powinny i\u015b\u0107 w przeciwnych kierunkach), wi\u0119c jednym wymiarem b\u0119dzie numer toru, drugim numer wagonika (liczone od zera). Dlaczego zmienne zgrupowane w tablicy musz\u0105 mie\u0107 ten sam typ? Jest to spowodowane konieczno\u015bci\u0105 wyliczenia miejsca, gdzie znajduje si\u0119 element o danym indeksie. Tak naprawd\u0119 komputerowi wystarczy, aby elementy zajmowa\u0142y t\u0119 sam\u0105 ilo\u015b\u0107 pami\u0119ci \u2013 ale j\u0119zyk jest napisany w taki a nie inny spos\u00f3b i elementy musz\u0105 by\u0107 tego samego typu i ju\u017c.<!--more--><br \/>\nDeklaracja najprostszej tablicy wygl\u0105da nast\u0119puj\u0105co: typ[] nazwa; &#8211; na przyk\u0142ad koszjablek[] mojkoszyk; gdzie typem mo\u017ce by\u0107 cokolwiek: zmienna prosta, zmienna zadeklarowana przez nas, enum, struktura, tablica dowolnego typu, tablica tablic tablic, jaki\u015b wska\u017anik, s\u0142owem wszystko.<br \/>\nAby zdefiniowa\u0107 tablic\u0119, nale\u017cy u\u017cy\u0107 operatora new. Trzymaj\u0105c si\u0119 przyk\u0142adu powy\u017cej, by\u0142oby to koszjablek[] koszyki = new koszjablek[10]; Zapis ten oznacza, \u017ce mamy now\u0105 tablic\u0119 z\u0142o\u017con\u0105 z 10 koszyk\u00f3w jab\u0142ek po\u0142o\u017conych jeden przy drugim. Je\u015bli chcemy podmieni\u0107 kt\u00f3ry\u015b z koszyk\u00f3w (np. bo poprzedni ju\u017c jest pusty, a chcemy go podmieni\u0107 pe\u0142nym) u\u017cyjemy instrukcji przypisania: mojkoszyk[2] = jakiskosz; Oczywi\u015bcie zmienna jakiskosz musi by\u0107 typu koszjablek. W\u0142a\u015bnie wymienili\u015bmy trzeci koszyk (poniewa\u017c liczymy od zera). Og\u00f3lnie mamy wi\u0119c nazwa_tablicy[indeks] = wartosc; . Pami\u0119tajmy, \u017ce indeks musi by\u0107 liczb\u0105 znajduj\u0105c\u0105 si\u0119 w przedziale od 0 do (nazwa_tablicy.Length -1).<br \/>\nMo\u017cemy nasz\u0105 tablic\u0119 wype\u0142ni\u0107 warto\u015bci\u0105 w chwili tworzenia. Nie musimy wtedy podawa\u0107 ilo\u015bci jej element\u00f3w (w przypadku jagged dotyczy to tylko ostatniego wymiaru). Przyk\u0142adem niech b\u0119dzie tablica liczb zawieraj\u0105cych kolejne pot\u0119gi dw\u00f3jki:<\/p>\n<pre class=\"brush: csharp; collapse: false\">  int[] bin = { 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048};<\/pre>\n<p>Jak wida\u0107, stworzona zosta\u0142a tablica int\u00f3w o podanych warto\u015bciach. Innym sposobem zapisu powy\u017cszego b\u0119dzie :<\/p>\n<pre class=\"brush: csharp; collapse: false\">  int[] bin = new int[]{ 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048};<\/pre>\n<p>Wypisanie wszystkich element\u00f3w tablicy wygl\u0105da\u0142oby tak:<\/p>\n<pre class=\"brush: csharp; collapse: false\">  \r\nforeach (int liczba in bin)\r\n{\r\nConsole.WriteLine(liczba);\r\n}<\/pre>\n<p style=\"text-align: justify;\">W przeciwie\u0144stwie j\u0119zyka C\/C++ tablice w C# mog\u0105 mie\u0107 wiele wymiar\u00f3w. Wymiary te zapisujemy w tym samym nawiasie kwadratowym po przecinku. Sp\u00f3jrzmy na przyk\u0142ad na tak\u0105 (celowo s\u0105 4 wymiary \u2013 bo te powy\u017cej 3 wymiar\u00f3w trudno sobie nawet wyobrazi\u0107):<\/p>\n<pre class=\"brush: csharp; collapse: false\">  \r\n\/\/jaki\u015b kod powy\u017cej\r\nint[,,,] tab = new int[5, 10, 2 ,4];\r\nSystem.Console.WriteLine(\"Mamy do czynienia z tablic\u0105 {0} wymiarow\u0105.\", tab.Rank);<\/pre>\n<p style=\"text-align: justify;\">Ka\u017cdy z wymiar\u00f3w mo\u017cemy potraktowa\u0107 np. jako warstw\u0119 czego\u015b na mapie w jakiej\u015b grze<br \/>\nPierwsze 3 wymiary to by\u0142aby d\u0142ugo\u015b\u0107 wysoko\u015b\u0107 i szeroko\u015b\u0107, a 4 to typ \u201eklocka\u201d.<br \/>\nPowy\u017cej jest napisane, \u017ce zmienne musz\u0105 by\u0107 jednego typu. I jest to prawda. Ale przecie\u017c tym typem mo\u017ce by\u0107 r\u00f3wnie dobrze object \u2013 a wiedz\u0105c co jest w kt\u00f3rym miejscu tablicy u\u017cy\u0107 rzutowania.<br \/>\nKto\u015b m\u00f3g\u0142by si\u0119 zastanawia\u0107 jak to mo\u017cliwe, skoro obiekty maj\u0105 r\u00f3\u017cny rozmiar. A mog\u0105 sobie mie\u0107, przecie\u017c obiekt jest typem referencyjnym \u2013 wi\u0119c w naszej tablicy s\u0105 przechowywane wy\u0142\u0105cznie referencje do tych obiekt\u00f3w \u2013 one same le\u017c\u0105 sobie gdzie\u015b na stercie i nie musimy si\u0119 nimi przejmowa\u0107. M\u00f3wi\u0105c referencja my\u015blimy o adresach, a te na danej platformie sprz\u0119towej maj\u0105 zawsze tak\u0105 sam\u0105 wielko\u015b\u0107 w bajtach (dla platformy 32 bit b\u0119dzie to 4 bajty, dla 64 bit 8 bajt\u00f3w).<br \/>\nZazwyczaj u\u017cywamy tablic dwuwymiarowych. Przyk\u0142ad inicjalizacji takiej tablicy wygl\u0105da nast\u0119puj\u0105co:<\/p>\n<pre class=\"brush: csharp; collapse: false\">  \r\nint[,] tablica = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };<\/pre>\n<p>Przyk\u0142adowy odczyt elementu:<\/p>\n<pre class=\"brush: csharp; collapse: false\">  \r\nSystem.Console.WriteLine(\"Element({0},{1})={2}\", 2, 1, tablica[2, 1]);<\/pre>\n<p>Mamy jeszcze taki tw\u00f3r jak tablice postrz\u0119pione (jagged), czyli normalne, znane chocia\u017cby z C++ tablice tablic. Mo\u017cemy j\u0105 zdefiniowa\u0107 tak<\/p>\n<pre class=\"brush: csharp; collapse: false\">  \r\nint[][] postrzepiona = new int[5][];<\/pre>\n<p>Albo na przyk\u0142ad tak:<\/p>\n<pre class=\"brush: csharp; collapse: false\">  \r\nint[][] strzep = new int[][]\r\n{\r\nnew int[4],\r\nnew int[7],\r\nnew int[5]\r\n};<\/pre>\n<p>Mo\u017cemy od razu wype\u0142ni\u0107 tablic\u0119 danymi, pisz\u0105c kod analogiczny do tego:<\/p>\n<pre class=\"brush: csharp; collapse: false\">  \r\nint[][] zainicjalizowanyStrzep =\r\n{\r\nnew int[] {1,2},\r\nnew int[] {3,4,5,6},\r\nnew int[] {7,8,9}\r\n};<\/pre>\n<p>Aby dobra\u0107 si\u0119 do konkretnej warto\u015bci z powy\u017cszego twora i wypisa\u0107 j\u0105 na ekran, mo\u017cna u\u017cy\u0107 takiej linijki:<\/p>\n<pre class=\"brush: csharp; collapse: false\">  \r\nConsole.WriteLine(zainicjalizowanyStrzep[1][2]);<\/pre>\n<p>Mo\u017cemy zainicjalizowa\u0107 r\u00f3wnie\u017c tylko jeden ze \u201estrz\u0119pk\u00f3w\u201d (czyli jedn\u0105 z \u201epodtablic) w nast\u0119puj\u0105cy spos\u00f3b:<\/p>\n<pre class=\"brush: csharp; collapse: false\">  \r\nint[][] InnaPostrzepiona = new int[6][];\r\nInnaPostrzepiona[0] = new int[4] { 1, 2, 3, 4 };<\/pre>\n<p style=\"text-align: justify;\">Nale\u017cy pami\u0119ta\u0107, \u017ce nie wa\u017cne czy we\u017amiemy tablic\u0119 jedno-, wielowymiarow\u0105 czy postrz\u0119pion\u0105, zawsze ilo\u015b\u0107 wymiar\u00f3w i d\u0142ugo\u015b\u0107 ka\u017cdego z nich jest podawana w momencie jej tworzenia. Jednak je\u017celi si\u0119 oka\u017ce, \u017ce wielko\u015b\u0107 wymiar\u00f3w nam nie pasuje, to mo\u017cemy to zmieni\u0107, tworz\u0105c nowy obiekt i przypisuj\u0105c go do starej zmiennej. Jednym s\u0142owem poni\u017cszy kod:<\/p>\n<pre class=\"brush: csharp; collapse: false\">  \r\nint[,] tablica = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };\r\nSystem.Console.WriteLine(\"Element({0},{1})={2}\", 2, 1, tablica[2, 1]);\r\n\/\/jakie\u015b operacje\r\ntablica = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, {9, 10} };\r\n\/\/jakie\u015b inne operacje<\/pre>\n<p style=\"text-align: justify;\">jest jak najbardziej poprawny. Dlaczego? Poniewa\u017c mamy do czynienia z zupe\u0142nie now\u0105 tablic\u0105, przypisan\u0105 do starej referencji.<br \/>\nJe\u017celi w przypadku inicjalizacji nie zainicjalizujemy ca\u0142ej tablicy tylko jej kawa\u0142ek, pozosta\u0142a jej cz\u0119\u015b\u0107 zostaje zainicjalizowana niejawnie warto\u015bciami domy\u015blnymi tj. wykonywany jest operator default na danym typie. Dla typ\u00f3w numerycznych jest to zero, dla boola false, dla typ\u00f3w referencyjnych jest to null itd.<br \/>\nTablica mo\u017ce by\u0107 u\u017cyta w funkcji jako parametr wej\u015bciowy (chocia\u017cby w najcz\u0119\u015bciej spotykanej funkcji \u2013 Main),<\/p>\n<pre class=\"brush: csharp; collapse: false\">  \r\nstatic void Main(string[] args)\r\n{\r\n\/\/jaki\u015b kod\r\n}<\/pre>\n<p>oraz jako parametr wyj\u015bciowy (jak poni\u017cej)<\/p>\n<pre class=\"brush: csharp; collapse: false\">  \r\nstatic void WypelniaczTablic(out int[] tablica)\r\n{\r\ntablica = new int[5] { 1, 2, 3, 4, 5 };\r\n}<\/pre>\n<p style=\"text-align: justify;\">I mo\u017cna ich normalnie u\u017cy\u0107 w funkcjach, odwo\u0142uj\u0105c si\u0119 do poszczeg\u00f3lnych jej element\u00f3w i tak dalej.<\/p>\n<p style=\"text-align: justify;\">Podsumowuj\u0105c: u\u017cycie tablic w j\u0119zyku C# jest proste i intuicyjne. Pozwala ono pouk\u0142ada\u0107 powi\u0105zane dane tego samego typu w jeden tw\u00f3r i wygodnie z tego tworu korzysta\u0107.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>(to te\u017c post na konkurs) Tablice s\u0105 zmiennymi tego samego typu, u\u0142o\u017cone w pami\u0119ci s\u0105siednio tak, \u017ce wiedz\u0105c kt\u00f3rym kolejno elementem od zerowego jest poszukiwany,<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/piatkosia.k4be.pl\/wordpress\/2014\/01\/05\/c-tablice\/\">Lecim dalej<span class=\"screen-reader-text\">[C#] Tablice<\/span> <i class=\"fas fa-angle-right\"><\/i><\/a><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,83],"tags":[142,163],"class_list":["post-662","post","type-post","status-publish","format-standard","hentry","category-bez-kategorii","category-c_sharp","tag-csharp","tag-tablice","entry"],"_links":{"self":[{"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/posts\/662","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/comments?post=662"}],"version-history":[{"count":6,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/posts\/662\/revisions"}],"predecessor-version":[{"id":669,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/posts\/662\/revisions\/669"}],"wp:attachment":[{"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/media?parent=662"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/categories?post=662"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/piatkosia.k4be.pl\/wordpress\/wp-json\/wp\/v2\/tags?post=662"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}