Szkolenia programowania we Wrocławiu
Kurs Java Podstawy - rozszerzony

Rozwiązanie 1.14

W tym zadaniu naszego kursu należało korzystać z własności length tablic. Dzięki temu nie musimy się martwić o to, czy w którymś miejscu przekroczymy zakres co jest bardzo przydatne. Dodatkowo wykorzystamy metodę printf() zamiast println(), aby w łatwiejszy sposób zaprezentować dane.

public class Tablice{
  public static void main(String[] args){
	  int[][] tab = new int[2][3];
	  int licznik=0;

	  for(int i=0; i< tab.length; i++)
		  for(int j=0; j< tab[i].length; j++)
			  tab[i][j] = licznik++;

	  for(int i=0; i< tab.length; i++)
		  for(int j=0; j< tab[i].length; j++)
			  System.out.printf("tab[%d][%d]=%d \n", i, j, tab[i][j]);
  }
}

Na początku utworzyliśmy tablicę o wymiarach 2x3 oraz zmienną całkowitą zainicjowaną liczbą 0 - posłuży nam ona do wypełniania tablicy.

Tablicę uzupełniamy wartościami od 0 do 5 wykorzystując dwie zagnieżdżone pętle for wykorzystując własność length.

Wyświetlamy wynik analogicznie. Używamy w tym celu metody printf(). W znaku cudzysłowu umieszczamy to co chcemy wyświetlić jednocześnie podając parametry. %d to argument całkowitoliczbowy. Później po przecinku podajemy wartości w odpowiedniej kolejności, które są pobierane do wyświetlanego tekstu.

Komentarze

Komentarze zamknięte. Zapraszamy do grupy na Facebooku
DzOn_DoE

Świetny kurs. Wielkie dzięki. Szczególnie podoba mi się konwencja, że w rozwiązaniu zawsze użyty jest sposób, o którym nie było mowy w danym dziale (tutaj funkcja printf ).

Darkpixel

Nie rozumiem ;D

Paniol

Czego nie rozumiesz?
Jedyne czego nie można zrozumieć to wykorzystanie metody print(f). Poczytaj sobie i zrozumiesz. Kolejne parametry wyświetlania "%d" podstawiasz po przecinakach tak jak byś miał d1, d2, d3.
Sama przeszukanie tablicy najłatwiej sobie ułożyć w głowie rysując prostokąt 2x3 analogicznie do gry w statki tylko numerujesz oba brzegi zaczynając od zera.


A teraz pozdrowienia dla autora bo lepszego kursu nie znalazłem w necie.
Tak trzymaj stary.

Andrzej

kurs jest ok, ale to jest troche nie zrozumiałe, tym bardziej, że wynik programu z rozwiazania jest inny niż w był zadany w poleceniu; brakuje pierwszej linii.

Szapko

"Tablicę uzupełniamy wartościami od 0 do 6(...)"
Od 0 do 5 :)

Patryk



Szapko:

Użyliśmy tu ważnej własności każdej tablicy, mianowicie length (zauważ, że nie jest to metoda i nie jest zakończona nawiasami() ). Określa ona jej długość, tutaj należy zapamiętać, że zwracana wielkość jest rzeczywista, a nie liczona od 0.
Slawek

Szapko ma racje, zapomniałem poprawić :)
length zwraca np 3, ale ponieważ zostały użyte ostre nierówności to w pętli pobieramy wartości od 0.
pierwsza pętla 0, 1; druga pętla 0, 1, 2; licznik także numeruje od 0 :)

Paweł

Nie rozumiem dlaczego jest zdefiniowane int licznik=0;
i dlaczego nie działa tab[i][j] = i++;
jak w przypadku zwyklej tablicy?

Slawek

W kolejnych przebiegach obu pętli wygląda to tak:
1. i=0 j=0
2. i=0 j=1
3. i=0 j=2
4. i=1 j=0
5. i=1 j=1
6. i=1 j=2
Koniec.

Paweł

Wiem jak dziala petla ale nie rozumiem roznicy miedzy
for(int i=0; i<10; i++)
tablica[i] = i+1; <---startujemy od jednyki i ok

a

int licznik=0;
for(int i=0; i< tab.length; i++)
for(int j=0; j< tab[i].length; j++)
tab[i][j] = licznik++;

Po co jest definiowana zmienna licznik? Wiem ze bez niej wyswietlaja sie same zera. Nie mozna zrobic i+1?

Slawek

No więc wykorzystując tab[i][j] = i+1 wyglądałoby to tak, wracając do mojego wcześniejszego wytłumaczenia:

W kolejnych przebiegach obu pętli wygląda to tak:
1. i=0 j=0 - tab[i][j]=i+1=1
2. i=0 j=1 - tab[i][j]=i+1=1
3. i=0 j=2 - tab[i][j]=i+1=1
4. i=1 j=0 - tab[i][j]=i+1=2
5. i=1 j=1 - tab[i][j]=i+1=2
6. i=1 j=2 - tab[i][j]=i+1=2

i jest licznikiem pętli i zmienia się jedynie z 0 na 1, jeśli byśmy zrobili na niej i++ gdzieś we wnętrzu pętli to dodatkowo przeskoczylibyśmy jedną iterację i zakończyli działanie pętli.
Można by jedynie sprytnie zapisać
tab[i][j] = i*3 + j;
wtedy by działało bez dodatkowej zmiennej, ale nie byłoby tak oczywiste, a na pierwszym miejscu powinno się stawiać czytelność kodu.

ahh no i główna różnica polega na tym, że tutaj mamy dwie zagnieżdżone pętle i tablicę dwuwymiarową, widzę, że chyba w zrozumieniu tego jest tutaj problem.

Adrian

w eclipsie wystarczy włączyć debugera i zobaczyć jak to wszystko fajnie działa.

Natalii

Problemem jest to ze dopoki nie pojdzie sie na studia i nie uslyszy o macierzach to ciezko jest cos takiego zrozumiec :)

Ja bym to sprobowala wytlumaczyc tak:
Kazdy na pewno zna cos takiego jak sudoku: sklada sie z 9 kwadratow podzielonych na nastepne 9 kwadracikow(ale to nieistotne teraz).
Gdybysmy chcieli stworzyc sudoku o wymiarach naszej tablicy dwuwymiarowej tab[2][3] skladaloby sie ono z 6 duzych kwadratow. Dlaczego? Bo mialoby ono 2 wiersze i 3 kolumny. Jak ktos ma problem z wyobraznia to niech sobie narysuje :)
A do kazdego z tych 6 kwadratow wpisujemy KOLEJNO liczby (to wazne bo to nie jest zgaduj zgadula tylko w konkretne miejsce ma trafic konkretna liczba ). Tymi wpisywanymi liczbami sa liczby przypisywane naszej zmiennej licznik.
Przy czym kazdy kwadrat ma swoje okreslone miejsce. Nie mozemy go przestawiac jak sie nam podoba. Czyli mozna by powiedziec ze kazdy taki kwadrat ma swoj wlasny nr a tym numerem nazywamy tutaj indeks tablicy. Kwadraty zaczynamy liczyc od 0 co oznacza ze ostatni kwadrat ma nr 5 ale kazdy dobrze wie ze takich kwadratow jest 6 a nie 5.

Podsumowujac 2*3=6 co daje nam 6 linijek wywietlenia danych (zakladajac ze wyswietlamy zawartosc calej tablicy dwuwymiarowej).

To tyle jesli chodzi o wytlumaczenie budowy takiej tablicy dwuwymiarowej.

Nastepnym problemem jest zauwazenie w jaki sposob odbywa sie zapisywanie do tablicy danych. Skad program wie co ma sie znalezc w konkretnym indeksie tablicy (tutaj w naszych kwadratach).

Otorz pierwsza petla for odpowiada za wpisywanie danych do wierszy. Takich wierszy mamy 2. Skad program to wie? Bo uzylismy magicznego slowka length(z ang. dlugosc) piszac tab.lenght mowimy o tym ze liczba kolumn ma dlugosc. Jaka dlugosc? No taka jaka zadeklarowalismy wczesniej czyli 2, bo i =2 (przy zalozeniu ze tab[2][3] to tab[i][j]). To samo sie tyczy liczby kolumn, ktorych mamy tutaj 3, bo j=3.

Innymi slowy idac od poczatku (zajme sie samymi petlami):

Spotykamy slowko for czyli wiemy ze tutaj bedziemy wykonywac jakas czynnosc konkretna ilosc razy (tutaj i< tab.length czyli 2 razy wykonamy ta petle). Nastepnie spotyklamy nastepne slowko for czyli znowu bedziemy wykonywac cos konkretna ilosc razy (j< tab[i].length czyli 3 razy). Oznacza to ze dopoki w tej drugiej petli nie wykonamy pewnych czynnosci 3 razy (mowimy ze petla wykona sie 3 razy) to nie bedziemy mogli zwiekszyc licznika pierwszej petli czyli przejsc do nastepnego kroku (prosciej mowiac to z wiersza o numerze 0 nie przejde do wiersza o numerze 1 dotad dokad nie wykonam wszystkich czynnosci dla drugiej petli ). Jeszcze inaczej to ujmujac mozna powiedziec ze uzupelnamy dane wiersz po wierszu, przy czym kazdy wiersz sklada sie z konkretnej liczby kolumn tutaj 3.

tab[i][j] = licznik++;
Powyzsza linijka kodu mowi o tym iz licznik bedzie sie zwiekszal co 1 (poczawszy od, 0 bo int licznik=0;) az do momentu gdy liczba kolumn wyniesie 3.
Potem wychodzimy z petli for dla kolumn zwiekszajac liczbe wierszy o 1 (wykonuje sie to w pierwszym for dla wierszy )i ponownie wchodzimy w petle for dla kolumn.

Efekt jest tego taki ze dla wiersza o indeksie 0 mamy indeksy kolumn 0,1,2 (licyba kolumn to 3). Mowi o tym zapis:
tab[0,0] = 0
tab[0,1] =1
tab[0,2] =2.
Skad te 0,1,2? A no stad ze licznik byl caly czas zwiekszany o 1 i nigdzie po wyjsciu z petli go nie zerowalismy.


Mam nadzieje ze pomoglam i jeszcze bardziej tego nie zagmatwalam.

chrisso

Natalio!
Jesteś Wielka :)
Czasem trzeba właśnie tak, jak przysłowiowej "krowie na granicy". Dla kogoś, kto wcześniej nie tylko nie miał w szkole macierzy, ale generalnie przygodę z matmą zakończył kilkanaście lub kilkadziesiąt lat wstecz, to tłumaczenie dokładne jest nieocenione. Super. Dzięki.

Miłosz

Bardzo ładnie wytłumaczone Natalii.
Naprawdę świetny kurs
gratulacje dla Autora

Sowa

Witam :) wiem że wyżej jest ładnie wytłumaczone ale...:P

for(int i=0; i< tab.length; i++)
for(int j=0; j< tab[i].length; j++)
tab[i][j] = licznik++;

pierwsze " i " oznacza że pętla wykona się 2 razy bo mamy 2 tablice,mnie zastanawia jakie ma działanie " i " tutaj
for(int j=0; j< tab[i].length; j++) jest to tutaj jako nazwa czy ilość powtórzeń ?bo tak wychodziło by 2 a nie 3 razy @_@ a to tab[i][j] = licznik++; oznacza że licznik dodaje 1 przy pętli aż osiągnie taką ilość jaką ma ilość "miejsca" w tablicy?

Sowa

?:D

Marcin

Sowa,
na początku była deklaracja tablicy intów
int[][] tab = new int[2][3];
2 określa liczbę wierszy natomiast 3 liczbę kolumn
Teraz przejdę do Twojego pytania

for(int i=0; i< tab.length; i++)
for(int j=0; j< tab[i].length; j++)
tab[i][j] = licznik++;


zmienna "i" jest tutaj licznikiem i pierwsza pętla for faktycznie przejdzie dwa razy, ale nie dlatego, jak napisałeś, że są dwie tablice, ale dlatego, że przyrównujesz ją do wymiaru tablicy i< tab.length. Przypominam o początkowej deklaracji tej tablicy, stąd właśnie dwa przejścia. Co do pętli wewnętrznej, zapis int j=0; j< tab[i].length; j++ wprowadza nową zmienną "j":, która również jest licznikiem. Za jej pomocą przechodzimy przez kolejne pola tablicy w obrębie danego (określonego zmienną "i") wiersza. Pętla wewnętrzna przejdzie trzy razy, ponieważ taka ilość kolumn była określona przy deklaracji tablicy.
tab[i][j] = licznik++; zapis ten przedstawia do jakiej komórki tablicy ma być zapisana wartość zmiennej "licznik". Przy każdym przejściu pętli (wewnętrznej i zewnętrznej) zmianie ulegają liczniki "i" i "j" do momentu określonego przez warunki i< tab.length; i j< tab[i].length;, a nie tak jak napisałeś "aż osiągnie taką ilość jaką ma ilość "miejsca" w tablicy". W sumie chodzi o to samo, ale zasada działania jest trochę inna.
Mam nadzieję, że trochę rozjaśniłem wątpliwości. Pozdrawiam.

Tommy

Wszystko fajnie, dobry kurs, ale zadania do wykonania trochę nieprzemyślane. W poprzednim przykładzie należało użyć tablica.length, choć zostało to wytłumaczone dopiero tutaj a teraz należało wykonać zupełnie niezrozumiałą dla mnie metodę printf(), Jestem całkowicie początkujący w kwestii programowania w ogóle i chciałem jakoś zagospodarować sobie swój wolny czas, ale po takich przygodach jak przy tym zadaniu (siedziałem 30 minut nad własnym "pomysłem" , żeby się później okazało, że muszę użyć nieznanej mi metody) po prostu się zniechęcam...

Slawek

Do wykonania tych zadań nie trzeba było używać rzeczy, które zostały pokazane w rozwiązaniach - to są dodatki i pokazanie, że da się to zrobić w inny sposób. Faktycznie powinienem może dodać do tego rozwiązanie tradycyjne, będę miał chwilę to dopiszę. Uwierz mi też, że 30 minut, to nie jest długie siedzenie nad pomysłem :) Zdarzy Ci się pewnie jeszcze, że i przez 2 dni będziesz musiał posiedzieć nad kilkoma wydawałoby się prostymi błędami :)

Krzysiek

Zgadzam się w zupełności z Tommym, bo takie akcje nie motywują tylko zniechęcają. Motywuje nas SAMODZIELNIE rozwiązane zadanie bo ono nas przekonuje że dobrze pojeliśmy dany materiał i możemy przejść z czystym sumieniem do następnej lekcji. A tu coś kumamy, zaczynamy rozumieć i zamiast dalej krok po kroczku to nagle bum PRZEPAŚĆ, czarna dziura, mam namyśli metodę printf, jestem początkujący. Pozostaje tylko jej analizowanie by to zazębić, szukanie w googlach a tym samym tracenie czasu i systematyki. Kurs jest dobry, ale zaczynam mieć wątpliwości czy dla osób początkujących. To tak jakby pierwszoklasite nauczyć dodawania a potem kazać mu pomnożyć liczby. No tak w końcu 2+2 to tyle samo co 2 x 2 tyle że skąd on ma to wiedzieć jak mu się tego nie wytłumaczy?

Slawek

Powtórzę tylko, że do wykonania tego zadania zupełnie nie potrzeba metody printf. Można je wykonać co najmniej na kilka sposobów bez niej i szczerze mówiąc to nie za bardzo rozumiem w czym jest tutaj problem.
Wszystkie rozwiązania, które są tutaj umieszczane, są tylko przykładowe i poglądowe, bo praktycznie nigdy nie dzieje się tak, że 2 osoby napiszą coś tak samo.
Nazywanie różnicy pomiędzy print(), a printf() PRZEPAŚCIĄ, pomimo że w rozwiązaniu jest napisane, czym jest %d, czyli chyba jedyna nowość to drobna przesada.
Są też tutaj komentarze - na większość naprawdę staram, się odpowiadać, coraz więcej jest osób która się angażuje i robi to także zamiast mnie.
W przerwie świątecznej powstanie forum - mam nadzieję, że wtedy to także dużo ułatwi.
Tymczasem pozdrawiam i mam nadzieję, że jednak będziesz kontynuował naukę, czy to z moim kursem, czy też z innym.

Krzysiek

Okay Sławek, nie denerwuj się. Ja poprostu zawsze wszystko muszę rozumieć i czasami jak trzeba to analizuje dany zapis literka po literce. Te tablice dały mi trochę w kość i stąd ta moja desperacja;) Ale teraz z perspektywy czasu uważam, że dobrze robisz wrzucając niespodziewanie coś nowego - to zmusza do myślenia. Dla innych desperatów tradycyjne rozwiązanie zadania

System.out.println("tab["+i+"]["+j+"]="+tab[i][j]);

Przy okazji, wspomniałem, że męczyłem się z tablicami. Chciałem zrobić numerowanie elementów w odwrotnej kolejności. Widzę też że dużo osób nie rozumie wprowadzenia dodatkowej zmiennej. Myślę że wiąże się to z tym że pętle for podajesz jako wypełnienie i nas początklujących to myli. A co myślisz o takim wytłumaczeniu?

int [] tablica = new int[10];
// utworzenie pustej tablicy o rozmiarze 10 elementow
for(int i = 0; i<10; i++)
/* utworzenie indeksu tablicy (zaindeksowanie elementow, można
powiedzieć wprowadzenie systemu, sposobu ich odczytywania)*/ tablica[i] = i+1;
/* wypelnienie tablicy (zapisanie zaindeksowanych już elementów).
Przypadkiem i uproszczeniem jest tutaj zastosowanie zmiennej
z pętli, można użyć też dodatkowej zmiennej np. int c = 20;
tablica[i] = c; c--; Tablice wypełnimy wtedy liczbami od 20 w dól
do 10*/

Bynajmniej ja to teraz tak rozumiem ;)))

Adrian

Jak dla mnie printf to super sprawa, posiedziałem i początkowo tez o niej nie wiedziałem to pisałem tak jak wszyscy print, a potem println, ale widać że Sławek podsunął lepsze rozwiązanie i to mi sie podoba.

WEST

nie wiem jak wyświetlić tablicę. Wpisywałem to co inni a nawet kopiowałem i nadal nie wyświetla pokazuje mi się błąd [[Ljava.lang.String;@7d4991ad lub przy printf coś w stylu the method printf in printstream is not applicable for... pomóżcie!!!

Lukasz

Witam,

Ja mam pytanie dotyczące warunków z pętli.
W pierwszej pętli mamy i<tab.length - tzn., że i<2 bo tyle ma wierszy nasza tabela (2x3)
W drugiej mamy j<tab[i].length - tzn., że j<3, bo tyle ma kolumn nasza tabela. Ale tu nie rozumiem, czy to "i" w tab[i], ja jakiś związek z "i" z pierwszej pętli? Skąd program wie, że w pierwszej pętli chodzi o ilość wierszy a w drugiej o ilość kolumn?

Czy możliwe są tablice więcej niż 2-wymiarowe (np. 2x3x4)? Wydaje mi się, że teoretycznie tak, więc jak wyglądał by wtedy warunek k<tab[???].length ????

Pozdrawiam,
Lukasz

folcrum

Zgadza się, zmienna "i" z pierwszej pętli ma znaczenie bo to ona w drugiej pętli ustawia sie na odpowiednią kolumne w której ma robić pętle. Inaczej mówiąc

for(int i=0; i< tab.length; i++)
// ustawia się na pierwszym wierszu pierwszej kolumny
for(int j=0; j< tab[i].length; j++)
// ustawia się na pierwszym wierszu "i" kolumny
tab[i][j] = licznik++;
// wykonuje instrukcje przypisania do odpowiedniego miejsca w tabeli


Zmienna "i" ustawia poprostu do której kolumny mają być wprowadzone dane.

Lukasz

ok, dzięki, bardziej mi chodziło o wyrażenie tab[i].length. tak więc tutaj tab[i].length zmienia się następująco:

j<tab[0].length dla i=0
j<tab[1].length dla i=1

i w obu wypadkach tab[i].length = 3, bo:

tab.length - długość w sensie ilość wierszy (wartość rzeczywista liczona od 1 w tablicy 2x3)
tab[i].length - długość w sensie ilość kolumn w i-tym wierszu (wartość rzeczywista liczona od 1 w tablicy 2x3)

Zgadza się czy coś źle rozumiem...

Slawek

dobrze rozumiesz.

Edzio94

Mam pytanie - czy moje rozwiązanie może spowodować jakieś błędy w przyszłości?

public class Tablice_Wielowymiarowe {
public static void main(String[] args){
int i = 0;
int j = 0;
int test=0;
int tablica[][] = new int [2][3];
for ( i = 0; i < tablica.length ; i++){
tablica[i][0] = i;
for (j = 0 ; j < tablica[i].length ; j++){

tablica [0][j]=j;
System.out.println("tablica ["+tablica[i][0]+"]["+tablica[0][j]+"] = "+test);
test++;
}
System.out.println();
}

}
}

Andy

Ale popaprane rozwiązanie!!!
i - to pierwsza zmienna, j -druga zmienna, a w podwójnej pętli umieszczamy :

tablica[i][j] = 3*i+j;

i koniec tego dobrego!!!!!!

SAK

Czy w wielowymiarowych tablicach można zastosować pętlę for each:
for (int x : tab)
System.out.println(x);

I jeżeli tak, to jak, bo mi się nie udaję..

SAK

Już znalazłem, sorry :)

Lukasz

Można też zrobić bez deklarowania pomocniczej zmiennej licznik. W ten sposób:

int[][] tablica = new int[2][3];
for(int i=0;i< tablica.length;i++)
for(int j=0;j<tablica[i].length;j++){
tablica[i][j]= i*tablica[i].length+j;
}

marko

Czy te %d to nie pochodzi z języka C ? Ja zrobiłem inaczej, a wynik zgodny z warunkami zadania:
int zad1[][]=new int[2][3];
int i,j,m;

i=0;
j=0;
m=0;
for(i=0;i<zad1.length;i++)
{
for(j=0;j<zad1[i].length;j++)
{
zad1[i][j]=m++;
System.out.println( "Element ["+i+"]["+j+"]"+" wynosi "+zad1[i][j]);
}
}

Sławek Ludwiczak

Parametry przy drukowaniu działają w zasadzie tak samo w wielu językach programowania, również w C/C++.

Bogdan

Rozwiązanie chyba nie do końca robi to co powinno :) Takie drobiazgi:
-w poleceniu było aby wyświetlało kolejne linie z odpowiednimi wartościami i kończące się średnikiem. :) A on się nie wyświetla.
-format wyświetlania kolejnych komórek tablicy: w poleceniu nie było nawiasów kwadratowych :)
Można trochę to uprościć, zamiast drugiego zestawu pętli do wyświetlania można od razu wyświetlać przypisywane wartości.
Pozdrawiam

Sławek Ludwiczak

oj, bo to taki fristajl
Pomijając drugą pętlę można równie dobrze, że można też zrezygnować z tablicy, bo można od razu wyświetlać wartości itp, kwestia mocno umowna :)

Maciek

Ogólnie super kurs, ale do tego rozwiazania powinien być dodany wyżej komentarz Natalii(bez niego strasznie długo się męczyłem żeby zrozumieć ten kod- może wynika to z tego że nie miałem kontaktu z macierzami).

Dev0

public class TabliceWielowymiarowe {

public static void main(String[] args) {
// Tablice wielowymiarowe

int tablica[][] = new int[2][3];
int dane = 0;
for (int i = 0; i < tablica.length; i++) {
for (int j = 0; j < tablica[i].length; j++) {
tablica[i][j] = dane;
System.out.println("tab["+i+","+j +"] = " +tablica[i][j]);
dane++;


Chyba ładniej?

WEST

nie wiem jak wyświetlić tablicę. Wpisywałem to co inni a nawet kopiowałem i nadal nie wyświetla pokazuje mi się błąd [[Ljava.lang.String;@7d4991ad lub przy printf coś w stylu the method printf in printstream is not applicable for...

WEST

ok już wiem o co chodzi gdy mam zapisane liczby w tablicy ale co z literami??

WEST

ok to też ogarnąłem.Nie potrzebnie uwziąłem się na tablice.Od tego co chciałem zrobić jest zabawa z wieloma klasami w jednym archiwum;)