Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
Paweł Boiński
PDF by tommy@tommy.ltd.pl
Kurs języka C++
1
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
Język C++ jest jednym z najbardziej popularnych języków używanych przez
programistów na całym świecie. O jego uniwersalności świadczy przede wszystkim
zróżnicowanie pisanych w nim programów. Mimo dość zaawansowanego już wieku
języka C jego nowa wersja czyli C++ nadal się rozwija. Niepodważalną zaletą tego
języka jest jego prostota oraz obiektowość rozumiana w szerokim sensie. Nie przez
przypadek to języki obiektowo zorientowane zawojowały i podbiły rynek
programistyczny. Wszystkich zapraszam do przeczytania tego kursu i zapewniam, że
pomoże on wam w pisaniu efektownych i efektywnych programów.
Kurs podzielony jest na rozdziały. Każdy z nich dotyczy nowego zagadnienia. Uwaga!!!
Nie rezygnuj z kontynuowania nauki po przeczytaniu pierwszych kilku rozdziałów!!! Być
może wydadzą Ci się one trochę nudne, są jednak koniecznym wprowadzeniem do
pisania programów. Dotyczą one przede wszystkim podstaw języka C i C++. Jeżeli
pisałeś już programy w C (lub C++) to możesz je pominąć. Zachęcam jednak do
przejrzenia ich - być może znajdziesz coś o czym zapomniałeś, a z pewnością
odświeżysz sobie pamięć.
Moja przygoda z programowaniem zaczęła się od języka BASIC, którego możecie nie
pamiętać. Były to czasy gdy światem komputerowym "rządziły" takie maszyny jak
Commodore 64, Atari XT, ZX Spectrum. Moim kolejnym krokiem było zapoznanie się z
językiem Pascal, potem Turbo Pascal, a następnie z Object Pascalem. Stąd już prosta
droga prowadzi do języka C++.
2
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
PIERWSZY PROGRAM..............................................................4
ZMIENNE .................................................................................7
ZAKRES WIDOCZNOŚCI (WAŻNOŚCI) I ZASŁANIANIE NAZW
INSTRUKCJE STERUJĄCE CZ.1...............................................14
INSTRUKCJE STERUJĄCE CZ.2...............................................18
INSTRUKCJE STERUJĄCE CZ.3...............................................22
COUT CZY PRINTF ?...............................................................26
MANIPULATORY ....................................................................30
FUNKCJE................................................................................34
3
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
ozdział 1 Pierwszy program
W tym rozdziale opisane są elementarne podstawy języka C:
-konstrukcja programu
-konstrukcja funkcji
-importowane bibliotek
Najprostszym programem, który robi cokolwiek jest aplikacja typu "hello world". Jej
zadaniem jest wyświetlenie napisu na ekranie monitora.
#include <stdio.h>
void main(void)
{
printf("hello world");
}
Zacznijmy od ogólnej konstrukcji.
W każdym programie w C++ musimy wyróżnić główną funkcję o nazwie main. To
właśnie ona jest uruchamiana gdy chcemy wykonać program. Część void main(void)
nazywamy nagłówkiem funkcji.
Składa się on z nazwy typu zwracanego przez funkcję, nazwy funkcji i listy argumentów
jakie przyjmuje funkcja. Typ void tak naprawdę oznacza brak typu - nasza funkcja ma
wypisywać na ekranie tylko napis "hello world", nie musi więc zwracać żadnej wartości i
nie potrzebuje żadnych argumentów. Po nagłówku następuje definicja funkcji którą ma
postać
{
//..
//instrukcje
//..
}
Dla ścisłości dodam, że dwa ukośniki (//) oznaczają komentarz - wszystko to co znajduje
się po nich aż do końca linii jest ignorowane przez kompilator.
W naszym programie jest tylko jedna instrukcja printf() służąca do wypisywania różnych
rzeczy na ekranie - opis tej funkcji można znaleźć w pomocy do kompilatora, a
użytkownicy linuksa mogą przeczytać opis każdej instrukcji w manualu (polecenie man
4
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
np. man printf ).
W najprostszej postaci wywołanie funkcji printf wymaga podania jednego parametru -
łańcuha znaków (string) albo zmiennej niekoniecznie typu łańcuchowego.
Zauważmy, że po każdej instrukci stawiamy znak ; (średnik). Taka konwencja zapisu
przyjęła się w bardzo wielu językach np. pascal, java. Po kompilacji i wykonaniu
programu na ekranie wyświetlony zostanie napis hello world (bez cudzysłowów).
Co by się stało gdybyśmy dodali jeszcze jedna linijkę printf("hello world") ?
Otrzymalibyśmy na ekranie napis hello worldhello world. Dlaczego?
Wynika to ze specyfikacji funkcji printf. Po wykonaniu tej funkcji znak kursora nie jest
przenoszony automatycznie do następnej linii. Aby uzyskać pożądany efekt stosujemy
tzw. znaki specjalne. Jednym z nich jest znak łamania linii \n. Otrzymujemy zatem
instrukcję o postaci printf("hello world\n"); która spełni nasze oczekiwania.
Ważnym elementem, o którym do tej pory nie wspomniałem są biblioteki języka C++.
Są to jakby gotowe zestawy funkcji, które możemy wykorzystać w naszych programach.
Jedną z takich bibliotek jest stdio.h, która zawiera funkcję printf. Importowanie biblioteki
polega na zasygnalizowaniu kompilatorowi, że chcemy z niej skorzystać. Istnieją dwa
sposoby zapisy dodania biblioteki do programu:
#include<nazwa_biblioteki>
lub
#include"nazwa_biblioteki"
Na razie wystarczy, że zapamiętasz jeden ze sposobów (o różnicy napiszę przy innej
okazji) i będziesz go używał.
5
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
6
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
ozdział 2 Zmienne
Bez zmiennych trudno sobie wyobrazić działanie jakiegokolwiek programu
komputerowego. Istnieje wiele rodzajów typów zmiennych. Co to jest typ zmiennej ?
Ogólnie mówiąc jest to definicja dotycząca zawartości danej zmiennej. Wiadomo
przecież, że liczby całkowite są przechowywane inaczej w pamięci komputera niż np.
liczby rzeczywiste, inne też są dopuszczalne operacje na tych typach zmiennych.
Programista musi poinformować kompilator ze zmienną jakiego typu ma do czynienia.
Typy można podzielić na:
-podstawowe(fundamentalne)
-pochodne
lub
-wbudowane
-zdefiniowane przez programistę
Najważniejsze typy zmiennych podstawowych to:
a)do reprezentacji liczb całkowitych
Short int, int, long int (różnią się zakresami)
b)do reprezentacji liczb rzeczywistych
float, double, long double (różne dokładności)
c)do reprezentacji znaków
char, wide char
Sposób deklaracji:
Jest on bardzo prosty - składa się z nazwy typu i nazwy zmiennej.
Int I; // deklaracja zmiennej całkowitej i , czytamy „i jest zmienną typu int”
Double x; // x jest zmienną typu double,
Char z; // z jest zmienną typu char.
Mając takie zmienne możemy je wykorzystać w dalszych instrukcjach np.
I = 5; // przypisz zmiennej i wartość 5
I = I + 2; // można tak, gdyż kompilator najpierw oblicza wartość wyrażenia stojącego
po prawej stronie operatora = a następnie przypisuje tę wartość zmiennej stojącej po
lewej stronie; w tym przypadku zwiększamy zmienną I o 2.
z = ’a’ ; przypisanie zmiennej z znaku ’a’
7
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
Oprócz typów podstawowych możemy także tworzyć typy pochodne(w rzeczywistości
nie tworzymy typów pochodnych a tylko definiujemy obiekty pochodne od typów
podstawowych - na razie zapamiętaj tylko, że każda zmienna jest obiektem) . Często
początkujący programiści zadają pytanie czy są one konieczne. Odpowiedź jest prosta -
są niezbędne. Nie tylko ułatwiają pracę, ale również są w niektórych sytuacjach
niezastąpione. Przed wymienieniem tych typów chcę Ci powiedzieć, że na razie
zajmiemy się tylko jednym (pierwszym) z nich a resztę zostawimy sobie na później.
Typy pochodne:
-tablica
-referencja
-wskaźnik
-funkcja
Tablica jest to uporządkowany zbiór zmiennych o tym samym typie. Wyobraźmy sobie,
że potrzebujemy 200 zmiennych typu int. Deklarowanie takiej liczby zmiennych byłoby
samobójstwem nie wspominając o szukaniu nazw dla nich. To samo możemy załatwić
jedną linijką
Int t[200]; // jest to deklaracja tablicy 200 obiektów typu int
A jak się odwoływać do takich obiektów??
W ten sposób:
t[20] = 30; // do 21 elementu tablicy przypisz wartość 30
Nie, nie pomyliłem się, do 21 a nie 20 - wyjaśnia to fakt, że elementy tablicy są
numerowane od 0 a nie od 1. Zatem w naszej tablicy możemy posługiwać się numerami
pól (czyli elementów tablicy) od 0 do 199. Może początkowo być to przyczyną błędów,
ale po pewnym czasie można się do tego przyzwyczaić.
8
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
9
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
ozdział 3 Zakres widoczności
(ważności) i zasłanianie
nazw
Skoro umiesz już deklarować obiekty (zmienne) nie sposób pominąć tematu zasłaniania
(zwanego czasem przesłanianiem) nazw. Aby wyjaśnić co to takiego jest konieczne jest
zdefiniowanie następujących pojęć:
- czas
życia obiektu - jest to czas od momentu powstania obiektu (powołania go do
życia aż do czasu jego zlikwidowania
- zakres
widoczności obiektu - jest to zakres programu, w którym możemy
odwołać-
się do tego obiektu (inaczej mówiąc jest to zakres programu, w
którym kompilator widzi dany obiekt)
Mając dany obiekt musimy zadbać o to aby był on widoczny we wszystkich miejscach, w
których będzie wykorzystywany.
Możemy wyróżnić kilka zakresów ważności:
- zakres lokalny - jeżeli jest ograniczony do pewnego fragmentu programu.
Przykładem może być-
blok instrukcji
{
//...
}
Każda zmienna(obiekt), która jest zadeklarowana wewnątrz takiego bloku jest
znana tylko i wyłącznie w nim. Czas życia obiektu kończy się w momencie końca
bloku instrukcji.
Np.
{
//...
{
int a = 15;
cout << a; #1
}
10
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
cout << a; #2
}
W #1 zostanie wypisana nazwa, ale w #2 jest błąd (taki program się nie
skompiluje).
Obiekt a jest widoczny i istnieje tylko wewnątrz tego bloku instrukcji, w którym
został stworzony. Poza tym blokiem nie ma żadnego obiektu a.
- zakres globalny (pliku) - na razie omawiane programy mieszczą się w jednym
pliku, więc wystarczy zapamiętać- ,
że obiekt zadeklarowany poza obszarem
bloku instrukcji (również bloku funkcji - patrz następny podpunkt) jest widziany w
całym programie (o ile nie zostanie przesłonięty), mówimy, że jest to obiekt
globalny
Np.
int a;
main (void)
{
#1
}
#2
Obiekt a jest obiektem globalnym - jest widziany zarówno w #1 jak i w #2
- zakres
funkcji
taki zakres ważności ma etykieta (wykorzystywana przez instrukcję goto), o
której może wspomnę później, choć jak się przekonasz nie jest ona niezbędna.
Wymieniam ją tutaj tylko ze względu na kompletność informacji
- zakres klasy - nazwa widoczna jest w całej klasie
brak przykładu - będzie gdy już dowiesz się co to jest klasa
Zasłanianie nazw:
Możemy zadeklarować dwa obiekty o tej samej nazwie - jedyny warunek - muszą mieć
inny zakres ważności. Zasłanianie nazw jest bardzo intuicyjne. Jeżeli mamy obiekt
globalny X to zadeklarowanie w pewnym bloku instrukcji obiektu o nazwie X przesłoni
obiekt globalny X.
Oczywiście będzie on cały czas istniał, jednak odwołanie się w tym bloku instrukcji do X
spowoduje odwołanie się do obiektu X zadeklarowanego w tym bloku. Można także
odwołać się do obiektu globalnego - z pomocą przychodzi nam operator zakresu ::,
który umieszcamy przed interesującą nas zmienną.
Zastanów się nad wynikiem działania tego programu:
Wskazówka: instrukcja cout wyrzuca napisy na ekran, zapis cout << x << endl; jest
11
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
równoważny następującemu: cout << x; cout << endl; gdzie endl do znak końca linii
(END Line).
Przykład:
#include <iostream.h>
int x = 5;
void main(void)
{
cout << x << endl;
int x = 10;
{
int x =15;
cout << x <<endl;
}
cout << x << endl;
cout << ::x << endl;
}
Program wypisz na ekranie:
5
15
10
5
Jeżeli zgadza się to z twoimi przewidywaniami to gratuluję - zrozumiałeś ten rozdział.
12
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
13
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
ozdział 4 Instrukcje sterujące cz.1
Przejdę teraz do opisu tzw. instrukcji sterujących bez których nie ma mowy o napisaniu
jakiegokolwiek bardziej złożonego programu. Na początku mogą się one wydawać nieco
skomplikowane ale po pewnym czasie nabierzesz takiej wprawy, że będą ci się one
wydawały zupełnie naturalne i nie będziesz na nie zwracał uwagi(co często prowadzi do
trudnych do wykrycia błędów).
Instrukcja if ...
Instrukcja if ... służy do sprawdzenia warunku, a następnie wykonania, bądź
niewykonania kolejnych instrukcji. Jej postać jest następująca:
if (wyrażenie)
{
//instrukcja/e
}
Jeżeli wyrażenie jest spełnione to instrukcje w zamknięte w klamrach są wykonywane.
Czym jest wyrażenie?
Tutaj wiele zależy od nas samych. W skrajnym przypadku może to być jedna zmienna i
to niekoniecznie typu bool. Otóż w C++ za prawdę uważa się wszystko co jest różne od
zera. Zatem liczba int o wartosci 1 jest w tym wypadku traktowana jako prawda. Nas
zapis wyglądałby np. tak:
int liczba_int=1;
if (liczba_int)
printf("prawda");
po wykonaniu tych instrukcji zobaczylibyśmy na ekranie napis "prawda"
Podobnie jest w przypadku następującego programu
int liczba_int;
//...
if (liczba_int>0)
printf("prawda")
Napis prawda ukaże się nam gdy liczba_int jest większa od zera.
A co zrobić gdy chcemy sprawdzić czy liczba znajduje się w danym zakresie? np. czy jest
14
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
większa od 5 ale mniejsza od 10?
Można to zrobić tak:
if (liczba_int>5)
if (liczba_int<10)
printf("liczba nalezy do przedziału (5,10)");
Jest to jednak mało eleganckie i bardzo niepraktyczne rozwiązanie. Łatwo sobie
wyobrazić co by było gdybyśmy mieli do sprawdzenia np. 10 warunków...
Z pomocą przychodzą nam wyrażenia złożone. Jak sama nazwa wskazuje składają się
one z kilku części. Przykład :
if ( (liczba_int>5) && (liczba_int<10) )
printf("liczba nalezy do przedziału (5,10)");
Tutaj widzimy, że sprawdzane są dwa warunki. Połączeniem jest symbol && zwany
operatorem koniunkcji. Aby wyrażenie było prawdziwe obie jego części muszą być
prawdziwe. Innym często stosowanym operatorem jest alternatywa ||. Aby takie
wyrażenie było spełnione wystarczy, że jedna ze stron jest spełniona. Pełny opis
operatorów logicznych znajduję się w dodatku B.
Pętle
Instrukcja for
Czy nie zastanawiałeś się np. jak wypełnić tablicę, powiedzmy, kolejnymi liczbami
naturalnymi począwszy od jeden.
Załóżmy, że naszą tablicą jest tablica o nazwie Liczby o następującej deklaracji
int Liczby[10];
Przypominam, że elementy są numerowane od zera.
Można nasze zadanie wykonać tak:
Liczby[0]=1;
Liczby[1]=2;
....
Liczby[9]=10;
No tak, powiesz, że proste. Wyobraź sobie teraz tablicę o 100 tysiącach elementów.
Trudne ??
Oczywiście, że nie. Stosujemy instrukcję for.
Nasz programik wyglądałby następująco:
for (int i=0; i<100000; i=i+1)
{
Liczby[i]=i+1;
15
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
}
A teraz komentarz:
Instrukcja for ma postać :
for (zmienna sterująca=stan początkowy ; warunek wykonywania ; operacja sterująca)
{
//instrukcje
}
Naszą zmienną sterującą jest w tym przypadku zmienna i. Początkowo ma wartość
równą 0. Warunkiem wykonywania jest wyrażenie i<100000. Należy to rozumieć w
następujący sposób. Dopóki zmienna i jest mniejsza od 100000 wykonuj zadanie. W
momencie gdy zmienna i jest większa lub równa 100000 przestań wykonywać ciało pętli
(czyli instukcje w niej zawarte). Ostatnim polem jest operacja sterująca. Mówi ona co po
każdym wykonaniu pętli ma być wykonane ze zmienną sterującą. W naszym przypadku
jest to zwiększenie o 1.
UWAGA!!! Podkreślam, że operacja(instrukcja) sterująca jest wykonywana na koniec
każdego wykonania pętli.
Przytoczony programik jest najprostszym przykładem użycia pętli for. Uwierz mi już
teraz – ta pętla jest najczęściej wykorzystywana we wszystkich programach, wkrótce
sam się o tym przekonasz.
16
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
17
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
ozdział 5 Instrukcje sterujące cz.2
Jeżeli już zapoznałeś się z poprzednimi instrukcjami pora przejść do kolejnych. Będą to
również pętle. Jak to, pętle już były powiesz. Rzeczywiście, jednak instrukcja for nie
zawsze jest najlepszym rozwiązaniem. W niektórych przypadkach znacznie łatwiej jest
używać innych instrukcji.
Instrukcja while ...
Jej postać to
while (warunek)
{
// instrukcje
}
Instrukcja while działa tak długo, jak spełniony jest warunek. Zauważ, że jeżeli warunek
nie jest spełniony na początku pętla nigdy się nie wykona. Jest to bardzo ważna uwaga i
radzę Ci byś dobrze ją zapamiętał. Aby lepiej zrozumieć instrukcję while przeanalizujmy
następujący program
#include „iostream.h”
void main(void)
{
int wysokosc_trojkata=10;
while
(wysokosc_trojkata>0)
{
for
(int
licznik=0;
licznik<wysokosc_trojkata;licznik++)
cout << '*' ;
cout
<<
endl;
wysokosc_trojkata--;
}
}
Na wstępie już wyjaśniam co robi cout (console out). Jest to instrukcja, która została
wprowadzona w C++ w celu ułatwienia wyprowadzania znaków na ekran. Aby ją
wykorzystać należy dodać bibliotekę iostream.h . Poprzednio używałem w przykładach
18
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
instrukcji printf, jednak dobrze abyś wiedział, ze nie jest to jedyny sposób wypisywania
napisów (ponadto printf pochodzi jeszcze z języka C ). Instrukcję cout wywołujemy z
jednym lub więcej parametrami.
cout << „hello”
wypisze na ekranie hello
cout << endl
spowoduje, że zostanie wypisany znak końca linii (czyli nastąpi
przejście do nowej linii)
Dodam, że endl to skrót od ENd Of Line a w wyświetlanym ciągu można używać również
znaków specjalnych.
Tyle dygresji na temat cout. Wracając do naszej pętli czy wiesz już co pojawi się na
ekranie??
Będzie to trójkąt złożony z gwiazdek, dokładnie taki:
**********
*********
********
*******
******
*****
****
***
**
*
Prześledźmy działanie programu krok po kroku.
/* ta linia definiuje i inicjalizuje zmienna przypisując jej wartość 10; */
int wysokosc_trojkata=10;
/* dopóki zmienna jest większa od zera wykonujemy ciało pętli */
while (wysokosc_trojkata>0)
{
/* Wypisujemy tyle gwiazdek ile wynosi zmienna wysokosc_licznika */
for (int licznik=0; licznik<wysokosc_trojkata;licznik++)
cout << '*' ;
/* przechodzimy do nowej linii */
cout
<<
endl;
/* zmniejszamy wysokość trójkąta o1*/
wysokosc_trojkata--;
}
Na początku zmienna wysokosc_trojkata ma wartość 10. Jest > 0 czyli wchodzimy do
pętli while.
Tam wypisujemy za pomocą pętli for 10 gwiazdek. Po zakończeniu pętli for
przechodzimy do nowej linii. Zmniejszamy wysokosc_trojkata o 1. ( gdyby tej instrukcji
nie było program działałby w nieskończonej pętli). Wracamy do warunku pętli while.
Teraz zmienna wysokosc_trojkata ma wartość 9 nadal jest więc większa 0 – znowu
19
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
wykonujemy ciało pętli. Widać, że będzie tak się działo dopóki zmienna
wysokosc_trojkata nie będzie miała wartości 0. Wówczas pętla while się zakończy.
Mam nadzieję, że dobrze wyjaśniłem działanie tego programu.
Najważniejszą rzeczą, którą trzeba zapamiętać to to, że warunek pętli while jest
sprawdzany na początku. Dlaczego?
Otóż jest jeszcze jeden typ pętli, który różni się tylko momentem, w którym sprawdzany
jest warunek wykonania. Jest to pętla do ... while.
Instrukcja do ... while
Jej działanie jest prawie identyczne jak w przypadku instrukcji while... . Najważniejszą
różnicą jest to, że warunek sprawdzany jest na końcu. Niesie to za sobą bardzo ważne
konsekwencje – pętla zostanie ZAWSZE wykonana przynajmniej jeden raz.
Jeżeli poprzedni program nieco zmodyfikujemy(zamieniamy while... na do...while) :
#include "iostream.h"
void main(void)
{
int
wysokosc_trojkata=10;
do
{
for
(int
licznik=0;
licznik<wysokosc_trojkata;licznik++)
cout << '*' ;
cout
<<
endl;
wysokosc_trojkata--;
}
while
(wysokosc_trojkata>0);
}
Wynik będzie identyczny.
Ale zauważ, że o ile taki program
#include „iostream.h”
void main(void)
{
int wysokosc_trojkata=0;
do
{
for
(int
licznik=0;
licznik<wysokosc_trojkata;licznik++)
20
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
cout << '*' ;
cout
<<
endl;
wysokosc_trojkata--;
}
while (wysokosc_trojkata>0)
}
nie wypisałby na ekranie nic, to taki (z pętla while):
wypisałby znak końca linii.
Jest to spowodowane tym, że warunek (wysokosc_trojkata>0) jest sprawdzany na
końcu, po przejściu pętli.
21
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
ozdział 6 Instrukcje sterujące cz.3
Znowu instrukcje sterujące?! zapytasz. Spokojnie, to już ostatni rozdział na ich temat.
Tym razem zajmiemy się instrukcją switch, goto, break, continue.
Instrukcja switch
Wyobraź sobie następującą sytuację:
Masz zrobić menu w trybie tekstowym, które będzie sterowane za pomocą
wczytywanych liczb np.
1) Nowa baza
2) Dodaj element
3) Usun element
4) Koniec
Program ma pobierać numer komendy z klawiatury i wykonywać odpowiednią akcję.
Pomijając kwestię wczytywania z klawiatury, dotychczas omówione instrukcje pozwalają
na rozwiązanie tego zadania w następujący sposób:
int NumerKomendy;
// Deklaracja zmiennej, w której będzie przechowywany numer
komendy
cout << „Podaj numer komendy:”;
// Wypisanie komunikatu
cin >> NumerKomendy;
// Pobranie numeru z klawiatury
if ( NumerKomendy == 1 )
{
// ... Tutaj odpowiedni kod odpowiadający za utworzenie nowej bazy
}
if (NumerKomendy == 2 )
{
// ... Tutaj odpowiedni kod odpowiadający za dodanie elementu
}
...itd.
Mało efektywne i dużo trzeba pisać.
W takiej sytuacji niezastąpiona jest instrukcja switch. Jak sama nazwa wskazuje pełni
ona rolę przełącznika.
22
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
Jej składnia jest następująca:
switch (ZmiennaSterujaca)
{
case wartosc : //instrukcje
break;
}
W naszym przypadku odpowiedni byłby taki kod:
int NumerKomendy;
cout << „Podaj numer komendy:”;
cin >> NumerKomendy;
switch ( NumerKomendy )
{
case 1 :
// ... Tutaj odpowiedni kod odpowiadający za utworzenie nowej bazy
break;
case 2 :
// ... Tutaj odpowiedni kod odpowiadający za dodanie elementu
break;
case 3 :
// ... Tutaj odpowiedni kod odpowiadający za usuniecie elementu
break;
case 4 :
// ... Tutaj odpowiedni kod odpowiadający za wyjscie
break;
default : cout << “Zla komenda”;
break;
}
Wydaje się, że jest to bardzo intuicyjne. Jako parametr switch podajemy zmienną, której
wartość wpływa na wykonywane akcje. Następnie po case podajemy wartość. Jeżeli jest
ona taka sama jak wartość zmiennej sterującej to zostanie wykonana akcja. Ich
wykonywanie kończy się po napotkaniu instrukcji break. Jeżeli żadna wartość nie jest
taka sama jak wartość zmiennej to wykonana zostanie akcja zdefiniowana jako default
(domyślny).
UWAGA! Dopasowanie powoduje wykonanie wszystkich akcji następujących po
napotkaniu pasującego case’a aż do napotkania instrukcji break lub końca instrukcji
switch.
Np.
Wykonanie poniższego programu
int Numer = 2;
// deklaracja zmiennej Numer i nadanie jej wartości 2
switch(Numer)
{
case 1: cout << “A\n”;
brak;
case 2: cout << “B\n”;
case 3: cout << “C\n”;
23
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
break;
}
spowoduje wypisanie na ekranie BC ani samego C. Zauważ, że dedfinicja akcji
domyślnej (default) nie jest konieczna.
Instrukcje break, continue, goto.
Z instrukcją break spotkaliśmy się już w poprzednim paragrafie. Powoduje ona
natychmiastowe zakończenie wykonywania instrukcji i można ją stosować również w
pętlach for, while, do...while. Jeżeli mamy do czynienia z pętlami zagnieżdżonymi to
wywołanie instrukcji break spowoduje zakończenie tej, w której się bezpośrednio
znajduje.
Instrukcja continue powoduje przerwane wykonywania pętli w danym przebiegu i
rozpoczęcie wykonywania następnego przebiegu (nie ma więc sensu stosowanie jej w
instrukcji switch – tam jest jeden przebieg) np.
int Licznik;
for (Licznik=1; Licznik<10; Licznik++)
{
cout << ”A”;
if (Licznik>5)
continue;
cout <<”B”;
}
da w wyniku napis na ekranie:
ABABABABAAAAAA
Instrukcja goto
Wiele osob pomija albo pragnie pominąć tę funkcję. Jej działanie polega na skoku do
pewnego określonego miejsca zaznaczonego etykietą. Mówi się, że stosują ją tylko źli
programiści ale ja uważam, że są sytuacje gdy użycie goto jest wskazane np. przy
natychmiastowym opuszczaniu wielokrotnie zagnieżdżonych pętli. Można sobie bez niej
poradzić ale program byłby wtedy znacznie mniej czytelny. Ale pamiętaj : używaj jej w
ostateczności.
Przykład:
cout <<”poczatek\n”;
goto Etykieta1;
cout << ”tego nie wypisze”;
Etykieta1: cout << ”koniec\n”;
Wynik to oczywiście:
poczatek
24
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
koniec
25
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
ozdział 7 Cout czy printf ?
O tych dwóch instrukcjach już wspomniałem wcześniej. Jak już wiesz, służą one do
wypisywania napisów na ekranie. Ponieważ jeszcze przez dość długi czas omawiane
przykłady będą opierały się na trybie dosowym postanowiłem dokładniej omówić te
funkcje.
Printf
Jest to funkcja znajdująca się w bibliotece stdio.h – aby z niej skorzystać musisz dodać
na początku kodu:
#include ”stdio.h”
Jej składnia wygląda następująco:
printf(const char *format[, argument, ...]);
Wygląda to paskudnie więc już tłumaczę. Parametrem tej funkcji jest zawsze ciąg
znaków (może być pusty). Ciągi znaków zawsze zapisujemy w cudzysłowach. Może być
zatem następujące wywołanie:
printf(”To trzeba wypisac”);
Na ekranie pojawi się napis: to trzeba wypisac
Jak wspomniałem ciąg może być pusty, zatem poprawnie jest także wywołanie
printf(””);
W tym przypadku nic nie zostanie wypisane.
Jest jednak coś, co sprawia, że ta funkcja jest bardzo wygodna w użyciu. Są to tzw.
Specyfikatory formatu ( ang. format specifiers). Nie będę tu omawiał wszystkich
ponieważ jest ich zbyt dużo a wiele z nich pewnie nigdy nie użyjesz. Warto skupić się
jednak na najważniejszych, czyli tych, które najczęściej są używane.
Co to jest specyfikator formatu?
Jest to wyrażenie, które określa format wyświetlanej informacji. Specyfikatory formatu
zawsze są podawane w ciągu znaków i zaczynają się od znaku %.
Myślę, że najlepiej będzię wytłumaczyć to na prostym przykładzie.
Załóżmy, że mamy jakąś zmienna wynik typu integer i chcemy wyświetlić ją na ekranie.
Umożliwia to właśnie funkcja printf a wygląda to tak:
int wynik;
wynik = 2*4+2;
printf(”W zmiennej wynik przechowywana jest wartosc = %i ”,wynik);
26
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
Na ekranie ukaże się napis:
W zmiennej wynik przechowywana jest wartosc = 10
A teraz opis działania.
Jak zapewne widzisz w wywołaniu funkcji printf mamy ciąg znaków oraz zmienną wynik
( po przecinku). Tutaj, choć dopiero funkcje zostaną omówione w następnych
rozdziałach, muszę już zapowiedzieć, że przy wywołaniu funkcji można użyć od zera do
n argumentów. Jeżeli wywołujemy funkcje z więcej niż jednym argumentem to musimy
je rozdzielić przecinkami.
Właśnie w naszym przypadku jest taka sytuacja. Funkcja printf jest wywoływana z
dwoma argumentami – zatem wywołanie ma postać printf( argument1, argument 2).
Wracając do specyfikatorów formatu – zauważ, że pierwszym argumentem jest, tak jak
to było do tej pory, ciąg znaków (czyli string). Różni się on tylko tym, że w jego wnętrzu
mamy znak % a po nim literkę „i”. Tutaj tkwi właśnie cała tajemnica. Literka „i” to skrót
od angielskiego integer czyli typu zmiennej, który zadeklarowaliśmy. Taki zapis mówi
kompilatorowi, że chcemy aby została wyświetlona dana w postaci integer. Tą daną jest
zmienna wynik i dlatego umieszczamy ją jako drugi argument. Oczywiście można użyć
większej ilości zmiennych i nie muszą to być zmienne typu integer.
Przykład:
int zmienna1, zmienna2; // deklarujemy dwie zmienne typu integer
zmienna1 = 14;
zmienna2 = zmienna1 / 2; // zmienna2 to polowa ze zmiennej1
printf(” zmienna 1 = %i \n zmienna 2 = %i ”, zmienna1, zmienna2);
Wynik to:
zmienna 1 = 14
zmienna 2 = 7
W powyższym programie mamy trzy parametry w wywołaniu printf. Jest to
spowodowane faktem, że zastosowaliśmy dwa specyfikatory formatu – musieliśmy
dodać do nich zmienne.
Zawsze specyfikatory czytamy od lewej do prawej i podstawiamy za nie kolejne
argumenty, które są wymienione we funkcji printf.
UWAGA!!! Nie możemy podać za małej ilości argumentów. Choć program się skompiluje
bez błędów to wynik będzie zły – w miejscu „niepokrytych” specyfikatorów zostaną
wstawione dziwne liczby. Możesz sam to sprawdzić. Odwrotna sytuacja tzn. jest więcej
argumentów za stringiem niż specyfikatorów w stringu nie spowoduje żadnych błędów
wyświetlania – nie zostaną wykorzystane wszystkie argumenty.
Specyfikatory mają rozmaite właściwości i zastosowanie. Za ich pomocą można np.
określić liczbę miejsc po przecinku wyświetlanej liczby albo sposób zaokrąglania liczb
itd...
27
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
Pełną listę specyfikatorów możesz znaleźć w dodatku B.
Cout
Jest to funkcja znajdująca się w bibliotece iostream.h – aby z niej skorzystać musisz
dodać na początku kodu:
#include ”iostream.h”
Funkcja cout jest jedną z tzw. Funkcji strumieniowych ( ang. stream – strumień).
Strumień to dane „płynące” od źródła do celu np. z klawiatury na ekran. Funkcja cout
zostałą wprowadzona dopiero w języku C++ ( printf było już w C ). Jej użycie w wielu
przypadkach jest znacznie wygodniejsze od zastosowania printf , przede wszystkim
wtedy, gdy mamy do wyświetlenia dużą liczbę zmiennych. Jej użycie jest bardzo proste
np.
cout << ”Na ekran \n”;
Jak widać można w niej używać także symboli specjalnych ( patrz dodatek A), tutaj
mamy \n czyli znak nowej linii. Możliwe jest również takie wywołanie:
cout << ”napis1” << ”napis2”;
Funkcja wypisze na ekranie:
napis1napis2
A jak wygląda wyprowadzanie na ekran wartości zmiennych ?
Bardzo prosto. Rozważmy przykład omawiany przy funkcji printf.
Dla przypomnienia :
int zmienna1, zmienna2; // deklarujemy dwie zmienne typu integer
zmienna1 = 14;
zmienna2 = zmienna1 / 2; // zmienna2 to polowa ze zmiennej1
printf(” zmienna 1 = %i \n zmienna 2 = %i ”, zmienna1, zmienna2);
Wynik to:
zmienna 1 = 14
zmienna 2 = 7
Napiszmy to samo z zastosowaniem cout.
Przykład:
int zmienna1, zmienna2; // deklarujemy dwie zmienne typu integer
zmienna1 = 14;
zmienna2 = zmienna1 / 2; // zmienna2 to polowa ze zmiennej1
cout <<” zmienna 1 = ” <<zmienna1 << ”\n zmienna 2 = ”<< zmienna2;
Wynik to:
28
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
zmienna 1 = 14
zmienna 2 = 7
Jak widać wyprowadzenie zmiennej na ekran jest bardzo proste. Wystarczy napisać :
cout << zmienna1;
A co z formatowaniem wyjścia ??
Tutaj NIE możemy zastosować żadnych specyfikatorów typu. Istnieją jednak tzw.
manipulatory ale o tym w następnym rozdziale.
29
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
ozdział 8 Manipulatory
Manipulatory to specjalne rozkazy, które „wrzucamy” do strumienia. W łatwy sposób
umożliwiają formatowanie strumienia.
Przykład.
Wiesz już, że możemy wyświetlić tekst w taki sposób:
cout << ”jakiś tekst”;
A co gdybyśmy chcieli wyświetlić w postaci heksadecymalnej zmienną?
Wystarczy, że napiszemy
cout << hex << nazwa_zmiennej;
W tym przypadku manipulatorem jest hex, który „mówi” strumieniowi, że dane mają być
wyświetlane w postaci heksadecymalnej. Warto zauważyć, że manipulatory nie są
wyświetlane na ekranie.
Wyróżniamy manipulatory bezargumentowe i argumentowe czyli, ładnie mówiąc po
polsku, parametryzowane. Omówię osobno każdy z manipulatorów.
Manipulatory bezargumentowe.
1. Manipulator ws.
Skrót pochodzi od angielskiego white spaces czyli białe znaki. Powoduje on
przeskoczenie wszystkich tzw. białych znaków takich jak np. tabulatory, spacje itp.
2. Manipulator ends.
Powoduje wstawienie znaku końca napisu (NULL) (z ang. end of string – koniec
napisu). Stosowany przeważnie gdy wypisujemy coś nie na ekran, lecz np. do pliku ,
czy też do tablicy znaków – odpowiednika typu string z Pascala(uwaga dla
wtajemniczonych).
3. Manipulator endl.
Jest to chyba najczęściej wykorzystywany manipulator. Jak sama nazwa wskazuje (z
ang. end of line – koniec linii) jego wstawienie powoduje zakończenie linii np.
cout << ”jestem wspaniały” << endl << „ i wielki.”;
Da w rezultacie napis:
Jestem wspaniały
30
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
i wielki.
4. Manipulatory oct, dec, hex.
Te trzy manipulatory mają bardzo podobne działanie. Ich zadaniem, jak zapewne się
domyślasz, jest formatowanie liczb.
oct – ustawia formatowanie na tryb oktalny(ósemkowy),
dec - ustawia formatownie na tryb dziesiętny,
hex – ustawia formatowanie na tryb heksadecymalny.
Takie manipulatory ułatwiają do maksimum zmianę formatu wyświetlanych liczb np.
cout << dec << nazwa_zmiennej << ” a ósemkowo = ” << oct <<
nazwa_zmiennej << ”a heksadecymalnie = ” << hex << nazwa_zmiennej;
5. Manipulator flush.
Strumień danych może być buforowany. Oznacza to, że dane nie trafiają natychmiast
po wysłaniu do celu, lecz są przechowywane w specjalnej pamięci zwanej buforem,
czyli jakby ”poczekalnią” a dopiero potem przesyłane dalej. Manipulator flush
stosujemy wówczas, gdy chcemy natychmiastowo opróżnić bufor. Jest to przydatne
szczególnie podczas debugowanie programów, gdy chcemy na bieżąco śledzić to co
dzieje się w programie.
Manipulatory argumentowe (parametryzowane).
1. Manipulator setprecision.
Wywołanie tego manipulatora ma postać setprecision(int), gdzie int w nawiasie
oznacza liczbę typu całkowitego. Przy pominięciu manipulatora domyślnie
zostanie przyjęta szóstka. Manipulator setprecision, jak sama nazwa wskazuje,
pozwala na ustalenie precyzji z jaką wyświetlana jest liczba zmiennoprzecinkowa.
Przykład:
#include ”iostream.h”
int main(void)
{
double x = 2333.123456789; // deklaracja i definicja zmiennej x
cout << x << endl;
// wykorzystujemy manipulator endl
cout << setprecision(3) << x << endl << setprecision(10) << x;
return 0;
}
Wynik:
2333.123456
2333.123
2333.1234567890
2. Manipulator setbase.
Jest to jakby odpowiednik manipulatorów bezargumentowych hex, bin, oct.
Wywołanie ma postać setbase(int) gdzie wartość zmiennej int określa rodzaj
systemu liczenia.
31
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
Przykład:
#include ”iostream.h”
int main(void)
{
int x = 134;
// deklaracja i definicja zmiennej x
cout << x << endl; // wykorzystujemy manipulator endl
cout << setbase(2) << x << endl << setbase(8) << x;
return 0;
}
Wynik:
134
10000110
206
Jak widać manipulatory np. hex i setbase(16) są sobie równoważne.
Uwaga: Jeżeli ustawimy setbase(0) to dla strumienia wyjściowego zostanie
przypisany system dziesiętny a dla strumienia wejściowego nie zostanie
przypisany żaden konkretny system. Konwersja będzie się odbywać na podstawie
formatu wprowadzanej liczby. (Np. zapis 0x2345 sugeruje, że mamy do czynienia
z liczbą heksadecymalną).
3. Manipulator setfill. - cdn
4. Manipulator setw. - cdn
UWAGA !!! Aby użyć manipulatorów parametryzowanych musisz dodać bibliotekę
”iomanip.h”.
32
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
33
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
ozdział 9 Funkcje
W poprzednich rozdziałach, w niektórych miejscach, pojawiły się zapisy funkcji. Celowo
zwlekałem z wprowadzeniem tego pojęcia aż do tego rozdziału. Wynika to z chęci
jednoczesnego wprowadzenia pojęcia funkcji oraz metody i wyjaśnienia różnicy między
tymi pojęciami. Do tego celu potrzebne będzie omówienie podstaw obiektowości, która
dotyczy nie tylko języka C++.
Wracając do pojęcia samej funkcji. Można powiedzieć, że jest to wydzielona część kodu
realizująca określone zadanie. Oczywiście ktoś może powiedzieć, że funkcja może nic nie
robić, więc nie realizuje też żadnego zadania. To prawda, jednak taki funkcje są
rzadkością i bywają wykorzystywane tylko w nielicznych przypadkach i to w sytuacjach
bardzo nietypowych. W swoich programach powinieneś/aś unikać takich funkcji, chyba
że stanowią one pewien etap przejściowy.
Podstawowy format funkcji w języku C++ wygląda następująco:
Parametr_zwracany nazwa_funkcji(argumenty funkcji)
{
ciało funkcji
}
Parametr zwracany – jest to typ zwracanego przez funkcję wyniku. Być może samo
sformułowanie „zwracanie wyniku” jest niezbyt eleganckie ale bardzo często jest
wykorzystywane przez programistów. Oznacza ono przekazanie wyliczonego wyniku do
miejsca w programie, gdzie ta funkcja została wywołana.
Nazwa funkcji – funkcję identyfikujemy przez jej nazwę – uwaga – nie może zaczynać
się od cyfr oraz być słowem zastrzeżonym języka C, ważna jest wielkość liter.
Argumenty – lista oddzielonych przecinkiem argumentów funkcji, czyli tego co chcemy
funkcji przekazać.
Przykład:
int multiple(int a, int b)
{
int
amulb;
amulb = a * b;
result
amulb;
34
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
}
Powyższy fragment kodu to funkcja o nazwie multiple, która mnoży przez siebie dwie
liczby podane na wejściu i zwraca obliczoną liczbę jako wynik swojego działania.
Zwrócenie następuje przez zapis result co_zwrócić. Należy pamiętać, że zwrócić można
tylko taką zmienną jaka została zadeklarowana w nagłówku funkcji.
Warto też dodać, że powyższą funkcję można znacznie uprościć.
int multiple(int a, int b)
{
result a * b;
}
Jak widać, nie trzeba specjalnie tworzyć zmiennej, którą chcemy zwrócić, kompilator
zadba o to sam.
Jak użyć takiej funkcji ?
Najlepszą ilustracją będzie kolejny przykład.
#include ”stdio.h”
int multiple(int a, int b)
{
result a * b;
}
void main(void)
{
int
a;
int
b;
a = 5;
b = 7;
int
c;
c = multiple(a,b);
printf(”Obliczona
wartośc %i\n”,c);
// ten sam efekt
printf(”Krocej to samo %i\n”,multiple(5,7));
}
Wynik:
Obliczona wartość 35
Krócej to samo 35
Komentarz:
Definicja funkcji znajduje się na początku programu, zaraz po sekcji include. Następnie
jest zapis
35
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
void main(void) – czy zauważyłeś podobieństwo do funkcji? Tak, jest to funkcja, ale
bardzo specyficzna. Praktycznie każdy program musi ją mieć. Jak widać, zamiast
argumentów i zwracanego typu widnieje napis „void”. Najprościej mówiąc jest to „nic”.
Inaczej – zapis:
main()
{
//...
}
będzie działał w większości kompilatorów równie dobrze (Czasami wymagane jest
wstawienie void – w zależności od używanego kompilatora).
Funkcja main to miejsce w którym rozpoczyna się działanie programu. Zaraz po
uruchomieniu następuje wywołanie tej funkcji (automatyczne – sami nie możemy jej
wywołąć!!!) i przetwarzanie kolejnych rozkazów. Pominięte zostają wszelkie
wcześniejsze struktury, nawet jeżeli znajdują się przed funkcją main.
Kolejno zostają zadeklarowane dwie zmienne typu int, przypisane im wartości,
deklaracja kolejnej zmiennej dla przechowania wyniku a następnie wywołanie funkcji.
Jako argumentów używamy wcześniej zdefiniowanych zmiennych(a,b) a wynik
przypisujemy do zmiennej c. Zapis
C = multiple(a,b);
oznacza, że to co zostało wyliczone przez multiple (czyli to co zwraca ta metoda) zostaje
przypisane do zmiennej c. Pamiętaj, że przetwarzanie rozpoczyna się od prawej strony,
zatem najpierw zostaje wyliczona funkcja, potem jest przypisanie.
Taki sam efekt działania programu można uzyskać bez deklarowania jakichkolwiek
zmiennych. Jest to dobre tylko w przypadku, gdy zmienne te nie byłyby potrzebne w
dalszej części programu.
Uwaga: deklaracja funkcji powinna być przed miejscem jej wywołania ! Oznacza to, że
gdybyśmy definicję multiple wstawili po funkcji main, kompilator wyrzuciłby bład.
36
Kurs języka C++ www.kurs-cpp.prv.pl
Paweł Boiński
Dodatek A
Funkcja Symbol
Nazwa
C+
Nowy wiersz
Tabulacja pozioma
Tabulacja pionowa
O jeden znak do tyłu
Powrót karetki
Nowa strona
Lewy ukośnik
Pytajnik
Liczba ósemkowa
Liczba szesnastkowa
Apostrof
Cydzysłów
NL
HT
VT
BS
CR
FF
\
?
ooo
hhh
‘
“
\n
\t
\v
\b
\r
\f
\\
\?
\ooo
\xhhh
\’
\“
37