Pętla for i instrukcje

0

petla.png

Jak to jest z nawiasami klamrowymi po pętli for.
Tzn gdy damy te nawiasy to wykonują sie wszystkie instrukcje a gdy nie damy nawiasów to tylko pierwsza instrukcja po pętli. W załaczniku umieściłem przykład programu który wskazuje na moja teorie. Wnioskuje to po tym że jak zmienna "k" bedzie zerem to warunek z pętli nie bedzie spełniony pętla nie wykona swojej instrukcji to wartość 1 z int lotteryOdds = 1; przejdzie do zmiennej odds[n][k] = lotteryOdds;

Dobrze wnioskuje z tymi nawiasami??

0

tak. Pętle for wykonują tylko jedną poniższą instrukcje jeżeli nie ma nawiasów klamrowych

0

Tak.

W kodzie produkcyjnym często się wstawia klamrę po pętli lub if nawet jeśli masz tylko jedną instrukcję. Dzięki temu można unikać błędów typu "myślałem, że ta instrukcja jest wewnątrz (zewnątrz) pętli", oraz łatwo coś dopisać (jak nie masz klamry, to przy dopisaniu instrukcji trzeba również klamrę wstawić i łatwo tutaj o wcześniej wspomniany błąd).
Przykład: http://4programmers.net/Forum/C_i_C++/257199-visual_c++_bledne_dzialanie_funkcji_logicznej?p=1170510#id1170510

0

A co z zasięgiem blokowym zmiennej w przypadku kiedy pod petla nie ma nawiasów klamrowych a jest deklaracja zmiennej?? (no bo jak sa klamry to wtedy dana zmienna jest dostepna tylko w klamrach a gdy pod pętla nie ma klamer tylko jedna instrukcja)

0

Dziwne pytania zadajesz :)

Szybki test na InteliJ Idea:

        for(int i=0; i<2; i++)
            Integer a = new AtomicInteger(i).getAndIncrement(); 

rzuca błąd kompilacji.

Bez deklaracji zmiennej:

        for(int i=0; i<2; i++)
            new AtomicInteger(i).getAndIncrement(); 

Jest OK.

0

A co z zasięgiem blokowym zmiennej w przypadku kiedy pod petla nie ma nawiasów klamrowych a jest deklaracja zmiennej?? (no bo jak sa klamry to wtedy dana zmienna jest dostepna tylko w klamrach a gdy pod pętla nie ma klamer tylko jedna instrukcja)

Zasięg jest taki sam.

0

wartek01 - nie rozumie twojej odpowiedzi.
Chodziło mi o to że jak utworze zmienną w bloku instrukcji pętli czyli w nawiasach klamrowych to ta zmienia ma zasięg na cały blok czyli miedzy nawiasami klamrowymi.
A gdy utworze zmienną pod pętlą (pierwsza i jedyna instrukcja wykonywania petli) to wtedy ta zmienna ma zasięg na cały zasięg blokowy metody w której sie znajduje czy tylko na
zasieg pola tej jednej instrukcji??

2

Jeśli nie ma klamer w pętli, to nie możesz deklarować zmiennej w kodzie pętli. Kod

for(int i=0;i<5;i++)
    int a = 7;

jest niepoprawny. Zatem pytanie o zasięg takiej zmiennej nie ma sensu.

0

a jesli zrobie to tak:


for(int i=0;i<5;i++)
    int a = i;

???

0

Przecież post wyżej Ci napisał to samo i jest to niepoprawne. To samo napisał Ci ktoś stronę temu. Zacznij myśleć.

0

Nawet dodanie klamer jest nie logiczne, bo zobacz na kod:

for(int i=0;i<5;i++)  {
    int a = 7;
}

Tworzenie zmiennej i przypisanie jej wartości, po to by nic nie robiło jest głupie. Jednak jak byś zrobił tak:

int a;
for(int i=0;i<5;i++)  {
    a = 7;
}

lub

int a;
for(int i=0;i<5;i++)  
    a = 7;

Powoduje to, że później możesz skorzystać z tej zmiennej, bo zadeklarowałeś ją wcześniej i po operacjach przeprowadzonych na niej w pętli, możesz z niej skorzystać.

ps. Dosłownie mam szacunek dla ludzi, którzy odpowiadają na posty, bo jest to naprawdę trudne wytłumaczyć komuś coś, co dla Ciebie jest proste i logiczne.

0

Pisząc to:

for(int i=0;i<5;i++)
    int a = i;

miałem na myśli żeby zdeklarowana zmienna "a" otrzymała wartość zmiennej "i" po wykonaniu na zmiennej "i" działań pętli. A wiec w tym konkretnym przypadku wartość "a" wynosiła by 4.
Taki sposób deklaracji zmiennej pod pętla miałem na mysli.

0

W takim przypadku zrób tak:

int a;
for(int i=0;i<5;i++)
   a = i;
0

Wiem że tak mogę zrobić ale dalej nie wiem dlaczego nie moge tej zmiennej zdeklarować pod pętlą

w taki sposób: Pisząc to:

for(int i=0;i<5;i++)
    int a = i;
0

Nie znam Java i nie wiem czy na takie coś kompilator pozwoli ale gdyby pozwolił wielokrotnie byś ją deklarował to chyba logiczne.

0

Ten zapis

for(int i=0;i<5;i++)
    int a = i;

jest równoważny z:

for(int i=0;i<5;i++) {
    int a = i;
}

Ciekawostka dla Ciebie @golec2604

for(int i=0;i<5;i++)
    int a = i; // zmienia jest za każdym razem tworzona i istnieje tylko dla tej pętli. 
// tutaj już zmienna a nie istnieje

Jeżeli nie potrafisz tego zrozumieć, to na Twoim miejscu porzucił bym programowanie.

0

Co do ciekawostki. Wiem że jest za każdym razem tworzona ale dlaczego tak nie może być i kompilator wywalą błąd ??

1

Bo miałbyś 5 zmiennych o nazwie a.

0

Ok ale jeśli napisze klamry

for(int i=0;i<5;i++) {
    int a = i;
}

to wtedy kompilator nie wywala błędu ale w tedy też bedzie 5 zmiennych o nazwie "a" w ciele pętli

2

Nie, każda wersja zmiennej a istnieje tylko w bloku między klamrami.

0

Mam rozumieć że każda wersja zmiennej "a" występuje w bloku miedzy klamrami tylko w momencie kiedy pętla wykonuje daną czynność, gdy pętla wykonuje swoją czynność powtórnie to następuje kasacja zmiennej i ponowna deklaracja o zmienionej wartości zmiennej "a" na kolejna wartość.

A gdy nie używam klamr to pętla musiała by utworzyć/zdeklarować kilka zmiennych o takiej nazwie i byłby konflikt nazw.

A gdy zdeklaruje zmienna przed pętla a inicjacje dam pod petla to wtedy pętla bedzie zmieniać tylko sama wartość danej zmiennej a nie bedzie jej deklarować.

Czy dobrze w końcu zrozumiałem??

0

Prawie dobrze, kasacja zmiennej następuje nie przy ponownym kodu wykonaniu pętli, ale trochę szybciej - po osiągnięciu zamykającej klamry. Po ostatnim wykonaniu kodu pętli zmienna a nie istnieje.

0

Mam inne pytanie dotyczące petli. Zobaczcie poniższy kod:

public class PetlaProba 
{
	public static void main(String[] args) 

 	 {
 		int n = 5;
 		int i;          
                        
		int x;          
		
		for (i=1;i<=n;i++)
		{
		x=i;
           // System.out.println(x+"   "+i);   // wiersz1 - zakomentowany wiersz drukowania w petli
   	 }
	
		System.out.println( x+"   "+i );     //  wiersz2 - w tym wierszu drukowania zgłasza mi błąd abym zainicjował zmienną x
		
	  }
	
}

Nie wiem dlaczego zgłasza mi błąd w drugim wierszu drukowania i prosi o inicjacje zmiennej "x" w miejscu deklaracji tej zmiennej, przecież ona jest zainicjowana w pętli.

A znowu przecież to samo jest ze zmienną "i" ona też nie jest zainicjowana w miejscu deklaracji tylko w pętli.

Nie rozumiem czemu tak jest??

===========================

Ponadto gdy od od komentuje pierwszy wiersz drukowania w petli (oraz za komentuje drugi wiersz drukowania) i włączę program wtedy w tym wierszu drukowania nie czepia się żeby zainicjować zmienną przed pętla.

Ktoś wyjaśni o co chodzi???

0

Poczytaj sobie w google: Java variable scopes. Zmienna zadeklarowana w scopie petli nalezy tylko do tej petli. A co do 'inicjalizacji' jak juz pisałem w zmienne lokalne muszą być zainicjalizowane przed użyciem. Jeśli np. petla nie wykona się ani razu, to x jest nie zainicjalizowany, więc dlatego musisz ją zainicjalicować tam gdzie deklarujesz.

Jeśli jesteś ciekawy to zajrzyj do specyfikacji języka(JLS) na temat pętli for:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.14

0

Rozumiem gdyby deklaracja była wewnątrz pętli to wtedy zakres jest widoczny tylko w petli,

ale jeżeli deklaracja zmiennej występuje poza pętla (nad petlą) a inicjalizacja tej zmiennej w nawiasach klamrowych pętli to jak to sie dzieje że występuje błąd??

Ponadto zwróć uwagę że zmienna "i" tez jest zainicjowana w pętli a deklaracje ma nad petlą a da się ją odczytać bez inicjacji w miejscu deklaracji.

Jak widać obie zmienne "i" oraz "x" są zainicjowane w pętli, obie też mają deklaracje poza pętla a tylko o zmienną "x" sie kompilator czepia że muszę ją zainicjować przed pęlą?

(nie wiem czy dobrze zrozumiałeś mojego wcześniejszego posta ale dlatego podałem ten przypadek na dwóch zmiennych.)

Na tym przykładzie chciałbym o wytłumaczenie bo nie wiem dlaczego błąd jest zgłaszany tylko dla jednej zmiennej a nie dla dwóch.

0

Jakbyś spojrzał w specyfikację, to byś wiedział że zmienna 'i' jest zainicjalizowana w forze. Natomiast x tylko gdy for się wykona choć raz, więc jest możliwym, że gdy pętla for się nie wykona w ogóle to zostałbyś z nie zainicjalizowaną zmienną x którą chciałbyś wyświetlić, dlatego nie skopilujesz tego.

0

No dobra ale taki błąd powinien sie pokazać gdy pętla nie wykona sie ani razu, a skoro sie wykona to powinno pójść. hmm?

Powiedz mi jeszcze jaki zasieg ma zmienna zainicjowana w nawiasach okrągłych pętli, czy taki sam jak zmienna "x" czyli do końca nawiasu klamrowego??

Pytanie do nazewnictwa zmiennych w pętlowych. Wiem że zmienna "x" jest zmienna lokalną bo działa tylko w miejscu pętli a zmienna "i" w tym przypadku jaka jest zmienną??

0

Pierwsze, kompilator nie analizuje pętli, zatem nie wie czy kod wewnątrz pętli wykona się choć raz. Pesymistycznie zakład, że kod nie wykona się ani razu. Po drobnej modyfikacji Twojego kodu, pętla może się nie wykonać ani razu.

Random r = new Random
int n = r.nextInt(3);;
int i;          
int x;           
for (i=1;i<=n;i++)
{
     x = i;
}
System.out.println( x+"   "+i );     //  wiersz2 - w tym wierszu drukowania zgłasza mi błąd abym zainicjował zmienną x

Drugie, i jest też zmienną lokalną. Lokalne są wszystkie zmienne deklarowane wewnątrz metod i argumenty metod.

0

A)
Napisz co robią pierwsze 2 linijki. Czytałem to w dokumentacji ale jakoś nie mogę wyciągnąć wniosków. Może źle zrozumiałem swoje tłumaczenie.

B)
Czy jest jakaś różnica funkcjonalna (np. w zasięgu lub w czymś innym) miedzy zmiennymi zainicjowanymi w pętli w nawiasach okrągłych a zmiennymi zainicjowanymi w nawiasach klamrowych?? (jedna różnicę którą wiem to to że zmienna zdeklarowana w nawiasach okrągłych jest zmienną sterująca dla ilości powtórzeń pętli.)

C)
Jeszcze chciałbym prosić o potwierdzenie tego co niżej napisałem:

Zmienna lokalna aby została użyta poza pętlą np. wydrukowane przez polecenie System.out.println() musi być zdeklarowana i zainicjowana wartościami początkowymi (przeważnie wartościami 0 lub 1 - zależy to od sytuacji) przed pętlą.
I po zdeklarowaniu i zainicjowaniu tych zmiennych lokalnych pętla czerpie z nich wartości początkowe następnie oblicza je wewnątrz pętli po obliczeniu ładuje te obliczone wartości do zmiennych lokalnych zdeklarowanych przed pętlą, kasuje wartości w pętli, następnie pobiera już nowe wartości - obliczone wcześniej z tych zmiennych lokalnych [zdeklarowanych i zainicjowanych przed pętlą] wykonuje ponowne obliczenia w pętli. Robi je tyle razy na ile pozwala jej na to postawiony warunek. Po wykonaniu określonej liczbie powtórzeń pętla kończy swoje działanie zapisuje w tych zmiennych lokalnych zdeklarowanych przed pętla swoje wartości, kasuje wartości w środku pętli.
Następnie np polecenie System.out.println() pobiera i drukuje te wartości z tych zmiennych lokalnych z przed pętli.

Rozumiem że można również zdeklarować i zainicjować zmienna lokalną wewnątrz pętli która bedzie tylko służyć do wewnętrznych obliczeń i nie będzie potrzebna na zewnątrz.

Po tych Waszych tłumaczeniach tak zrozumiałem działanie zmiennych lokalnych w pętli i sam mechanizm pętli. I teraz pytam Was czy dobrze w końcu rozumiem?? (Mam nadzieje że odpowiedź będzie brzmiała TAK)

0

A)
Pierwszy wiersz tworzy obiekt losujący (z klasy Random). Drugi wiersz losuje liczbę całkowitą z przedziału [0-2].
B)
Nie ma żadnej różnicy (nawet tej, którą wymieniłeś).

        int i = 0;
        for(int k=0;i<4;i++)
        {
            System.out.println(k+" "+i);
        }

Zmienna zainicjowana w nawiasach okrągłych nie jest zmienną sterującą pętli.
C)
Niezupełnie, nie ma żadnego kasowania, nie ma zapisywania (w zadeklarowanych przed pętlą zmiennych) po zakończeniu pętli. Wartości są zapisywane na bieżąco podczas wykonywania pętli.

1 użytkowników online, w tym zalogowanych: 0, gości: 1