Serwis Edukacyjny
w I-LO w Tarnowie
obrazek

Materiały dla uczniów liceum

  Wyjście       Spis treści       Wstecz       Dalej  

Autor artykułu: mgr Jerzy Wałaszek

©2021 mgr Jerzy Wałaszek
I LO w Tarnowie

obrazek

Materiały dla klasy II

Pętla iteracyjna

SPIS TREŚCI

Pętla for

Obieg iterowany jest to obieg, który posiada swój numer. Przez iterowanie rozumiemy wykonywanie w programie obiegów numerowanych. Pętla iteracyjna jest pętlą, która numeruje kolejno wykonane obiegi. Numer obiegu przechowywany jest w zmiennej zwanej licznikiem pętli (ang. loop counter). Pętlę iteracyjną można w prosty sposób zbudować przy pomocy pętli warunkowej typu while. Uruchom poniższy program:
// Pętla warunkowa
//----------------

#include <iostream>

using namespace std;

int main()
{
  setlocale(LC_ALL,"");

  int i = 1; // licznik pętli

  while (i <= 20)
  {
    cout << "Nr obiegu pętli: " << i << endl;
    i++;
  }

  return 0;
}

Zwróć uwagę na charakterystyczną budowę tej pętli:

int i = 1;   czynności przygotowawcze, najczęściej inicjalizacja licznika pętli, wykonywane przed pętlą
while(i <= 20)   sprawdzenie warunku kontynuacji, wykonywane na początku każdego obiegu
cout << ...   instrukcja wykonywana w każdym obiegu
i++   modyfikacja licznika pętli, wykonywana na końcu każdego obiegu

Ponieważ pętle iteracyjne są bardzo częstym elementem programów w języku C++, istnieje instrukcja, która ułatwia ich stosowanie. Jest to instrukcja for o następującej składni:

for(a; b; c) instrukcja;

lub w postaci blokowej:

for(a; b; c)
{
    instrukcja_1;
    instrukcja_2;
    ...
    instrukcja_n;
}
a czynności przygotowawcze przed pętlą
b warunek kontynuacji sprawdzany przed każdym obiegiem pętli
c czynności wykonywane na końcu każdego obiegu pętli

Instrukcja for działa następująco:

Najpierw komputer wykonuje operację określoną przez parametr a. Najczęściej jest to przypisanie wartości początkowej zmiennej, która będzie pełniła rolę licznika pętli. Operacja ta jest wykonywana jednokrotnie przed rozpoczęciem pętli. Następnie komputer zaczyna wykonywać obiegi iterowane. Przed każdym obiegiem sprawdzany jest warunek b. Jeśli ma on wartość różną od zera, to obieg zostanie wykonany. Inaczej pętla zakończy działanie. W każdym obiegu jest wykonywana podana instrukcja (lub instrukcje w bloku). Na końcu każdego obiegu wykonywane jest działanie określone parametrem c. Najczęściej jest to operacja modyfikacji licznika pętli, aby w następnym obiegu miał inną wartość.

Instrukcja for grupuje w jednym miejscu wszystkie elementy sterujące wykonywaniem pętli iteracyjnej. Poniżej mamy poprzedni program w wersji z pętlą for:

// Pętla iteracyjna
//-----------------

#include <iostream>

using namespace std;

int main()
{
  setlocale(LC_ALL,"");

  int i; // licznik pętli

  for(i = 1; i <= 20; i++)
    cout << "Nr obiegu pętli: " << i << endl;

  return 0;
}

Jak widzisz, program jest krótszy i bardziej zwarty. Gdy nabierzesz wprawy, to okaże się, że stosowanie for zamiast while zwiększa czytelność programu.

Pobawmy się trochę pętlami iteracyjnymi. Numery obiegów nie muszą być kolejnymi liczbami naturalnymi: licznik pętli możesz modyfikować w dowolny sposób:

// Pętla iteracyjna
//-----------------

#include <iostream>

using namespace std;

int main()
{
  setlocale(LC_ALL,"");

  int i; // licznik pętli

  for(i = 1; i <= 20; i = i + 2)
    cout << "Nr obiegu pętli: " << i << endl;

  return 0;
}

Licznik pętli możesz wykorzystywać do kontrolowania liczby obiegów, które wykona pętla:

// Pętla iteracyjna
//-----------------

#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
  setlocale(LC_ALL,"");

  int i;     // licznik pętli
  int p = 1; // potęgi liczby 2

  for(i = 1; i <= 31; i++)
  {
      cout << "2^"
           << setw(2)  << i
           << " = "
           << setw(10) << p << endl;
      p = p + p;
  }

  return 0;
}

Pętlę for można wykorzystać również jako pętlę warunkową, którą w sumie jest (instrukcja for jest wewnętrznie rozwijana w odpowiednią pętlę while).

Uruchom program:
// Pętla iteracyjna
//-----------------

#include <iostream>

using namespace std;

int main()
{
  setlocale(LC_ALL,"");

  int i;     // liczby nieparzyste
  int g;     // granica sumowania
  int s = 0; // suma

  cout << "Podaj granicę sumowania liczb nieparzystych: ";
  cin  >> g;
  cout << endl;

  for(i = 1; s < g; i = i + 2)
    s = s + i; // Tworzymy sumę

  cout << "Suma liczb nieparzystych od 1 do " << i - 2
       << " przekracza granicę " << g
       << " i wynosi " << s << endl;

  return 0;
}

Program sumuje kolejne liczby nieparzyste, aż ich suma przekroczy zadaną granicę. Zwróć uwagę, że warunek kontynuacji nie jest związany z wartością licznika pętli (może to być dowolny warunek logiczny) . Otrzymujemy zatem normalną pętlę warunkową.


Niepotrzebne elementy w obszarze sterowania pętli for można pominąć, jednak należy zachować średniki. Pominięcie warunku kontynuacji spowoduje, że pętla będzie się wykonywała w nieskończoność (tzn. aż zatrzymamy program kombinacją klawiszy Ctrl+C).

// Pętla iteracyjna
//-----------------

#include <iostream>

using namespace std;

int main()
{
  unsigned i = 0;

  setlocale(LC_ALL,"");

  for(; ; i++) cout << i << " ";

  return 0;
}
 
Na początek:  podrozdziału   strony 

Pętle zagnieżdżone

Poniższy fragment programu wypisuje wiersz zbudowany z 20 znaków X:

for(i = 0; i < 20; i++) cout << "X";
cout << endl;

Jeśli powtórzymy ten fragment programu 20 razy, to otrzymamy kwadrat z literek X. Instrukcją powtarzaną w pętli może być druga pętla - otrzymamy wtedy układ pętli zagnieżdżonych:

for(j = 0; j < 20; j++)
{
    for(i = 0; i < 20; i++) cout << "X";
    cout << endl;
}

Pętla wewnętrzna jest sterowana zmienną i. Jej zadaniem jest wyświetlenie jednego wiersza z 20 znaków X. Pętla ta jest powtarzana 20 razy przez pętlę zewnętrzną sterowaną zmienną j. W efekcie w oknie konsoli pojawia się 20 wierszy, każdy zbudowany z 20 literek X:

XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX

W pętlach zagnieżdżonych muszą być stosowane różne zmienne liczników pętli.

Jeśli ilość wykonań pętli wewnętrznej uzależnimy od numeru obiegu pętli zewnętrznej, to otrzymamy trójkąt:

for(j = 0; j < 20; j++)
{
    for(i = 0; i <= j; i++) cout << "X";

    cout << endl;
}
X
XX
XXX
XXXX
XXXXX
XXXXXX
XXXXXXX
XXXXXXXX
XXXXXXXXX
XXXXXXXXXX
XXXXXXXXXXX
XXXXXXXXXXXX
XXXXXXXXXXXXX
XXXXXXXXXXXXXX
XXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX

Zastanów się, jak zmienić podane pętle, aby uzyskać następujące wydruki w oknie konsoli:

XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXX
XXXXXXXXXXXXXX
XXXXXXXXXXXXX
XXXXXXXXXXXX
XXXXXXXXXXX
XXXXXXXXXX
XXXXXXXXX
XXXXXXXX
XXXXXXX
XXXXXX
XXXXX
XXXX
XXX
XX
X
                        X
                  XX
                 XXX
                XXXX
               XXXXX
              XXXXXX
             XXXXXXX
            XXXXXXXX
           XXXXXXXXX
          XXXXXXXXXX
         XXXXXXXXXXX
        XXXXXXXXXXXX
       XXXXXXXXXXXXX
      XXXXXXXXXXXXXX
     XXXXXXXXXXXXXXX
    XXXXXXXXXXXXXXXX
   XXXXXXXXXXXXXXXXX
  XXXXXXXXXXXXXXXXXX
 XXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX
     XXXXXXXXXXXXXXXXXXXX
 XXXXXXXXXXXXXXXXXXX
  XXXXXXXXXXXXXXXXXX
   XXXXXXXXXXXXXXXXX
    XXXXXXXXXXXXXXXX
     XXXXXXXXXXXXXXX
      XXXXXXXXXXXXXX
       XXXXXXXXXXXXX
        XXXXXXXXXXXX
         XXXXXXXXXXX
          XXXXXXXXXX
           XXXXXXXXX
            XXXXXXXX
             XXXXXXX
              XXXXXX
               XXXXX
                XXXX
                 XXX
                  XX
                   X
Na początek:  podrozdziału   strony 

Funkcje logiczne

W wyrażeniach możemy stosować funkcje logiczne, których w języku C++ mamy trzy:

NIE - Negacja/Zaprzeczenie logiczne (ang. NOT)

w !w
0 1
1 0

Jest to funkcja jednoargumentowa, której argumentem jest wyrażenie w. Wynikiem jest wartość przeciwna do wartości logicznej wyrażenia w.

LUB - Alternatywa/Suma logiczna (ang. OR)

w1 w2 w1 || w2
0 0 0
0 1 1
1 0 1
1 1 1

Jest to funkcja dwuargumentowa. Wynik jest równy true tylko wtedy, gdy dowolny z argumentów jest prawdziwy (ma wartość różną od zera). Jeśli oba argumenty są fałszywe (równe zero), to wynikiem jest false. Nazwa suma logiczna pochodzi z podobieństwa wyniku tej funkcji do operacji dodawania liczb nieujemnych. Suma dwóch liczb nieujemnych jest różna od 0, jeśli dowolna z sumowanych liczb jest różna od 0. Suma wynosi 0, jeśli oba argumenty są równe 0.

I - Koniunkcja/Iloczyn logiczny (ang. AND)

w1 w2 w1 && w2
0 0 0
0 1 0
1 0 0
1 1 1

Jest to funkcja dwuargumentowa. Wynik jest równy true tylko wtedy, gdy oba argumenty są prawdziwe (różne od zera). W przeciwnym razie wynik jest równy false. Nazwa iloczyn logiczny pochodzi z podobieństwa wyniku tej funkcji do operacji mnożenia. Wynik mnożenia jest niezerowy, jeśli wszystkie mnożone liczby są niezerowe.

Funkcje logiczne można łączyć:

a || b || c || d
a && b && c && d
a && (b || c)
!(a || b && c)

Wykorzystując funkcję LUB utwórz pętle, które tworzą następujące wydruki (zastanów się dla jakich wartości zmiennych i,j  ma być wyświetlana spacja lub znak X):

XXXXXXXXXXXXXXXX
X              X
X              X
X              X
X              X
X              X
X              X
X              X
X              X
X              X
X              X
X              X
X              X
X              X
X              X
XXXXXXXXXXXXXXXX
    XXXXXXXXXXXXXXXX
XX             X
X X            X
X  X           X
X   X          X
X    X         X
X     X        X
X      X       X
X       X      X
X        X     X
X         X    X
X          X   X
X           X  X
X            X X
X             XX
XXXXXXXXXXXXXXXX
    XXXXXXXXXXXXXXXX
X             XX
X            X X
X           X  X
X          X   X
X         X    X
X        X     X
X       X      X
X      X       X
X     X        X
X    X         X
X   X          X
X  X           X
X X            X
XX             X
XXXXXXXXXXXXXXXX
    XXXXXXXXXXXXXXXX
XX            XX
X X          X X
X  X        X  X
X   X      X   X
X    X    X    X
X     X  X     X
X      XX      X
X      XX      X
X     X  X     X
X    X    X    X
X   X      X   X
X  X        X  X
X X          X X
XX            XX
XXXXXXXXXXXXXXXX
Na początek:  podrozdziału   strony 

Zespół Przedmiotowy
Chemii-Fizyki-Informatyki

w I Liceum Ogólnokształcącym
im. Kazimierza Brodzińskiego
w Tarnowie
ul. Piłsudskiego 4
©2021 mgr Jerzy Wałaszek

Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone
pod warunkiem podania źródła oraz niepobierania za to pieniędzy.

Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl

Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.

Informacje dodatkowe.