POWRÓT NA STRONĘ SZKOŁY

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: