Pętle for i foreach
Pętla for
Konstrukcja pętli for
jest następująca:
for (wyrażenie1; warunek; wyrażenie2)
{
blok_instrukcji;
}
blok_instrukcji
będzie wykonywany dopóty, dopóki spełniony jest warunek
. Mówiąc inaczej - najpierw interpreter sprawdza, czy warunek jest spełniony. Jeżeli tak, to wykonywany jest blok_instrukcji
. Jeżeli nie, to wykonywanie pętli jest zakończone i wykonywane są instrukcje znajdujące się po bloku pętli. Omawiany warunek
jest po prostu warunkiem kolejnego obiegu pętli - wykonania blok_instrukcji
. Poprawne określenie warunku jest bardzo ważne. Załóżmy, że określiliśmy nasz warunek jako 5>2
. Może jest to warunek skrajnie głupi ale załóżmy, że ktoś jednak taki warunek zastosował. Co z tego wynika? Tylko tyle, że zawsze pięć jest większe od dwóch, a więc warunek jest zawsze spełniony, a więc pętla będzie się wykonywać w nieskończoność. Prowadzi to, do zawieszenia programu. Wprawdzie, żaden programista nie stawia takich warunków, niemniej błędy niepoprawnego określenia warunku wykonywania pętli zdarzają się dosyć często.
Najczęściej pętli for
używa się w ten sposób, że wyrażenie1
ustawia wartość początkową licznika, warunek
sprawdza stan licznika, natomiast wyrażenie2
zmienia stan licznika. Co robi licznik? Liczy kolejne obiegi pętli. Najlepiej zobaczyć to na przykładach.
Ćwiczenie 1_12_1_1
Napisz skrypt, który wyświetli 1000 kolejnych liczb całkowitych począwszy od 5. Zastosuj jeden plik. Kod PHP realizujący, to zadanie:
<?php
for ($i=1;$i<=1000;$i++)
{
$liczba=$i+4;//ponieważ zaczynamy wyświetlanie od 5
$napis=(string)$liczba;//rzutujemy integer na string
if ($i<1000) $napis.=', ';//oddzielamy kolejne liczby przecikami, oprócz ostatniej
echo $napis;
}
?>
- Licznikiem jest zmienna
$i
; - wartość początkowa licznika wynosi
1
; - pętla jest wykonywana, jeżeli wartość licznika jest mniejsza lub równa
1000
; - po każdym obiegu pętli wartość licznika jest zwiększana o
1
;
Ćwiczenie 1_12_1_2
Napisz skrypt, obliczający n! (n silnia). Liczbę n wyślij formularzem. Dla uproszczenia, zakładamy, że użytkownik wyśle liczbę całkowitą, nieujemną. Kod PHP realizujący, to zadanie:
<?php
$n=$_POST['n'];//odbieramy wartość wysłaną formularzem
if ($n==0) echo '0! (0 silnia) = 1'; // 0!=1 (zero silnia równa się jeden)
else
{
$silnia=1;
for ($i=1;$i<=$n;$i++)//np. 4!=1*2*3*4*5
$silnia*=$i;
echo $n.'! ('.$n.' silnia) = '.$silnia;//wyświetlamy wynik
}
?>
Ćwiczenie 1_12_1_3
Napisz skrypt, który za pomocą znaków * (gwiazdki) narysuje choinkę. Zastosuj jeden plik. Zastosuj kod HTML i PHP:
<!doctype html>
<html>
<head>
<title>Testowanie skryptów PHP</title>
<meta charset="UTF-8" />
</head>
<body>
<?php
define('X', 11);
echo '<pre>';
for ($w=1;$w<=X;$w++)
for ($k=1;$k<=X+$w;$k++)
{
if ($k==X+$w) echo "\n"; else
if ($k>X-$w && $k<X+$w) echo '*';
else echo ' ';
}
echo '</pre>';
?>
</body>
</html>
- Na początku zdefiniowaliśmy stałą
X
, która określa wielkość choinki. - Znacznik
<pre>
zapewni nam układ wyświetlany zgodny z pisanym układem gwiazdek. - Zewnętrzna pętla
for
wyznacza działania w kolejnych wierszach. - Wewnętrzna pętla
for
pisze znak gwiazdki, spacji lub przeniesienia do nowego wiersza"\n"
w kolejnych wierszach.
Zagnieżdżone pętle for
W poprzednim przykładzie, w którym rysowaliśmy choinkę, zastosowaliśmy petlę w pętli. Podobny układ, można zastosować np. do wypełniania lub odczytywania tabel. Jedna pętla "jechałaby" po wierszach, natomiast druga po kolumnach. Poniżej pokazane są dwa przykłady tłumaczące działanie zagnieżdżonych pętli for
.
Ćwiczenie 1_12_1_4. Testowanie zagnieżdżonej pętli for - przykład 1
Przetestuj pokazany kod PHP:
<?php
$a=0;
for ($i=1;$i<=10;$i++)
for ($j=1;$j<=20;$j++)
for ($k=1;$k<=30;$k++)
{
$a++;
echo 'Dla $i=='.$i.', $j=='.$j.', $k=='.$k.' wartość $a wynosi '.$a.'<br />';
}
?>
Pytanie: Jaka będzie więc wartość zmiennej $a
, jeżeli $i==2
, $j==3
oraz $k==4
?
Zwróć uwagę, że zapis
for ($i=1;$i<10;$i++)
for ($j=1;$j<20;$j++)
for ($k=1;$k<30;$k++)
Jest równoznaczny z zapisem:
for ($i=1;$i<10;$i++)
{
for ($j=1;$j<20;$j++)
{
for ($k=1;$k<30;$k++)
}
}
W tej drugiej postaci wyraźnie widać, że w na jeden obieg pętli z licznikiem $i
, składa się 20 obiegów pętli z licznikiem $j
, przy czym na jeden obieg pętli z licznikiem $j
, składa się 30 obiegów pętli z licznikiem $k
. Jaka będzie więc wartość zmiennej $a
, jeżeli $i==2
, $j==3
oraz $k==4
?. Dla łatwiejszej identyfikacji, ponumerujmy pętle zaczynając od zewnętrznej (z licznikiem $i
). W pierwszym obiegu pętli 1, wykona się 20 razy pętla 2 i w każdym obiegu petli 2 wykona się 30 razy pętla 3 - tak więc instrukcja ++$a
wykona się 20*30 razy, wartość $a
, po pierwszym obiegu pętli 1 wyniesie 600. W drugim obiegu pętli 1 , pętla 2 wykona się 3 razy, przy czym za pierszym i drugim razem, pętla 3 wykona się 30 razy (30+30), natomiast w ostatnim obiegu pętli 2, pętla 3 wykona się 4 razy. Podsumowując zmiany wartości $a
mamy: 600+60+4=664. Odszukaj tę wartość w zestawieniu pokazanym w przeglądarce. Czy nasze rozumowanie było poprawne?
Zwróć uwagę, że w naszym prostym przykładzie, instrukcja ++$a
wykonała się 6000 razy!
Ćwiczenie 1_12_1_5. Testowanie zagnieżdżonej pętli for - przykład 2
Przetestuj pokazany kod PHP:
<?php
$a=0;
for ($i=1;$i<=10;$i++)
{
$a++;
for ($j=1;$j<=20;$j++)
{
$a++;
for ($k=1;$k<=30;$k++)
{
$a++;
echo 'Dla $i=='.$i.', $j=='.$j.', $k=='.$k.' wartość $a wynosi '.$a.'<br />';
}
}
}
?>
Tym razem każda z pętli otwiera swój blok nawiasem klamrowym. Tych nawiasów nie można pominąć, ponieważ pierwszą instrukcją w każdej z pętli jest $a++
i dopiero po tej istrukcji rozpoczyna się następna pętla. Dlatego zmienna $a
osiąga wartość większą jak w poprzednim przykładzie.
Ćwiczenie 1_12_1_6. Zamiana liczby zapisanej w dowolnym systemie na postać dziesiętną
Liczbę całkowitą nieujemną zapisaną w notacji wybranego systemu (dwójkowego, ósemkowego, itd.), zapisz postaci dziesiętnej. Przykładowy kod PHP realizujący, to zadanie:
<?php
function wartosc_znaku($znak)
{
$znaki='0123456789ABCDEF';
return strpos($znaki,$znak);
}
$liczba=$_POST['liczba'];
$podstawa=$_POST['podstawa'];
if ($liczba=='' || $podstawa=='') echo 'Brak danych!';
else if ($podstawa<2 || $podstawa>16) echo 'Podstawa musi być liczbą z przedziału 2..16 ';
else
{
echo $liczba.'<sub>'.$podstawa.'</sub> = ';
$nowa_liczba=0;
$licznik=0;
for ($z=strlen($liczba)-1;$z>=0;$z--)
{
$licznik++;
if ($licznik===1) $mnoznik=1; else $mnoznik*=$podstawa;
$nowa_liczba+=$mnoznik*wartosc_znaku($liczba[$z]);
}
echo $nowa_liczba.'<sub>10</sub>';
}
?>
Pokazany kod wymaga wytłumaczenia:
- Dla uproszczenia zakładamy, że użytkownik wpisze poprawnie liczbę oraz podstawę systemu.
-
Funkcja wbudowana
strpos($tekst, $fragment)
wskazuje pozycję łańcucha$fragment
w łańcuchu$tekst
. -
Funkcja wbudowana
strlen($tekst)
oblicza długość łańcucha znaków liczoną w liczbie znaków. -
Do zamiany liczby na zapis dziesiętny wykorzystano definicję systemów pozycyjnych.
Na przykład:
123410 = 4⋅100 + 3⋅101 + 2⋅102 + 1⋅103
Nie trudno zauważyć kolejne potęgi podstawy systemu - w przykładzie podstawą jest liczba 10. Uogólniając ten przykład na system o dowolnej podstawie, otrzymamy wzór zamieniający liczę zapisaną w dowolnym systemie na zapis dziesiętny.
Jeżeli mamy liczbęC1..Cn
(C1..Cn - kolejne cyfry tej liczby) zapisaną w systemie o podstawieP
, to liczba ta zapisana w wystemie dziesiętnym wyniesieliczba10 = Cn⋅P0 + Cn-1⋅P1 + Cn-2⋅P2 +..+C1⋅Pn-1
Pętla foreach
Pętlę foreach
omówimy dopiero wtedy, kiedy poznamy tablice. Służy ona do wykonywania operacji na kolejnych elementach tablicy.
Jeżeli zapomniałeś jak przygotować i gdzie zapisywać pliki testowe: