1_3.pdf
(
470 KB
)
Pobierz
Od zera do gier kodera
3
DZIAŁANIE PROGRAMU
Nic nie dzieje się wbrew naturze,
lecz wbrew temu, co o niej wiemy.
Fox Mulder w serialu „Z archiwum X”
Poznaliśmy już przedsmak uroków programowania w C++ i stworzyliśmy kilka własnych
programów. Opanowaliśmy jednocześnie najbardziej podstawowe podstawy podstaw
kodowania w tym języku :)
Możemy więc odkryć kolejne, ważne jego elementy, które pozwolą nam tworzyć bardziej
interesujące i przydatne programy. Przyszła bowiem pora na spotkanie z instrukcjami
sterującymi przebiegiem aplikacji i sposobem jej działania.
Funkcje nieco bliżej
Z funkcjami mieliśmy do czynienia już wcześniej. Powiedzieliśmy sobie wtedy, że są to
wydzielone fragmenty kodu realizujące jakąś czynność. Przytoczyłem przy tym dość
banalny przykład funkcji
PokazTekst()
, wyświetlającej w konsoli ustalony napis.
Niewątpliwie był on klarowny i ukazywał wspomniane tam przeznaczenie funkcji (czyli
podział kodu na fragmenty), jednakże pomijał dwa bardzo ważne aspekty z nimi
związane. Chodzi mianowicie o
parametry
oraz
zwracanie wartości
. Rozszerzają one
użyteczność i możliwości funkcji tak znacznie, że bez nich w zasadzie trudno wyobrazić
sobie skuteczne i efektywne programowanie.
W takiej sytuacji nie możemy wszak przejść obok nich obojętnie - niezwłocznie
przystąpimy zatem do poznawania tych arcyważnych zagadnień :)
Parametry funkcji
Nie tylko w programowaniu trudno wskazać operację, którą można wykonać bez
posiadania o niej dodatkowych informacji. Przykładowo, nie można wykonać operacji
kopiowania czy przesunięcia pliku do innego katalogu, jeśli nie jest znana nazwa tegoż
pliku oraz nazwa docelowego folderu.
Gdybyśmy napisali funkcję realizującą taką czynność, to nazwy pliku oraz katalogu
finalnego byłyby jej
parametrami
.
Parametry funkcji
to dodatkowe dane, przekazywane do funkcji podczas jej wywołania.
Parametry pełnią rolę dodatkowych zmiennych wewnątrz funkcji i można ich używać
podobnie jak innych zmiennych, zadeklarowanych w niej bezpośrednio. Różnią się one
oczywiście tym, że wartości parametrów pochodzą z „zewnątrz” – są im przypisywane
podczas wywołania funkcji.
78
Podstawy programowania
Po tym krótkim opisie czas na obrazowy przykład. Oto zmodyfikujemy nasz program
liczący tak, żeby korzystał z dobrodziejstw parametrów funkcji:
// Parameters - wykorzystanie parametrów funkcji
#include
<iostream>
#include
<conio.h>
void
Dodaj(
int
nWartosc1,
int
nWartosc2)
{
int
nWynik = nWartosc1 + nWartosc2;
std::cout << nWartosc1 <<
" + "
<< nWartosc2 <<
" = "
<< nWynik;
std::cout << std::endl;
}
void
main()
{
int
nLiczba1;
std::cout<<
"Podaj pierwsza liczbe: "
;
std::cin >> nLiczba1;
int
nLiczba2;
std::cout<<
"Podaj druga liczbe: "
;
std::cin >> nLiczba2;
Dodaj (nLiczba1, nLiczba2);
getch();
}
Rzut oka na działający program pozwala stwierdzić, iż wykonuje on taką samą pracę, jak
jego poprzednia wersja. Z kolei spojrzenie na kod ujawnia w nim widoczne zmiany –
przyjrzyjmy się im.
Zasadnicza czynność programu, czyli dodawanie dwóch liczb, została wyodrębniona w
postaci osobnej funkcji
Dodaj()
. Posiada ona dwa parametry
nWartosc1
i
nWartosc2
,
które są w niej dodawane do siebie i wyświetlane w konsoli.
Wielce interesujący jest w związku z tym nagłówek funkcji
Dodaj()
, zawierający
deklarację owych dwóch parametrów:
void
Dodaj(
int
nWartosc1,
int
nWartosc2)
Jak sam widzisz, wygląda ona bardzo podobnie do deklaracji zmiennych – najpierw
piszemy typ parametru, a następnie jego nazwę. Nazwa ta pozwala odwoływać się do
wartości parametru w kodzie funkcji, a więc na przykład użyć jej jako składnika sumy.
Określenia kolejnych parametrów oddzielamy od siebie przecinkami, zaś całą deklarację
umieszczamy w nawiasie po nazwie funkcji.
Wywołanie takiej funkcji jest raczej oczywiste:
Dodaj (nLiczba1, nLiczba2);
Podajemy tu w nawiasie kolejne
wartości
, które zostaną przypisane jej parametrom;
oddzielamy je tradycyjnie już przecinkami. W niniejszym przypadku parametrowi
nWartosc1
zostanie nadana wartość zmiennej
nLiczba1
, zaś
nWartosc2
–
nLiczba2
.
Myślę, że jest to dość intuicyjne i nie wymaga więcej wyczerpującego komentarza :)
***
Działanie programu
79
Reasumując: parametry pozwalają nam przekazywać funkcjom dodatkowe dane, których
mogą użyć do wykonania swoich działań. Ilość, typy i nazwy parametrów deklarujemy w
nagłówku funkcji, zaś podczas jej wywoływania podajemy ich wartości w analogiczny
sposób.
Wartość zwracana przez funkcję
Spora część funkcji pisanych przez programistów ma za zadanie obliczenie jakiegoś
wyniku (często na podstawie przekazanych im parametrów). Inne z kolei wykonują
operacje, które nie zawsze muszą się udać (choćby usunięcie pliku – dany plik może
przecież już nie istnieć).
W takich przypadkach istnieje więc potrzeba, by funkcja
zwróciła
jakąś
wartość
.
Niekiedy będzie to rezultat jej intensywnej pracy, a innym razem jedynie informacja, czy
zlecona funkcji czynność została wykonana pomyślnie.
Zgodnie ze zwyczajem, popatrzymy teraz na odpowiedni program przykładowy
17
:
) Pyta
on użytkownika o długości boków prostokąta, wyświetlając w zamian jego pole
powierzchni oraz obwód. Czyni to ten kod (jest to fragment funkcji
main()
):
// ReturnValue - funkcje zwracające wartość
int
nDlugosc1;
std::cout <<
"Podaj dlugosc pierwszego boku: "
;
std::cin >> nDlugosc1;
int
nDlugosc2;
std::cout <<
"Podaj dlugosc drugiego boku: "
;
std::cin >> nDlugosc2;
std::cout <<
"Obwod prostokata: "
<< Obwod(nDlugosc1, nDlugosc2) <<
std::endl;
std::cout <<
"Pole prostokata: "
<< Pole(nDlugosc1, nDlugosc2) <<
std::endl;
getch();
Linijki wyświetlające gotowy wynik zawierają wywołania dwóch funkcji –
Obwod()
i
Pole()
. Można je umieścić w tym miejscu, gdyż zwracają one wartości – w dodatku te,
które chcemy zaprezentować :) Wyświetlamy je dokładnie w ten sam sposób jak wartości
zmiennych i wszystkich innych wyrażeń liczbowych.
Cała istota działania aplikacji zawiera się więc w tych dwóch funkcjach. Prezentują się
one następująco:
int
Obwod(
int
nBok1,
int
nBok2)
{
return
2
* (nBok1 + nBok2);
}
int
Pole(
int
nBok1,
int
nBok2)
{
return
nBok1 * nBok2;
}
Cóż ciekawego możemy o nich rzec? Widoczną różnicą w stosunku do dotychczasowych
przykładów funkcji, jakie mieliśmy okazję napotkać, jest chociażby zastąpienie słówka
17
Całość programu jest dołączona do tutoriala, tutaj zaprezentujemy tylko jego najważniejsze fragmenty
80
Podstawy programowania
void
przez nazwę typu,
int
. To oczywiście nie przypadek – w taki właśnie sposób
informujemy kompilator, iż nasza funkcja ma zwracać wartość oraz wskazujemy jej typ.
Kod funkcji to tylko jeden wiersz, zaczynający się od
return
(‘powrót’). Określa on ni
mniej, ni więcej, jak tylko ową wartość, która będzie zwrócona i stanie się wynikiem
działania funkcji. Rezultat ten zobaczymy w końcu i my w oknie konsoli:
Screen 15. Miernik prostokątów w akcji
return
powoduje jeszcze jeden efekt, który nie jest tu tak wyraźnie widoczny. Użycie tej
instrukcji skutkuje mianowicie natychmiastowym
przerwaniem
działania funkcji i
powrotem do miejsca jej wywołania. Wprawdzie nasze proste funkcje i tak kończą się
niemal od razu, więc nie ma to większego znaczenia, jednak w przypadku poważniejszych
podprogramów należy o tym fakcie pamiętać.
Wynika z niego także możliwość użycia
return
w funkcjach niezwracających żadnej
wartości – można je w ten sposób przerwać, zanim wykonają swój kod w całości.
Ponieważ nie mamy wtedy żadnej wartości do zwracania, używamy samego słowa
return
;
- bez wskazywania nim jakiegoś wyrażenia.
***
Dowiedzieliśmy się zatem, iż funkcja może zwracać wartość jako wynik swej pracy.
Rezultat taki winien być określonego typu – deklarujemy go w nagłówku funkcji jeszcze
przed jej nazwą. Natomiast w kodzie funkcji możemy użyć instrukcji
return
, by wskazać
wartość będącą jej wynikiem. Jednocześnie instrukcja ta spowoduje zakończenie
działania funkcji.
Składnia funkcji
Gdy już poznaliśmy zawiłości i niuanse związane z używaniem funkcji w swoich
aplikacjach, możemy tą wydatną porcję informacji podsumować ogólnymi regułami
składniowymi dla podprogramów w C++. Otóż postać funkcji w tym języku jest
następująca:
typ_zwracanej_wartości
/
void
nazwa_funkcji
(
[
typ_parametru
nazwa
, ...
]
)
{
instrukcje_1
return
wartość_funkcji_1
;
instrukcje_2
return
wartość_funkcji_2
;
instrukcje_3
return
wartość_funkcji_3
;
...
return
wartość_funkcji_n
;
}
Jeżeli dokładnie przestudiowałeś (i zrozumiałeś! :)) wiadomości z tego paragrafu i z
poprzedniego rozdziału, nie powinna być ona dla ciebie żadnym zaskoczeniem.
Działanie programu
81
Zauważ jeszcze, ze fraza
return
może występować kilka razy, zwracać w każdym z
wariantów
różne
wartości, a całość funkcji mieć logiczny sens i działać poprawnie. Jest to
możliwe między innymi dzięki instrukcjom warunkowym, które poznamy już za chwilę.
***
W ten oto sposób uzyskaliśmy bardzo ważną umiejętność programistyczną, jaką jest
poprawne używanie funkcji we własnych programach. Upewnij się przeto, iż skrupulatnie
przyswoiłeś sobie informacje o tym zagadnieniu, jakie serwowałem w aktualnym i
poprzednim rozdziale. W dalszej części kursu będziemy często korzystać z funkcji w
przykładowych kodach i omawianych tematach, dlatego ważne jest, byś nie miał
kłopotów z nimi.
Jeśli natomiast czujesz się na siłach i chcesz dowiedzieć czegoś więcej o funkcjach,
zajrzyj do
pomocy MSDN
zawartej w Visual Studio.
Sterowanie warunkowe
Dobrze napisany program powinien być przygotowany na każdą ewentualność i
nietypową sytuację, jaka może się przydarzyć w czasie jego działania. W niektórych
przypadkach nawet proste czynności mogą potencjalnie kończyć się niepowodzeniem, zaś
porządna aplikacja musi radzić sobie z takimi drobnymi (lub całkiem sporymi) kryzysami.
Oczywiście program nie uczyni nic, czego nie przewidziałby jego twórca. Dlatego też
ważnym zadaniem programisty jest opracowanie kodu reagującego odpowiednio na
nietypowe sytuacje, w rodzaju błędnych danych wprowadzonych przez użytkownika lub
braku pliku potrzebnego aplikacji do działania.
Możliwe są też przypadki, w których dla kilku całkowicie poprawnych sytuacji, danych itp.
trzeba wykonać zupełnie inne operacje. Ważne jest wtedy rozróżnienie tych wszystkich
wariantów i skierowanie działania programu na właściwe tory, gdy ma miejsce któryś z
nich.
Do wszystkich tych zadań stworzono w C++ (i w każdym języku programowania) zestaw
odpowiednich narzędzi, zwanych
instrukcjami warunkowymi
. Ich przeznaczeniem jest
właśnie dokonywanie różnorakich wyborów, zależnych od ustalonych
warunków
.
Jak widać, przydatność tych konstrukcji jest nadspodziewanie duża, żal byłoby więc
ominąć je bez wnikania w ich szczegóły, prawda? :) Niezwłocznie zatem zajmiemy się
nimi, poznając ich składnię i sposób funkcjonowania.
Instrukcja warunkowa
if
Instrukcja
if
(‘jeżeli’) pozwala wykonać jakiś kod tylko wtedy, gdy spełniony jest
określony warunek. Jej działanie sprowadza się więc do sprawdzenia tegoż warunku i,
jeśli zostanie stwierdzona jego prawdziwość, wykonania wskazanego bloku kodu.
Tę prostą ideę może ilustrować choćby taki przykład:
// SimpleIf – prosty przykład instrukcji if
void
main()
{
int
nLiczba;
std::cout<<
"Wprowadz liczbe wieksza od 10: "
;
std::cin >> nLiczba;
Plik z chomika:
forestek1
Inne pliki z tego folderu:
1_1.pdf
(430 KB)
1_4.pdf
(685 KB)
1_2.pdf
(475 KB)
1_3.pdf
(470 KB)
1_5.pdf
(816 KB)
Inne foldery tego chomika:
Prata
Symfonia C++ Standard. Wyd I 2005. Jerzy Grębosz
Zgłoś jeśli
naruszono regulamin