Lekcje >> Podstawy PHP
Polimax

Drukarnia w Warszawie realizująca druk wizytówek, plakatów jak również fotoksiążki, fotoobrazy i fotokalendarze - z wysyłką na terenie całego kraju.

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 podstawie P, to liczba ta zapisana w wystemie dziesiętnym wyniesie liczba10 = 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: