User Tools

Site Tools


dydaktyka:cprog:2015:conditionals

This is an old revision of the document!


Pętla "for", instrukcje warunkowe, operatory relacyjne i logiczne

Cel laboratorium

  • Zapoznanie z pętlą for.
  • Zapoznanie z instrukcją warunkową if oraz jej wariantami (if-else, if-else if-else).
  • Budowanie warunków z użyciem operatorów relacyjnych i logicznych.
  • Usystematyzowanie pojęć: instrukcja, wyrażenie, operator, operand.
  • Wprowadzenie pojęcia blok instrukcji.
  • Wprowadzenie nowego operatora: % (modulo).

Operatory relacyjne

Oprócz operatorów arytmetycznych istnieją również operatory, które stosuje się do porównywania danych – podobnie jak w matematyce.

Poniższa tabela zestawia operatory relacyjne i podaje ich znaczenie (zwróć szczególną uwagę na operator równy oraz różny):

Operator Opis
== równy
> większy
< mniejszy
>= większy lub równy
<= mniejszy lub równy
!= różny

Wynik relacji fałszywej wynosi zawsze 0.
Wynik relacji prawdziwej wynosi zawsze 1.

:!: Język C nie udostępnia typu logicznego (o wartościach prawda i fałsz); zamiast tego reprezentuje te wartości korzystając z typu int.


Przykład użycia operatorów relacyjnych:

#include <stdio.h>
 
int main(void)
{
    int a = 12;
    int b = 34567;
    int r1 = (a < b);
    int r2 = (a == b);
 
    printf("a < b  = %d\n", r1);
    printf("a == b = %d\n", r2);
 
    return 0;
}

Pętla "for"

Pętla for (ang. dla) pozwala na wykonywanie fragmentu programu określoną ilość razy.

Wykorzystuje ona trzy wyrażenia rozdzielone średnikami:

  • inicjalizacja licznika – wykonywane jeden raz, zaraz przed pierwszą iteracją (obiegiem pętli)
  • warunek – obliczany przed każdym potencjalnym wykonaniem pętli (jeśli wyrażenie to jest fałszywe, pętla zostaje zakończona)
  • zmiana (aktualizacja) – obliczane na końcu każdej iteracji

Pętla for kończy się jedną instrukcją prostą lub złożoną.

Pętla for to “pętla z warunkiem wejścia”, co oznacza że pętla może nie wykonać się ani razu, jeśli na samym początku warunek nie został spełniony.

Ogólna postać pętli for:

for (inicjalizacja; test; aktualizacja)
    instrukcja

Przykład 1 – Wielokrotne wypisywanie na ekran

#include <stdio.h>
 
int main()
{
    int i;
 
    for(i = 1; i <= 10; i = i + 1) {
        printf("%d\n", i);
    }
 
    return 0;
}

Przykład 2 – Obliczanie silnii

silnia.c
#include <stdio.h>
 
int main()
{
    int s, n, i;
 
    printf("Podaj liczbę naturalną n: ");
    scanf("%d", &n);
 
    s = 1;
    for(i = 2; i <= n; i = i + 1) {
        s = s * i;
    }
 
    printf("%d! = %d\n", n, s);
 
    return 0;
}

Zadanie 1
Napisz program, który oblicza sumę liczb całkowitych z zakresu od 1 do 10 przy pomocy pętli for.
Oczekiwany wynik: 55

Zadanie 2
Napisz program, który wczytuje zadane przez użytkownika dwie liczby całkowite ($a$ i $b$) i oblicza sumę liczb z przedziału $\langle a, b \rangle$. Z góry załóż, że $a \leq b$ – nie sprawdzaj tego w programie.
Przykład: Dla liczb $a = 3, b = 5$ poprawnym wynikiem jest $3+4+5=12$.

Instrukcja warunkowa "if"

Często chcemy, aby działanie programu zależało od pewnego warunku, na przykład “jeśli dzielnik wynosi 0, to wyświetl komunikat o błędzie, w przeciwnym razie oblicz wartość dzielenia”. Do realizacji takich zadań służy m.in. instrukcja warunkowa if.

Instrukcja warunkowa podejmuje decyzję “którą instrukcję wykonać w następnej kolejności” na podstawie wartości wyrażenia podanego w warunku . Bardzo często jako warunku używa się wyrażenia relacyjnego.

:!: W języku C warunek uznawany jest za spełniony (prawdziwy), jeśli jego wartość jest różna od 0 (a więc niekoniecznie wynosi 1!).

Ogólna postać instrukcji if:

if (wyrażenie)
    instrukcja

Przykład 1

#include <stdio.h>
 
int main()
{
    int wiek = 60;
 
    if(wiek > 50) {
        printf("Warunek spelniony - osoba ma ponad 50 lat.\n");
    }
 
    if(wiek == 50) {
        printf("Warunek spelniony - osoba ma rowno 50 lat.\n");
    }
 
    return 0;
}

PS. Po co te “wąsiki”? - Przeczytaj kolejny fragment laboratorium.

:!: Uwaga
Programistom zdarza się przez nieuwagę zamiast == napisać =. Ponieważ wartość wyrażenia przypisania wynosi tyle, co przypisywana wartość – czyli to, co stoi po prawej stronie – stąd wyrażenie to jest prawdziwe gdy tylko przypisujemy dowolną wartość różną od 0:

#include <stdio.h>
 
int main()
{
    int wiek = 60;
 
    if(wiek > 50) {
        printf("Warunek spelniony - osoba ma ponad 50 lat.\n");
    }
 
    if(wiek = 50) { // czy na pewno chodzilo o operator przypisania '='?
        printf("Warunek spelniony - osoba ma rowno 50 lat.\n");
    }
 
    if(wiek = 0) { // czy na pewno chodzilo o operator przypisania '='?
        printf("Warunek spelniony - osoba dopiero sie urodzila.\n");
    }
 
    return 0;
}

Blok instrukcji

Blok instrukcji (inaczej: instrukcja złożona) to przynajmniej dwie instrukcje scalone ze sobą poprzez zawarcie ich w nawiasach klamrowych: { }
Blok instrukcji jest traktowany przez kompilator jak pojedyncza instrukcja.

Porównaj działanie poniższych programów:

if_without_block.c
#include <stdio.h>
 
int main()
{
    int wiek = 16;
 
    // nie ma klamer
    if(wiek > 18)
        printf("Osoba jest pelnoletnia.\n");
        printf("Osoba moze wyrobic dowod osobisty.\n");
 
    return 0;
}
if_with_block.c
#include <stdio.h>
 
int main()
{
    int wiek = 16;
 
    // sa klamry
    if(wiek > 18) {
        printf("Osoba jest pelnoletnia.\n");
        printf("Osoba moze wyrobic dowod osobisty.\n");
    }
 
    return 0;
}

Instrukcja warunkowa if w przypadku spełnienia warunku wykonuje tylko jedną instrukcję, znajdującą się bezpośrednio za if-em.
W przypadku pierwszego programu (mimo wcięć w kodzie) instrukcja if obejmuje tylko pierwsze wywołanie funkcji printf().
W drugim przypadku umieszczenie obu instrukcji printf() w bloku kodu pozwala na wykonanie ich obu w przypadku spełnienia warunku.

Instrukcja warunkowa "if-else"

Często chcemy, aby działanie programu zależało od pewnego warunku, na przykład “jeśli dzielnik wynosi 0, to wyświetl komunikat o błędzie, w przeciwnym razie oblicz wartość dzielenia”. Do realizacji takich zadań służy m.in. instrukcja warunkowa if-else (ang. elsew przeciwnym razie).

Ogólna postać instrukcji if-else:

if (wyrażenie)
    instrukcja1
else
    instrukcja2

Jeśli warunek jest prawdą, wykonywana jest instrukcji następująca po słowie kluczowym if (czyli instrukcja1).
W przeciwnym razie wykonywana jest instrukcja po słowie kluczowym else (czyli instrukcja2).


Przykład 1

#include <stdio.h>
 
int main()
{
    int wiek = 40;
 
    if (wiek > 50) {
        printf("Warunek spelniony - osoba ma ponad 50 lat.\n");
    } else {
        printf("Warunek nie byl spelniony - zatem osoba nie ma wiecej niz 50 lat.\n");
    }
 
    return 0;
}

Przykład 2 - Zagnieżdżanie instrukcji

#include <stdio.h>
 
int main()
{
    int wiek = 40;
 
    if (wiek > 50) {
        if (wiek > 70) {
            printf("Osoba ma ponad 70 lat.\n");
        } else {
            printf("Osoba ma ponad 50, lecz mniej niz 70 lat.\n");
        }
    } else {
        printf("Osoba nie ma wiecej niz 50 lat.\n");
    }
 
    return 0;
}

PS. Za moment poznasz sposoby na zapisanie tego w bardziej czytelny sposób…

Instrukcja warunkowa "if-else if-else"

Zdarza się, że chcemy niejako wybrać spośród jednej z kilku możliwości – na przykład aby określić ilość miejsc zerowych równania kwadratowego rozpatrujemy trzy przypadki: $\Delta > 0$, $\Delta = 0$ oraz $\Delta < 0$.

Do realizacji takiego zadania służy instrukcja if-else if-else o ogólnej postaci:

if (wyrażenie1)
    instrukcja1
else if (wyrażenie2)
    instrukcja2
...
else if (wyrażenie_n-1)
    instrukcja_n-1
else
    instrukcja_n

Jeśli pierwszy warunek jest prawdą, wykonywana jest instrukcja instrukcja1.
W przeciwnym razie, jeśli prawdziwe jest drugie wyrażenie, wykonaj instrukcję instrukcja2 – i tak dalej.
Jeśli żaden z warunków nie został spełniony, wykonaj instrukcję po else (czyli instrukcję instrukcja_n).


Przykład

Aby uczynić program do weryfikacji wieku bardziej czytelnym możemy napisać:

#include <stdio.h>
 
int main()
{
    int wiek = 40;
 
    if (wiek > 70) {
        printf("Osoba ma ponad 70 lat.\n");
    } else if (wiek > 50) {
        printf("Osoba ma ponad 50, lecz mniej niz 70 lat.\n");
    } else {
        printf("Osoba nie ma wiecej niz 50 lat.\n");
    }
 
    return 0;
}

Operatory logiczne

Operatory logiczne języka C pozwalają na łączenie operatorów relacyjnych w bardziej efektywne instrukcje służące do testowania danych. Poniższa tabela przedstawia operatory logiczne:

operator opis odpowiednik w algebrze Boole'a przykład
&& i (AND) $\wedge$ a && b
|| lub (OR) $\vee$ a || b
! nie (NOT) $\neg$ !a

:!: Wynik relacji prawdziwej wynosi zawsze 1, a fałszywej – 0.


Przykład
Poniższy kod sprawdza wartość logiczną wyrażenia $\neg (a < b \wedge b > c)$:

#include <stdio.h>
 
int main()
{
    int a = 1;
    int b = 12;
    int c = 100;
 
    printf("%d\n", !((a < b) && (b > c)));
 
   return 0;
}

Instrukcja, operator, wyrażenie...

Przez ostatnie dwa laboratoria używaliśmy wielu pojęć, które są dla Ciebie prawdopodobnie obce. Teraz, gdy już masz pewną intuicję co do działania pewnych konstrukcji języka C, możemy je odrobinę dokładniej zdefiniować.


Operator

W języku C pewne operacje (np. działania matematyczne) wyrażane są za pomocą operatorów. Na przykład, operator + powoduje zsumowanie wartości znajdujących się po jeo obydwu stronach.
Skąd nazwa “operator”? Hm… może po prostu brzmi lepiej niż “ta rzecz”?

Operand

Operand to “coś”, czym posługują się operatory. Na przykład dla operatora dzielenia (/) lewym operandem jest dzielna, a prawym – dzielnik.

Wyrażenie

Wyrażenie (expression) to kombinacja operatorów i operandów. Każde wyrażenie w języku C ma wartość.

Oto kilka przykładów wyrażeń:

wyrażenie wartość
4 4
-6 -6
4 + 21 25
a * (b + c / d) / 20 (zależy od wartości a, b i c)
q = 5 * 2 10
7 > 3 1

Instrukcja

Najprościej mówiąc – instrukcja (statement) to wyrażenie, na końcu krórego znajduje się średnik.
Zatem a = 5 jest wyrażeniem, natomiast a = 5; to już instrukcja.

Program komputerowy składa się głównie właśnie z instrukcji.

Oto przykłady instrukcji:

#include <stdio.h>
 
int main()
{
    int a;
 
    a = 1;  // instrukcja przypisania
 
    if (a > 4) {    // instrukcja warunkowa
        printf("%d\n", a);  // instrukcja wywołania funkcji
    }
 
   return 0;
}

Być może zastanawiasz się: Jak to if jest instrukcją? Przecież nie ma na końcu średnika!
Odpowiedź brzmi – blok instrukcji traktowany jest jak jednak instrukcja.

:!: Sam średnik również oznacza instrukcję – instrukcję pustą – zatem poniższy program jest poprawny, choć niekoniecznie robi to, co zapewne miał robić w zamierzeniu jego twórcy:

#include <stdio.h>
 
int main()
{
    int a = 3;
 
    // Oblicz wartosc bezwzgledna liczby 'a'
    if (a < 0);
        a = -a;
 
    printf("%d\n", a);
 
    return 0;
}

Jeśli program nie działa tak, jak oczekujesz, sprawdź czy na końcu linii z if albo for nie znalazł się przypadkiem średnik.
Z drugiej strony tę właściwość można ciekawie wykorzystać - patrz: idiom do czyszczenia bufora wejściowego.


Zadania podsumowujące

Zadanie 1

(poziom trudności: )

Napisz program, który poda ilość rozwiązań równania kwadratowego dla zadanych przez użytkownika współczynników $a$, $b$ i $c$.

Zadanie 2

(poziom trudności: )

Napisz program, który sprawdzi czy zadana przez użytkownika liczba jest liczbą parzystą i wypisze odpowiedni komunikat.
Wskazówka: Podczas rozwiązywania tego zadania może Ci się przydać operator modulo (%), który zwraca resztę z dzielenia, np. wyrażenie 5 % 3 ma wartość 2.

Zadanie 3

(poziom trudności: )

Napisz program sprawdzający w naiwny sposób (czyli: najprostszy), czy zadana przez użytkownika liczba jest liczbą pierwszą.
Wykorzystaj pętlę for i operator modulo (%).

dydaktyka/cprog/2015/conditionals.1445515283.txt.gz · Last modified: 2020/03/25 11:46 (external edit)